1 /*
2 * Copyright (c) 2015 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
12 // Everything declared/defined in this header is only required when WebRTC is
13 // build with H264 support, please do not move anything out of the
14 // #ifdef unless needed and tested.
15 #ifdef WEBRTC_USE_H264
16
17 #include "modules/video_coding/codecs/h264/h264_encoder_impl.h"
18
19 #include <algorithm>
20 #include <limits>
21 #include <string>
22
23 #include "absl/strings/match.h"
24 #include "common_video/libyuv/include/webrtc_libyuv.h"
25 #include "modules/video_coding/svc/create_scalability_structure.h"
26 #include "modules/video_coding/utility/simulcast_rate_allocator.h"
27 #include "modules/video_coding/utility/simulcast_utility.h"
28 #include "rtc_base/checks.h"
29 #include "rtc_base/logging.h"
30 #include "rtc_base/time_utils.h"
31 #include "system_wrappers/include/metrics.h"
32 #include "third_party/libyuv/include/libyuv/convert.h"
33 #include "third_party/libyuv/include/libyuv/scale.h"
34 #include "third_party/openh264/src/codec/api/wels/codec_api.h"
35 #include "third_party/openh264/src/codec/api/wels/codec_app_def.h"
36 #include "third_party/openh264/src/codec/api/wels/codec_def.h"
37 #include "third_party/openh264/src/codec/api/wels/codec_ver.h"
38
39 namespace webrtc {
40
41 namespace {
42
43 const bool kOpenH264EncoderDetailedLogging = false;
44
45 // QP scaling thresholds.
46 static const int kLowH264QpThreshold = 24;
47 static const int kHighH264QpThreshold = 37;
48
49 // Used by histograms. Values of entries should not be changed.
50 enum H264EncoderImplEvent {
51 kH264EncoderEventInit = 0,
52 kH264EncoderEventError = 1,
53 kH264EncoderEventMax = 16,
54 };
55
NumberOfThreads(int width,int height,int number_of_cores)56 int NumberOfThreads(int width, int height, int number_of_cores) {
57 // TODO(hbos): In Chromium, multiple threads do not work with sandbox on Mac,
58 // see crbug.com/583348. Until further investigated, only use one thread.
59 // if (width * height >= 1920 * 1080 && number_of_cores > 8) {
60 // return 8; // 8 threads for 1080p on high perf machines.
61 // } else if (width * height > 1280 * 960 && number_of_cores >= 6) {
62 // return 3; // 3 threads for 1080p.
63 // } else if (width * height > 640 * 480 && number_of_cores >= 3) {
64 // return 2; // 2 threads for qHD/HD.
65 // } else {
66 // return 1; // 1 thread for VGA or less.
67 // }
68 // TODO(sprang): Also check sSliceArgument.uiSliceNum om GetEncoderPrams(),
69 // before enabling multithreading here.
70 return 1;
71 }
72
ConvertToVideoFrameType(EVideoFrameType type)73 VideoFrameType ConvertToVideoFrameType(EVideoFrameType type) {
74 switch (type) {
75 case videoFrameTypeIDR:
76 return VideoFrameType::kVideoFrameKey;
77 case videoFrameTypeSkip:
78 case videoFrameTypeI:
79 case videoFrameTypeP:
80 case videoFrameTypeIPMixed:
81 return VideoFrameType::kVideoFrameDelta;
82 case videoFrameTypeInvalid:
83 break;
84 }
85 RTC_DCHECK_NOTREACHED() << "Unexpected/invalid frame type: " << type;
86 return VideoFrameType::kEmptyFrame;
87 }
88
89 } // namespace
90
91 // Helper method used by H264EncoderImpl::Encode.
92 // Copies the encoded bytes from `info` to `encoded_image`. The
93 // `encoded_image->_buffer` may be deleted and reallocated if a bigger buffer is
94 // required.
95 //
96 // After OpenH264 encoding, the encoded bytes are stored in `info` spread out
97 // over a number of layers and "NAL units". Each NAL unit is a fragment starting
98 // with the four-byte start code {0,0,0,1}. All of this data (including the
99 // start codes) is copied to the `encoded_image->_buffer`.
RtpFragmentize(EncodedImage * encoded_image,SFrameBSInfo * info)100 static void RtpFragmentize(EncodedImage* encoded_image, SFrameBSInfo* info) {
101 // Calculate minimum buffer size required to hold encoded data.
102 size_t required_capacity = 0;
103 size_t fragments_count = 0;
104 for (int layer = 0; layer < info->iLayerNum; ++layer) {
105 const SLayerBSInfo& layerInfo = info->sLayerInfo[layer];
106 for (int nal = 0; nal < layerInfo.iNalCount; ++nal, ++fragments_count) {
107 RTC_CHECK_GE(layerInfo.pNalLengthInByte[nal], 0);
108 // Ensure `required_capacity` will not overflow.
109 RTC_CHECK_LE(layerInfo.pNalLengthInByte[nal],
110 std::numeric_limits<size_t>::max() - required_capacity);
111 required_capacity += layerInfo.pNalLengthInByte[nal];
112 }
113 }
114 auto buffer = EncodedImageBuffer::Create(required_capacity);
115 encoded_image->SetEncodedData(buffer);
116
117 // Iterate layers and NAL units, note each NAL unit as a fragment and copy
118 // the data to `encoded_image->_buffer`.
119 const uint8_t start_code[4] = {0, 0, 0, 1};
120 size_t frag = 0;
121 encoded_image->set_size(0);
122 for (int layer = 0; layer < info->iLayerNum; ++layer) {
123 const SLayerBSInfo& layerInfo = info->sLayerInfo[layer];
124 // Iterate NAL units making up this layer, noting fragments.
125 size_t layer_len = 0;
126 for (int nal = 0; nal < layerInfo.iNalCount; ++nal, ++frag) {
127 // Because the sum of all layer lengths, `required_capacity`, fits in a
128 // `size_t`, we know that any indices in-between will not overflow.
129 RTC_DCHECK_GE(layerInfo.pNalLengthInByte[nal], 4);
130 RTC_DCHECK_EQ(layerInfo.pBsBuf[layer_len + 0], start_code[0]);
131 RTC_DCHECK_EQ(layerInfo.pBsBuf[layer_len + 1], start_code[1]);
132 RTC_DCHECK_EQ(layerInfo.pBsBuf[layer_len + 2], start_code[2]);
133 RTC_DCHECK_EQ(layerInfo.pBsBuf[layer_len + 3], start_code[3]);
134 layer_len += layerInfo.pNalLengthInByte[nal];
135 }
136 // Copy the entire layer's data (including start codes).
137 memcpy(buffer->data() + encoded_image->size(), layerInfo.pBsBuf, layer_len);
138 encoded_image->set_size(encoded_image->size() + layer_len);
139 }
140 }
141
H264EncoderImpl(const cricket::VideoCodec & codec)142 H264EncoderImpl::H264EncoderImpl(const cricket::VideoCodec& codec)
143 : packetization_mode_(H264PacketizationMode::SingleNalUnit),
144 max_payload_size_(0),
145 number_of_cores_(0),
146 encoded_image_callback_(nullptr),
147 has_reported_init_(false),
148 has_reported_error_(false) {
149 RTC_CHECK(absl::EqualsIgnoreCase(codec.name, cricket::kH264CodecName));
150 std::string packetization_mode_string;
151 if (codec.GetParam(cricket::kH264FmtpPacketizationMode,
152 &packetization_mode_string) &&
153 packetization_mode_string == "1") {
154 packetization_mode_ = H264PacketizationMode::NonInterleaved;
155 }
156 downscaled_buffers_.reserve(kMaxSimulcastStreams - 1);
157 encoded_images_.reserve(kMaxSimulcastStreams);
158 encoders_.reserve(kMaxSimulcastStreams);
159 configurations_.reserve(kMaxSimulcastStreams);
160 tl0sync_limit_.reserve(kMaxSimulcastStreams);
161 svc_controllers_.reserve(kMaxSimulcastStreams);
162 }
163
~H264EncoderImpl()164 H264EncoderImpl::~H264EncoderImpl() {
165 Release();
166 }
167
InitEncode(const VideoCodec * inst,const VideoEncoder::Settings & settings)168 int32_t H264EncoderImpl::InitEncode(const VideoCodec* inst,
169 const VideoEncoder::Settings& settings) {
170 ReportInit();
171 if (!inst || inst->codecType != kVideoCodecH264) {
172 ReportError();
173 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
174 }
175 if (inst->maxFramerate == 0) {
176 ReportError();
177 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
178 }
179 if (inst->width < 1 || inst->height < 1) {
180 ReportError();
181 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
182 }
183
184 int32_t release_ret = Release();
185 if (release_ret != WEBRTC_VIDEO_CODEC_OK) {
186 ReportError();
187 return release_ret;
188 }
189
190 int number_of_streams = SimulcastUtility::NumberOfSimulcastStreams(*inst);
191 bool doing_simulcast = (number_of_streams > 1);
192
193 if (doing_simulcast &&
194 !SimulcastUtility::ValidSimulcastParameters(*inst, number_of_streams)) {
195 return WEBRTC_VIDEO_CODEC_ERR_SIMULCAST_PARAMETERS_NOT_SUPPORTED;
196 }
197 downscaled_buffers_.resize(number_of_streams - 1);
198 encoded_images_.resize(number_of_streams);
199 encoders_.resize(number_of_streams);
200 pictures_.resize(number_of_streams);
201 svc_controllers_.resize(number_of_streams);
202 configurations_.resize(number_of_streams);
203 tl0sync_limit_.resize(number_of_streams);
204
205 number_of_cores_ = settings.number_of_cores;
206 max_payload_size_ = settings.max_payload_size;
207 codec_ = *inst;
208
209 // Code expects simulcastStream resolutions to be correct, make sure they are
210 // filled even when there are no simulcast layers.
211 if (codec_.numberOfSimulcastStreams == 0) {
212 codec_.simulcastStream[0].width = codec_.width;
213 codec_.simulcastStream[0].height = codec_.height;
214 }
215
216 for (int i = 0, idx = number_of_streams - 1; i < number_of_streams;
217 ++i, --idx) {
218 ISVCEncoder* openh264_encoder;
219 // Create encoder.
220 if (WelsCreateSVCEncoder(&openh264_encoder) != 0) {
221 // Failed to create encoder.
222 RTC_LOG(LS_ERROR) << "Failed to create OpenH264 encoder";
223 RTC_DCHECK(!openh264_encoder);
224 Release();
225 ReportError();
226 return WEBRTC_VIDEO_CODEC_ERROR;
227 }
228 RTC_DCHECK(openh264_encoder);
229 if (kOpenH264EncoderDetailedLogging) {
230 int trace_level = WELS_LOG_DETAIL;
231 openh264_encoder->SetOption(ENCODER_OPTION_TRACE_LEVEL, &trace_level);
232 }
233 // else WELS_LOG_DEFAULT is used by default.
234
235 // Store h264 encoder.
236 encoders_[i] = openh264_encoder;
237
238 // Set internal settings from codec_settings
239 configurations_[i].simulcast_idx = idx;
240 configurations_[i].sending = false;
241 configurations_[i].width = codec_.simulcastStream[idx].width;
242 configurations_[i].height = codec_.simulcastStream[idx].height;
243 configurations_[i].max_frame_rate = static_cast<float>(codec_.maxFramerate);
244 configurations_[i].frame_dropping_on = codec_.GetFrameDropEnabled();
245 configurations_[i].key_frame_interval = codec_.H264()->keyFrameInterval;
246 configurations_[i].num_temporal_layers =
247 std::max(codec_.H264()->numberOfTemporalLayers,
248 codec_.simulcastStream[idx].numberOfTemporalLayers);
249
250 // Create downscaled image buffers.
251 if (i > 0) {
252 downscaled_buffers_[i - 1] = I420Buffer::Create(
253 configurations_[i].width, configurations_[i].height,
254 configurations_[i].width, configurations_[i].width / 2,
255 configurations_[i].width / 2);
256 }
257
258 // Codec_settings uses kbits/second; encoder uses bits/second.
259 configurations_[i].max_bps = codec_.maxBitrate * 1000;
260 configurations_[i].target_bps = codec_.startBitrate * 1000;
261
262 // Create encoder parameters based on the layer configuration.
263 SEncParamExt encoder_params = CreateEncoderParams(i);
264
265 // Initialize.
266 if (openh264_encoder->InitializeExt(&encoder_params) != 0) {
267 RTC_LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder";
268 Release();
269 ReportError();
270 return WEBRTC_VIDEO_CODEC_ERROR;
271 }
272 // TODO(pbos): Base init params on these values before submitting.
273 int video_format = EVideoFormatType::videoFormatI420;
274 openh264_encoder->SetOption(ENCODER_OPTION_DATAFORMAT, &video_format);
275
276 // Initialize encoded image. Default buffer size: size of unencoded data.
277
278 const size_t new_capacity =
279 CalcBufferSize(VideoType::kI420, codec_.simulcastStream[idx].width,
280 codec_.simulcastStream[idx].height);
281 encoded_images_[i].SetEncodedData(EncodedImageBuffer::Create(new_capacity));
282 encoded_images_[i]._encodedWidth = codec_.simulcastStream[idx].width;
283 encoded_images_[i]._encodedHeight = codec_.simulcastStream[idx].height;
284 encoded_images_[i].set_size(0);
285
286 tl0sync_limit_[i] = configurations_[i].num_temporal_layers;
287 absl::optional<ScalabilityMode> scalability_mode;
288 switch (configurations_[i].num_temporal_layers) {
289 case 0:
290 break;
291 case 1:
292 scalability_mode = ScalabilityMode::kL1T1;
293 break;
294 case 2:
295 scalability_mode = ScalabilityMode::kL1T2;
296 break;
297 case 3:
298 scalability_mode = ScalabilityMode::kL1T3;
299 break;
300 default:
301 RTC_DCHECK_NOTREACHED();
302 }
303 if (scalability_mode.has_value()) {
304 svc_controllers_[i] =
305 CreateScalabilityStructure(scalability_mode.value());
306 if (svc_controllers_[i] == nullptr) {
307 RTC_LOG(LS_ERROR) << "Failed to create scalability structure";
308 Release();
309 ReportError();
310 return WEBRTC_VIDEO_CODEC_ERROR;
311 }
312 }
313 }
314
315 SimulcastRateAllocator init_allocator(codec_);
316 VideoBitrateAllocation allocation =
317 init_allocator.Allocate(VideoBitrateAllocationParameters(
318 DataRate::KilobitsPerSec(codec_.startBitrate), codec_.maxFramerate));
319 SetRates(RateControlParameters(allocation, codec_.maxFramerate));
320 return WEBRTC_VIDEO_CODEC_OK;
321 }
322
Release()323 int32_t H264EncoderImpl::Release() {
324 while (!encoders_.empty()) {
325 ISVCEncoder* openh264_encoder = encoders_.back();
326 if (openh264_encoder) {
327 RTC_CHECK_EQ(0, openh264_encoder->Uninitialize());
328 WelsDestroySVCEncoder(openh264_encoder);
329 }
330 encoders_.pop_back();
331 }
332 downscaled_buffers_.clear();
333 configurations_.clear();
334 encoded_images_.clear();
335 pictures_.clear();
336 tl0sync_limit_.clear();
337 svc_controllers_.clear();
338 return WEBRTC_VIDEO_CODEC_OK;
339 }
340
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)341 int32_t H264EncoderImpl::RegisterEncodeCompleteCallback(
342 EncodedImageCallback* callback) {
343 encoded_image_callback_ = callback;
344 return WEBRTC_VIDEO_CODEC_OK;
345 }
346
SetRates(const RateControlParameters & parameters)347 void H264EncoderImpl::SetRates(const RateControlParameters& parameters) {
348 if (encoders_.empty()) {
349 RTC_LOG(LS_WARNING) << "SetRates() while uninitialized.";
350 return;
351 }
352
353 if (parameters.framerate_fps < 1.0) {
354 RTC_LOG(LS_WARNING) << "Invalid frame rate: " << parameters.framerate_fps;
355 return;
356 }
357
358 if (parameters.bitrate.get_sum_bps() == 0) {
359 // Encoder paused, turn off all encoding.
360 for (size_t i = 0; i < configurations_.size(); ++i) {
361 configurations_[i].SetStreamState(false);
362 }
363 return;
364 }
365
366 codec_.maxFramerate = static_cast<uint32_t>(parameters.framerate_fps);
367
368 size_t stream_idx = encoders_.size() - 1;
369 for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) {
370 // Update layer config.
371 configurations_[i].target_bps =
372 parameters.bitrate.GetSpatialLayerSum(stream_idx);
373 configurations_[i].max_frame_rate = parameters.framerate_fps;
374
375 if (configurations_[i].target_bps) {
376 configurations_[i].SetStreamState(true);
377
378 // Update h264 encoder.
379 SBitrateInfo target_bitrate;
380 memset(&target_bitrate, 0, sizeof(SBitrateInfo));
381 target_bitrate.iLayer = SPATIAL_LAYER_ALL,
382 target_bitrate.iBitrate = configurations_[i].target_bps;
383 encoders_[i]->SetOption(ENCODER_OPTION_BITRATE, &target_bitrate);
384 encoders_[i]->SetOption(ENCODER_OPTION_FRAME_RATE,
385 &configurations_[i].max_frame_rate);
386 } else {
387 configurations_[i].SetStreamState(false);
388 }
389 }
390 }
391
Encode(const VideoFrame & input_frame,const std::vector<VideoFrameType> * frame_types)392 int32_t H264EncoderImpl::Encode(
393 const VideoFrame& input_frame,
394 const std::vector<VideoFrameType>* frame_types) {
395 if (encoders_.empty()) {
396 ReportError();
397 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
398 }
399 if (!encoded_image_callback_) {
400 RTC_LOG(LS_WARNING)
401 << "InitEncode() has been called, but a callback function "
402 "has not been set with RegisterEncodeCompleteCallback()";
403 ReportError();
404 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
405 }
406
407 rtc::scoped_refptr<I420BufferInterface> frame_buffer =
408 input_frame.video_frame_buffer()->ToI420();
409 if (!frame_buffer) {
410 RTC_LOG(LS_ERROR) << "Failed to convert "
411 << VideoFrameBufferTypeToString(
412 input_frame.video_frame_buffer()->type())
413 << " image to I420. Can't encode frame.";
414 return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
415 }
416 RTC_CHECK(frame_buffer->type() == VideoFrameBuffer::Type::kI420 ||
417 frame_buffer->type() == VideoFrameBuffer::Type::kI420A);
418
419 bool send_key_frame = false;
420 for (size_t i = 0; i < configurations_.size(); ++i) {
421 if (configurations_[i].key_frame_request && configurations_[i].sending) {
422 send_key_frame = true;
423 break;
424 }
425 }
426
427 if (!send_key_frame && frame_types) {
428 for (size_t i = 0; i < configurations_.size(); ++i) {
429 const size_t simulcast_idx =
430 static_cast<size_t>(configurations_[i].simulcast_idx);
431 if (configurations_[i].sending && simulcast_idx < frame_types->size() &&
432 (*frame_types)[simulcast_idx] == VideoFrameType::kVideoFrameKey) {
433 send_key_frame = true;
434 break;
435 }
436 }
437 }
438
439 RTC_DCHECK_EQ(configurations_[0].width, frame_buffer->width());
440 RTC_DCHECK_EQ(configurations_[0].height, frame_buffer->height());
441
442 // Encode image for each layer.
443 for (size_t i = 0; i < encoders_.size(); ++i) {
444 // EncodeFrame input.
445 pictures_[i] = {0};
446 pictures_[i].iPicWidth = configurations_[i].width;
447 pictures_[i].iPicHeight = configurations_[i].height;
448 pictures_[i].iColorFormat = EVideoFormatType::videoFormatI420;
449 pictures_[i].uiTimeStamp = input_frame.ntp_time_ms();
450 // Downscale images on second and ongoing layers.
451 if (i == 0) {
452 pictures_[i].iStride[0] = frame_buffer->StrideY();
453 pictures_[i].iStride[1] = frame_buffer->StrideU();
454 pictures_[i].iStride[2] = frame_buffer->StrideV();
455 pictures_[i].pData[0] = const_cast<uint8_t*>(frame_buffer->DataY());
456 pictures_[i].pData[1] = const_cast<uint8_t*>(frame_buffer->DataU());
457 pictures_[i].pData[2] = const_cast<uint8_t*>(frame_buffer->DataV());
458 } else {
459 pictures_[i].iStride[0] = downscaled_buffers_[i - 1]->StrideY();
460 pictures_[i].iStride[1] = downscaled_buffers_[i - 1]->StrideU();
461 pictures_[i].iStride[2] = downscaled_buffers_[i - 1]->StrideV();
462 pictures_[i].pData[0] =
463 const_cast<uint8_t*>(downscaled_buffers_[i - 1]->DataY());
464 pictures_[i].pData[1] =
465 const_cast<uint8_t*>(downscaled_buffers_[i - 1]->DataU());
466 pictures_[i].pData[2] =
467 const_cast<uint8_t*>(downscaled_buffers_[i - 1]->DataV());
468 // Scale the image down a number of times by downsampling factor.
469 libyuv::I420Scale(pictures_[i - 1].pData[0], pictures_[i - 1].iStride[0],
470 pictures_[i - 1].pData[1], pictures_[i - 1].iStride[1],
471 pictures_[i - 1].pData[2], pictures_[i - 1].iStride[2],
472 configurations_[i - 1].width,
473 configurations_[i - 1].height, pictures_[i].pData[0],
474 pictures_[i].iStride[0], pictures_[i].pData[1],
475 pictures_[i].iStride[1], pictures_[i].pData[2],
476 pictures_[i].iStride[2], configurations_[i].width,
477 configurations_[i].height, libyuv::kFilterBox);
478 }
479
480 if (!configurations_[i].sending) {
481 continue;
482 }
483 if (frame_types != nullptr) {
484 // Skip frame?
485 if ((*frame_types)[i] == VideoFrameType::kEmptyFrame) {
486 continue;
487 }
488 }
489 if (send_key_frame) {
490 // API doc says ForceIntraFrame(false) does nothing, but calling this
491 // function forces a key frame regardless of the `bIDR` argument's value.
492 // (If every frame is a key frame we get lag/delays.)
493 encoders_[i]->ForceIntraFrame(true);
494 configurations_[i].key_frame_request = false;
495 }
496 // EncodeFrame output.
497 SFrameBSInfo info;
498 memset(&info, 0, sizeof(SFrameBSInfo));
499
500 std::vector<ScalableVideoController::LayerFrameConfig> layer_frames;
501 if (svc_controllers_[i]) {
502 layer_frames = svc_controllers_[i]->NextFrameConfig(send_key_frame);
503 RTC_CHECK_EQ(layer_frames.size(), 1);
504 }
505
506 // Encode!
507 int enc_ret = encoders_[i]->EncodeFrame(&pictures_[i], &info);
508 if (enc_ret != 0) {
509 RTC_LOG(LS_ERROR)
510 << "OpenH264 frame encoding failed, EncodeFrame returned " << enc_ret
511 << ".";
512 ReportError();
513 return WEBRTC_VIDEO_CODEC_ERROR;
514 }
515
516 encoded_images_[i]._encodedWidth = configurations_[i].width;
517 encoded_images_[i]._encodedHeight = configurations_[i].height;
518 encoded_images_[i].SetTimestamp(input_frame.timestamp());
519 encoded_images_[i].SetColorSpace(input_frame.color_space());
520 encoded_images_[i]._frameType = ConvertToVideoFrameType(info.eFrameType);
521 encoded_images_[i].SetSpatialIndex(configurations_[i].simulcast_idx);
522
523 // Split encoded image up into fragments. This also updates
524 // `encoded_image_`.
525 RtpFragmentize(&encoded_images_[i], &info);
526
527 // Encoder can skip frames to save bandwidth in which case
528 // `encoded_images_[i]._length` == 0.
529 if (encoded_images_[i].size() > 0) {
530 // Parse QP.
531 h264_bitstream_parser_.ParseBitstream(encoded_images_[i]);
532 encoded_images_[i].qp_ =
533 h264_bitstream_parser_.GetLastSliceQp().value_or(-1);
534
535 // Deliver encoded image.
536 CodecSpecificInfo codec_specific;
537 codec_specific.codecType = kVideoCodecH264;
538 codec_specific.codecSpecific.H264.packetization_mode =
539 packetization_mode_;
540 codec_specific.codecSpecific.H264.temporal_idx = kNoTemporalIdx;
541 codec_specific.codecSpecific.H264.idr_frame =
542 info.eFrameType == videoFrameTypeIDR;
543 codec_specific.codecSpecific.H264.base_layer_sync = false;
544 if (configurations_[i].num_temporal_layers > 1) {
545 const uint8_t tid = info.sLayerInfo[0].uiTemporalId;
546 codec_specific.codecSpecific.H264.temporal_idx = tid;
547 codec_specific.codecSpecific.H264.base_layer_sync =
548 tid > 0 && tid < tl0sync_limit_[i];
549 if (svc_controllers_[i]) {
550 if (layer_frames[0].TemporalId() != tid) {
551 RTC_LOG(LS_WARNING)
552 << "Encoder produced a frame for layer S" << (i + 1) << "T"
553 << tid + 1 << " that wasn't requested.";
554 continue;
555 }
556 encoded_images_[i].SetTemporalIndex(tid);
557 }
558 if (codec_specific.codecSpecific.H264.base_layer_sync) {
559 tl0sync_limit_[i] = tid;
560 }
561 if (tid == 0) {
562 tl0sync_limit_[i] = configurations_[i].num_temporal_layers;
563 }
564 }
565 if (svc_controllers_[i]) {
566 codec_specific.generic_frame_info =
567 svc_controllers_[i]->OnEncodeDone(layer_frames[0]);
568 if (send_key_frame && codec_specific.generic_frame_info.has_value()) {
569 codec_specific.template_structure =
570 svc_controllers_[i]->DependencyStructure();
571 }
572 }
573 encoded_image_callback_->OnEncodedImage(encoded_images_[i],
574 &codec_specific);
575 }
576 }
577 return WEBRTC_VIDEO_CODEC_OK;
578 }
579
580 // Initialization parameters.
581 // There are two ways to initialize. There is SEncParamBase (cleared with
582 // memset(&p, 0, sizeof(SEncParamBase)) used in Initialize, and SEncParamExt
583 // which is a superset of SEncParamBase (cleared with GetDefaultParams) used
584 // in InitializeExt.
CreateEncoderParams(size_t i) const585 SEncParamExt H264EncoderImpl::CreateEncoderParams(size_t i) const {
586 SEncParamExt encoder_params;
587 encoders_[i]->GetDefaultParams(&encoder_params);
588 if (codec_.mode == VideoCodecMode::kRealtimeVideo) {
589 encoder_params.iUsageType = CAMERA_VIDEO_REAL_TIME;
590 } else if (codec_.mode == VideoCodecMode::kScreensharing) {
591 encoder_params.iUsageType = SCREEN_CONTENT_REAL_TIME;
592 } else {
593 RTC_DCHECK_NOTREACHED();
594 }
595 encoder_params.iPicWidth = configurations_[i].width;
596 encoder_params.iPicHeight = configurations_[i].height;
597 encoder_params.iTargetBitrate = configurations_[i].target_bps;
598 // Keep unspecified. WebRTC's max codec bitrate is not the same setting
599 // as OpenH264's iMaxBitrate. More details in https://crbug.com/webrtc/11543
600 encoder_params.iMaxBitrate = UNSPECIFIED_BIT_RATE;
601 // Rate Control mode
602 encoder_params.iRCMode = RC_BITRATE_MODE;
603 encoder_params.fMaxFrameRate = configurations_[i].max_frame_rate;
604
605 // The following parameters are extension parameters (they're in SEncParamExt,
606 // not in SEncParamBase).
607 encoder_params.bEnableFrameSkip = configurations_[i].frame_dropping_on;
608 // `uiIntraPeriod` - multiple of GOP size
609 // `keyFrameInterval` - number of frames
610 encoder_params.uiIntraPeriod = configurations_[i].key_frame_interval;
611 // Reuse SPS id if possible. This helps to avoid reset of chromium HW decoder
612 // on each key-frame.
613 // Note that WebRTC resets encoder on resolution change which makes all
614 // EParameterSetStrategy modes except INCREASING_ID (default) essentially
615 // equivalent to CONSTANT_ID.
616 encoder_params.eSpsPpsIdStrategy = SPS_LISTING;
617 encoder_params.uiMaxNalSize = 0;
618 // Threading model: use auto.
619 // 0: auto (dynamic imp. internal encoder)
620 // 1: single thread (default value)
621 // >1: number of threads
622 encoder_params.iMultipleThreadIdc = NumberOfThreads(
623 encoder_params.iPicWidth, encoder_params.iPicHeight, number_of_cores_);
624 // The base spatial layer 0 is the only one we use.
625 encoder_params.sSpatialLayers[0].iVideoWidth = encoder_params.iPicWidth;
626 encoder_params.sSpatialLayers[0].iVideoHeight = encoder_params.iPicHeight;
627 encoder_params.sSpatialLayers[0].fFrameRate = encoder_params.fMaxFrameRate;
628 encoder_params.sSpatialLayers[0].iSpatialBitrate =
629 encoder_params.iTargetBitrate;
630 encoder_params.sSpatialLayers[0].iMaxSpatialBitrate =
631 encoder_params.iMaxBitrate;
632 encoder_params.iTemporalLayerNum = configurations_[i].num_temporal_layers;
633 if (encoder_params.iTemporalLayerNum > 1) {
634 // iNumRefFrame specifies total number of reference buffers to allocate.
635 // For N temporal layers we need at least (N - 1) buffers to store last
636 // encoded frames of all reference temporal layers.
637 // Note that there is no API in OpenH264 encoder to specify exact set of
638 // references to be used to prediction of a given frame. Encoder can
639 // theoretically use all available reference buffers.
640 encoder_params.iNumRefFrame = encoder_params.iTemporalLayerNum - 1;
641 }
642 RTC_LOG(LS_INFO) << "OpenH264 version is " << OPENH264_MAJOR << "."
643 << OPENH264_MINOR;
644 switch (packetization_mode_) {
645 case H264PacketizationMode::SingleNalUnit:
646 // Limit the size of the packets produced.
647 encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceNum = 1;
648 encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceMode =
649 SM_SIZELIMITED_SLICE;
650 encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint =
651 static_cast<unsigned int>(max_payload_size_);
652 RTC_LOG(LS_INFO) << "Encoder is configured with NALU constraint: "
653 << max_payload_size_ << " bytes";
654 break;
655 case H264PacketizationMode::NonInterleaved:
656 // When uiSliceMode = SM_FIXEDSLCNUM_SLICE, uiSliceNum = 0 means auto
657 // design it with cpu core number.
658 // TODO(sprang): Set to 0 when we understand why the rate controller borks
659 // when uiSliceNum > 1.
660 encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceNum = 1;
661 encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceMode =
662 SM_FIXEDSLCNUM_SLICE;
663 break;
664 }
665 return encoder_params;
666 }
667
ReportInit()668 void H264EncoderImpl::ReportInit() {
669 if (has_reported_init_)
670 return;
671 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264EncoderImpl.Event",
672 kH264EncoderEventInit, kH264EncoderEventMax);
673 has_reported_init_ = true;
674 }
675
ReportError()676 void H264EncoderImpl::ReportError() {
677 if (has_reported_error_)
678 return;
679 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264EncoderImpl.Event",
680 kH264EncoderEventError, kH264EncoderEventMax);
681 has_reported_error_ = true;
682 }
683
GetEncoderInfo() const684 VideoEncoder::EncoderInfo H264EncoderImpl::GetEncoderInfo() const {
685 EncoderInfo info;
686 info.supports_native_handle = false;
687 info.implementation_name = "OpenH264";
688 info.scaling_settings =
689 VideoEncoder::ScalingSettings(kLowH264QpThreshold, kHighH264QpThreshold);
690 info.is_hardware_accelerated = false;
691 info.supports_simulcast = true;
692 info.preferred_pixel_formats = {VideoFrameBuffer::Type::kI420};
693 return info;
694 }
695
SetStreamState(bool send_stream)696 void H264EncoderImpl::LayerConfig::SetStreamState(bool send_stream) {
697 if (send_stream && !sending) {
698 // Need a key frame if we have not sent this stream before.
699 key_frame_request = true;
700 }
701 sending = send_stream;
702 }
703
704 } // namespace webrtc
705
706 #endif // WEBRTC_USE_H264
707