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

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

Issue 2510583002: Reland #2 of Issue 2434073003: Extract bitrate allocation ... (Closed)
Patch Set: Addressed comments 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 bool VideoCodecInitializer::SetupCodec(
25 const VideoEncoderConfig& config,
26 const VideoSendStream::Config::EncoderSettings settings,
27 const std::vector<VideoStream>& streams,
28 VideoCodec* codec,
29 std::unique_ptr<VideoBitrateAllocator>* bitrate_allocator) {
30 *codec = VideoEncoderConfigToVideoCodec(
31 config, streams, settings.payload_name, settings.payload_type);
32
33 std::unique_ptr<TemporalLayersFactory> tl_factory;
34 switch (codec->codecType) {
35 case kVideoCodecVP8: {
36 if (!codec->VP8()->tl_factory) {
37 if (codec->mode == kScreensharing &&
38 codec->numberOfSimulcastStreams == 1 &&
39 codec->VP8()->numberOfTemporalLayers == 2) {
40 // Conference mode temporal layering for screen content.
41 tl_factory.reset(new ScreenshareTemporalLayersFactory());
42 } else {
43 // Standard video temporal layers.
44 tl_factory.reset(new TemporalLayersFactory());
45 }
46 codec->VP8()->tl_factory = tl_factory.get();
47 }
48 break;
49 }
50 default: {
51 // TODO(sprang): Warn, once we have specific allocators for all supported
52 // codec types.
53 break;
54 }
55 }
56 *bitrate_allocator = CreateBitrateAllocator(*codec, std::move(tl_factory));
57
58 return true;
59 }
60
61 std::unique_ptr<VideoBitrateAllocator>
62 VideoCodecInitializer::CreateBitrateAllocator(
63 const VideoCodec& codec,
64 std::unique_ptr<TemporalLayersFactory> tl_factory) {
65 std::unique_ptr<VideoBitrateAllocator> rate_allocator;
66
67 switch (codec.codecType) {
68 case kVideoCodecVP8: {
69 // Set up default VP8 temporal layer factory, if not provided.
70 rate_allocator.reset(
71 new SimulcastRateAllocator(codec, std::move(tl_factory)));
72 } break;
73 default:
74 rate_allocator.reset(new DefaultVideoBitrateAllocator(codec));
75 }
76
77 return rate_allocator;
78 }
79
80 // TODO(sprang): Split this up and separate the codec specific parts.
81 VideoCodec VideoCodecInitializer::VideoEncoderConfigToVideoCodec(
82 const VideoEncoderConfig& config,
83 const std::vector<VideoStream>& streams,
84 const std::string& payload_name,
85 int payload_type) {
86 static const int kEncoderMinBitrateKbps = 30;
87 RTC_DCHECK(!streams.empty());
88 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
89
90 VideoCodec video_codec;
91 memset(&video_codec, 0, sizeof(video_codec));
92 video_codec.codecType = PayloadNameToCodecType(payload_name)
93 .value_or(VideoCodecType::kVideoCodecGeneric);
94
95 switch (config.content_type) {
96 case VideoEncoderConfig::ContentType::kRealtimeVideo:
97 video_codec.mode = kRealtimeVideo;
98 break;
99 case VideoEncoderConfig::ContentType::kScreen:
100 video_codec.mode = kScreensharing;
101 if (streams.size() == 1 &&
102 streams[0].temporal_layer_thresholds_bps.size() == 1) {
103 video_codec.targetBitrate =
104 streams[0].temporal_layer_thresholds_bps[0] / 1000;
105 }
106 break;
107 }
108
109 if (config.encoder_specific_settings)
110 config.encoder_specific_settings->FillEncoderSpecificSettings(&video_codec);
111
112 switch (video_codec.codecType) {
113 case kVideoCodecVP8: {
114 if (!config.encoder_specific_settings)
115 *video_codec.VP8() = VideoEncoder::GetDefaultVp8Settings();
116 video_codec.VP8()->numberOfTemporalLayers = static_cast<unsigned char>(
117 streams.back().temporal_layer_thresholds_bps.size() + 1);
118 break;
119 }
120 case kVideoCodecVP9: {
121 if (!config.encoder_specific_settings)
122 *video_codec.VP9() = VideoEncoder::GetDefaultVp9Settings();
123 if (video_codec.mode == kScreensharing &&
124 config.encoder_specific_settings) {
125 video_codec.VP9()->flexibleMode = true;
126 // For now VP9 screensharing use 1 temporal and 2 spatial layers.
127 RTC_DCHECK_EQ(1, video_codec.VP9()->numberOfTemporalLayers);
128 RTC_DCHECK_EQ(2, video_codec.VP9()->numberOfSpatialLayers);
129 }
130 video_codec.VP9()->numberOfTemporalLayers = static_cast<unsigned char>(
131 streams.back().temporal_layer_thresholds_bps.size() + 1);
132 break;
133 }
134 case kVideoCodecH264: {
135 if (!config.encoder_specific_settings)
136 *video_codec.H264() = VideoEncoder::GetDefaultH264Settings();
137 break;
138 }
139 default:
140 // TODO(pbos): Support encoder_settings codec-agnostically.
141 RTC_DCHECK(!config.encoder_specific_settings)
142 << "Encoder-specific settings for codec type not wired up.";
143 break;
144 }
145
146 strncpy(video_codec.plName, payload_name.c_str(), kPayloadNameSize - 1);
147 video_codec.plName[kPayloadNameSize - 1] = '\0';
148 video_codec.plType = payload_type;
149 video_codec.numberOfSimulcastStreams =
150 static_cast<unsigned char>(streams.size());
151 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
152 if (video_codec.minBitrate < kEncoderMinBitrateKbps)
153 video_codec.minBitrate = kEncoderMinBitrateKbps;
154 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams));
155 if (video_codec.codecType == kVideoCodecVP9) {
156 // If the vector is empty, bitrates will be configured automatically.
157 RTC_DCHECK(config.spatial_layers.empty() ||
158 config.spatial_layers.size() ==
159 video_codec.VP9()->numberOfSpatialLayers);
160 RTC_DCHECK_LE(video_codec.VP9()->numberOfSpatialLayers,
161 kMaxSimulcastStreams);
162 for (size_t i = 0; i < config.spatial_layers.size(); ++i)
163 video_codec.spatialLayers[i] = config.spatial_layers[i];
164 }
165 for (size_t i = 0; i < streams.size(); ++i) {
166 SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
167 RTC_DCHECK_GT(streams[i].width, 0u);
168 RTC_DCHECK_GT(streams[i].height, 0u);
169 RTC_DCHECK_GT(streams[i].max_framerate, 0);
170 // Different framerates not supported per stream at the moment.
171 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
172 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
173 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
174 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
175 RTC_DCHECK_GE(streams[i].max_qp, 0);
176
177 sim_stream->width = static_cast<uint16_t>(streams[i].width);
178 sim_stream->height = static_cast<uint16_t>(streams[i].height);
179 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
180 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
181 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
182 sim_stream->qpMax = streams[i].max_qp;
183 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>(
184 streams[i].temporal_layer_thresholds_bps.size() + 1);
185
186 video_codec.width =
187 std::max(video_codec.width, static_cast<uint16_t>(streams[i].width));
188 video_codec.height =
189 std::max(video_codec.height, static_cast<uint16_t>(streams[i].height));
190 video_codec.minBitrate =
191 std::min(static_cast<uint16_t>(video_codec.minBitrate),
192 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000));
193 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
194 video_codec.qpMax = std::max(video_codec.qpMax,
195 static_cast<unsigned int>(streams[i].max_qp));
196 }
197
198 if (video_codec.maxBitrate == 0) {
199 // Unset max bitrate -> cap to one bit per pixel.
200 video_codec.maxBitrate =
201 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
202 1000;
203 }
204 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
205 video_codec.maxBitrate = kEncoderMinBitrateKbps;
206
207 RTC_DCHECK_GT(streams[0].max_framerate, 0);
208 video_codec.maxFramerate = streams[0].max_framerate;
209 return video_codec;
210 }
211
212 } // 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