| Index: webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.cc b/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.cc
|
| index d7df12209d1897718c456f3b845011cb1f82a417..6150aa89c07dc3e62f58e7fb7e884d4f0e0296f2 100644
|
| --- a/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.cc
|
| +++ b/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.cc
|
| @@ -12,6 +12,7 @@
|
| #include "webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h"
|
|
|
| #include <limits>
|
| +#include <string>
|
|
|
| #include "third_party/openh264/src/codec/api/svc/codec_api.h"
|
| #include "third_party/openh264/src/codec/api/svc/codec_app_def.h"
|
| @@ -21,6 +22,7 @@
|
| #include "webrtc/base/checks.h"
|
| #include "webrtc/base/logging.h"
|
| #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
| +#include "webrtc/media/base/mediaconstants.h"
|
| #include "webrtc/system_wrappers/include/metrics.h"
|
|
|
| namespace webrtc {
|
| @@ -150,7 +152,7 @@ static void RtpFragmentize(EncodedImage* encoded_image,
|
| }
|
| }
|
|
|
| -H264EncoderImpl::H264EncoderImpl()
|
| +H264EncoderImpl::H264EncoderImpl(const cricket::VideoCodec& codec)
|
| : openh264_encoder_(nullptr),
|
| width_(0),
|
| height_(0),
|
| @@ -160,10 +162,20 @@ H264EncoderImpl::H264EncoderImpl()
|
| mode_(kRealtimeVideo),
|
| frame_dropping_on_(false),
|
| key_frame_interval_(0),
|
| + packetization_mode_(H264PacketizationMode::SingleNalUnit),
|
| + max_payload_size_(0),
|
| number_of_cores_(0),
|
| encoded_image_callback_(nullptr),
|
| has_reported_init_(false),
|
| - has_reported_error_(false) {}
|
| + has_reported_error_(false) {
|
| + RTC_CHECK(cricket::CodecNamesEq(codec.name, cricket::kH264CodecName));
|
| + std::string packetization_mode_string;
|
| + if (codec.GetParam(cricket::kH264FmtpPacketizationMode,
|
| + &packetization_mode_string) &&
|
| + packetization_mode_string == "1") {
|
| + packetization_mode_ = H264PacketizationMode::NonInterleaved;
|
| + }
|
| +}
|
|
|
| H264EncoderImpl::~H264EncoderImpl() {
|
| Release();
|
| @@ -171,7 +183,7 @@ H264EncoderImpl::~H264EncoderImpl() {
|
|
|
| int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
| int32_t number_of_cores,
|
| - size_t /*max_payload_size*/) {
|
| + size_t max_payload_size) {
|
| ReportInit();
|
| if (!codec_settings ||
|
| codec_settings->codecType != kVideoCodecH264) {
|
| @@ -218,6 +230,7 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
| mode_ = codec_settings->mode;
|
| frame_dropping_on_ = codec_settings->H264().frameDroppingOn;
|
| key_frame_interval_ = codec_settings->H264().keyFrameInterval;
|
| + max_payload_size_ = max_payload_size;
|
|
|
| // Codec_settings uses kbits/second; encoder uses bits/second.
|
| max_bps_ = codec_settings->maxBitrate * 1000;
|
| @@ -227,6 +240,7 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
|
| target_bps_ = codec_settings->targetBitrate * 1000;
|
|
|
| SEncParamExt encoder_params = CreateEncoderParams();
|
| +
|
| // Initialize.
|
| if (openh264_encoder_->InitializeExt(&encoder_params) != 0) {
|
| LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder";
|
| @@ -370,6 +384,7 @@ int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame,
|
| // Deliver encoded image.
|
| CodecSpecificInfo codec_specific;
|
| codec_specific.codecType = kVideoCodecH264;
|
| + codec_specific.codecSpecific.H264.packetization_mode = packetization_mode_;
|
| encoded_image_callback_->OnEncodedImage(encoded_image_, &codec_specific,
|
| &frag_header);
|
|
|
| @@ -434,19 +449,46 @@ SEncParamExt H264EncoderImpl::CreateEncoderParams() const {
|
| encoder_params.iTargetBitrate;
|
| encoder_params.sSpatialLayers[0].iMaxSpatialBitrate =
|
| encoder_params.iMaxBitrate;
|
| + LOG(INFO) << "OpenH264 version is " << OPENH264_MAJOR << "."
|
| + << OPENH264_MINOR;
|
| + switch (packetization_mode_) {
|
| + case H264PacketizationMode::SingleNalUnit:
|
| +// Limit the size of the packets produced.
|
| #if (OPENH264_MAJOR == 1) && (OPENH264_MINOR <= 5)
|
| - // Slice num according to number of threads.
|
| - encoder_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_AUTO_SLICE;
|
| + encoder_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_DYN_SLICE;
|
| + // The slice size is max payload size - room for a NAL header.
|
| + // The constant 50 is NAL_HEADER_ADD_0X30BYTES in openh264 source,
|
| + // but is not exported.
|
| + const kNalHeaderSizeAllocation = 50;
|
| + encoder_params.sSpatialLayers[0]
|
| + .sSliceCfg.sSliceArgument.uiSliceSizeConstraint =
|
| + static_cast<unsigned int>(max_payload_size_ -
|
| + kNalHeaderSizeAllocation);
|
| + encoder_params.uiMaxNalSize =
|
| + static_cast<unsigned int>(max_payload_size_);
|
| #else
|
| - // When uiSliceMode = SM_FIXEDSLCNUM_SLICE, uiSliceNum = 0 means auto design
|
| - // it with cpu core number.
|
| - // TODO(sprang): Set to 0 when we understand why the rate controller borks
|
| - // when uiSliceNum > 1.
|
| - encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceNum = 1;
|
| - encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceMode =
|
| - SM_FIXEDSLCNUM_SLICE;
|
| + encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceNum = 1;
|
| + encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceMode =
|
| + SM_SIZELIMITED_SLICE;
|
| + encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceSizeConstraint =
|
| + static_cast<unsigned int>(max_payload_size_);
|
| #endif
|
| -
|
| + break;
|
| + case H264PacketizationMode::NonInterleaved:
|
| +#if (OPENH264_MAJOR == 1) && (OPENH264_MINOR <= 5)
|
| + // Slice num according to number of threads.
|
| + encoder_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_AUTO_SLICE;
|
| +#else
|
| + // When uiSliceMode = SM_FIXEDSLCNUM_SLICE, uiSliceNum = 0 means auto
|
| + // design it with cpu core number.
|
| + // TODO(sprang): Set to 0 when we understand why the rate controller borks
|
| + // when uiSliceNum > 1.
|
| + encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceNum = 1;
|
| + encoder_params.sSpatialLayers[0].sSliceArgument.uiSliceMode =
|
| + SM_FIXEDSLCNUM_SLICE;
|
| +#endif
|
| + break;
|
| + }
|
| return encoder_params;
|
| }
|
|
|
|
|