Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: webrtc/modules/video_coding/video_codec_initializer.cc

Issue 2488833004: Reland of Issue 2434073003: Extract bitrate allocation ... (Closed)
Patch Set: Rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/video_coding/include/video_codec_initializer.h"
12
13 #include "webrtc/base/basictypes.h"
14 #include "webrtc/common_video/include/video_bitrate_allocator.h"
15 #include "webrtc/common_types.h"
16 #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h"
17 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
18 #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h"
19 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
20 #include "webrtc/system_wrappers/include/clock.h"
21
22 namespace webrtc {
23
24 struct ScreenshareTemporalLayersFactory : webrtc::TemporalLayersFactory {
25 ScreenshareTemporalLayersFactory() {}
26 virtual ~ScreenshareTemporalLayersFactory() {}
27
28 virtual webrtc::TemporalLayers* Create(int simulcast_id,
29 int num_temporal_layers,
30 uint8_t initial_tl0_pic_idx) const {
31 webrtc::TemporalLayers* tl = new webrtc::ScreenshareLayers(
32 num_temporal_layers, rand(), webrtc::Clock::GetRealTimeClock());
33 if (listener_)
34 listener_->OnTemporalLayersCreated(simulcast_id, tl);
35 return tl;
36 }
37 };
38
39 bool VideoCodecInitializer::SetupCodec(
40 const VideoEncoderConfig& config,
41 const VideoSendStream::Config::EncoderSettings settings,
42 const std::vector<VideoStream>& streams,
43 VideoCodec* codec,
44 std::unique_ptr<VideoBitrateAllocator>* bitrate_allocator) {
45 *codec = VideoEncoderConfigToVideoCodec(
46 config, streams, settings.payload_name, settings.payload_type);
47
48 std::unique_ptr<TemporalLayersFactory> tl_factory;
49 switch (codec->codecType) {
50 case kVideoCodecVP8: {
51 if (!codec->VP8()->tl_factory) {
52 if (codec->mode == kScreensharing &&
53 codec->numberOfSimulcastStreams == 1 &&
54 codec->VP8()->numberOfTemporalLayers == 2) {
55 // Conference mode temporal layering for screen content.
56 tl_factory.reset(new ScreenshareTemporalLayersFactory());
57 } else {
58 // Standard video temporal layers.
59 tl_factory.reset(new TemporalLayersFactory());
60 }
61 codec->VP8()->tl_factory = tl_factory.get();
62 }
63 break;
64 }
65 default: {
66 // TODO(sprang): Warn, once we have specific allocators for all supported
67 // codec types.
68 break;
69 }
70 }
71 *bitrate_allocator = CreateBitrateAllocator(*codec, std::move(tl_factory));
72
73 return true;
74 }
75
76 std::unique_ptr<VideoBitrateAllocator>
77 VideoCodecInitializer::CreateBitrateAllocator(
78 const VideoCodec& codec,
79 std::unique_ptr<TemporalLayersFactory> tl_factory) {
80 std::unique_ptr<VideoBitrateAllocator> rate_allocator;
81
82 switch (codec.codecType) {
83 case kVideoCodecVP8: {
84 // Set up default VP8 temporal layer factory, if not provided.
85 rate_allocator.reset(
86 new SimulcastRateAllocator(codec, std::move(tl_factory)));
87 } break;
88 default:
89 rate_allocator.reset(new DefaultVideoBitrateAllocator(codec));
90 }
91
92 return rate_allocator;
93 }
94
95 // TODO(sprang): Split this up and separate the codec specific parts.
96 VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
97 const VideoEncoderConfig& config,
98 const std::vector<VideoStream>& streams,
99 const std::string& payload_name,
100 int payload_type) {
101 static const int kEncoderMinBitrateKbps = 30;
102 RTC_DCHECK(!streams.empty());
103 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
104
105 VideoCodec video_codec;
106 memset(&video_codec, 0, sizeof(video_codec));
107 video_codec.codecType = PayloadNameToCodecType(payload_name)
108 .value_or(VideoCodecType::kVideoCodecGeneric);
109
110 switch (config.content_type) {
111 case VideoEncoderConfig::ContentType::kRealtimeVideo:
112 video_codec.mode = kRealtimeVideo;
113 break;
114 case VideoEncoderConfig::ContentType::kScreen:
115 video_codec.mode = kScreensharing;
116 if (streams.size() == 1 &&
117 streams[0].temporal_layer_thresholds_bps.size() == 1) {
118 video_codec.targetBitrate =
119 streams[0].temporal_layer_thresholds_bps[0] / 1000;
120 }
121 break;
122 }
123
124 if (config.encoder_specific_settings)
125 config.encoder_specific_settings->FillEncoderSpecificSettings(&video_codec);
126
127 switch (video_codec.codecType) {
128 case kVideoCodecVP8: {
129 if (!config.encoder_specific_settings)
130 *video_codec.VP8() = VideoEncoder::GetDefaultVp8Settings();
131 video_codec.VP8()->numberOfTemporalLayers = static_cast<unsigned char>(
132 streams.back().temporal_layer_thresholds_bps.size() + 1);
133 break;
134 }
135 case kVideoCodecVP9: {
136 if (!config.encoder_specific_settings)
137 *video_codec.VP9() = VideoEncoder::GetDefaultVp9Settings();
138 if (video_codec.mode == kScreensharing &&
139 config.encoder_specific_settings) {
140 video_codec.VP9()->flexibleMode = true;
141 // For now VP9 screensharing use 1 temporal and 2 spatial layers.
142 RTC_DCHECK_EQ(1, video_codec.VP9()->numberOfTemporalLayers);
143 RTC_DCHECK_EQ(2, video_codec.VP9()->numberOfSpatialLayers);
144 }
145 video_codec.VP9()->numberOfTemporalLayers = static_cast<unsigned char>(
146 streams.back().temporal_layer_thresholds_bps.size() + 1);
147 break;
148 }
149 case kVideoCodecH264: {
150 if (!config.encoder_specific_settings)
151 *video_codec.H264() = VideoEncoder::GetDefaultH264Settings();
152 break;
153 }
154 default:
155 // TODO(pbos): Support encoder_settings codec-agnostically.
156 RTC_DCHECK(!config.encoder_specific_settings)
157 << "Encoder-specific settings for codec type not wired up.";
158 break;
159 }
160
161 strncpy(video_codec.plName, payload_name.c_str(), kPayloadNameSize - 1);
162 video_codec.plName[kPayloadNameSize - 1] = '\0';
163 video_codec.plType = payload_type;
164 video_codec.numberOfSimulcastStreams =
165 static_cast<unsigned char>(streams.size());
166 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
167 if (video_codec.minBitrate < kEncoderMinBitrateKbps)
168 video_codec.minBitrate = kEncoderMinBitrateKbps;
169 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams));
170 if (video_codec.codecType == kVideoCodecVP9) {
171 // If the vector is empty, bitrates will be configured automatically.
172 RTC_DCHECK(config.spatial_layers.empty() ||
173 config.spatial_layers.size() ==
174 video_codec.VP9()->numberOfSpatialLayers);
175 RTC_DCHECK_LE(video_codec.VP9()->numberOfSpatialLayers,
176 kMaxSimulcastStreams);
177 for (size_t i = 0; i < config.spatial_layers.size(); ++i)
178 video_codec.spatialLayers[i] = config.spatial_layers[i];
179 }
180 for (size_t i = 0; i < streams.size(); ++i) {
181 SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
182 RTC_DCHECK_GT(streams[i].width, 0u);
183 RTC_DCHECK_GT(streams[i].height, 0u);
184 RTC_DCHECK_GT(streams[i].max_framerate, 0);
185 // Different framerates not supported per stream at the moment.
186 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
187 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
188 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
189 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
190 RTC_DCHECK_GE(streams[i].max_qp, 0);
191
192 sim_stream->width = static_cast<uint16_t>(streams[i].width);
193 sim_stream->height = static_cast<uint16_t>(streams[i].height);
194 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
195 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
196 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
197 sim_stream->qpMax = streams[i].max_qp;
198 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>(
199 streams[i].temporal_layer_thresholds_bps.size() + 1);
200
201 video_codec.width =
202 std::max(video_codec.width, static_cast<uint16_t>(streams[i].width));
203 video_codec.height =
204 std::max(video_codec.height, static_cast<uint16_t>(streams[i].height));
205 video_codec.minBitrate =
206 std::min(static_cast<uint16_t>(video_codec.minBitrate),
207 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000));
208 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
209 video_codec.qpMax = std::max(video_codec.qpMax,
210 static_cast<unsigned int>(streams[i].max_qp));
211 }
212
213 if (video_codec.maxBitrate == 0) {
214 // Unset max bitrate -> cap to one bit per pixel.
215 video_codec.maxBitrate =
216 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
217 1000;
218 }
219 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
220 video_codec.maxBitrate = kEncoderMinBitrateKbps;
221
222 RTC_DCHECK_GT(streams[0].max_framerate, 0);
223 video_codec.maxFramerate = streams[0].max_framerate;
224 return video_codec;
225 }
226
227 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/utility/video_coding_utility.gyp ('k') | webrtc/modules/video_coding/video_coding.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698