Implement H.264 packetization mode 0.

This approach extends the H.264 specific information with
a packetization mode enum.

Status: Parameter is in code. No way to set it yet.

Rebase of CL  2009213002

BUG=600254

Review-Url: https://codereview.webrtc.org/2337453002
Cr-Commit-Position: refs/heads/master@{#15032}
This commit is contained in:
hta
2016-11-10 21:50:00 -08:00
committed by Commit bot
parent e95f5bf69d
commit 3bba101f36
18 changed files with 315 additions and 45 deletions

View File

@ -64,6 +64,7 @@ VideoCodecH264 VideoEncoder::GetDefaultH264Settings() {
h264_settings.frameDroppingOn = true;
h264_settings.keyFrameInterval = 3000;
h264_settings.packetization_mode = kH264PacketizationMode1;
h264_settings.spsData = nullptr;
h264_settings.spsLen = 0;
h264_settings.ppsData = nullptr;

View File

@ -152,6 +152,15 @@ static void RtpFragmentize(EncodedImage* encoded_image,
H264EncoderImpl::H264EncoderImpl()
: openh264_encoder_(nullptr),
width_(0),
height_(0),
max_frame_rate_(0.0f),
target_bps_(0),
max_bps_(0),
mode_(kRealtimeVideo),
frame_dropping_on_(false),
key_frame_interval_(0),
max_payload_size_(0),
number_of_cores_(0),
encoded_image_callback_(nullptr),
has_reported_init_(false),
@ -163,7 +172,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) {
@ -210,6 +219,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;
@ -217,8 +227,12 @@ int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
target_bps_ = codec_settings->startBitrate * 1000;
else
target_bps_ = codec_settings->targetBitrate * 1000;
RTC_DCHECK(codec_settings->H264().packetization_mode !=
kH264PacketizationModeNotSet);
packetization_mode_ = codec_settings->H264().packetization_mode;
SEncParamExt encoder_params = CreateEncoderParams();
// Initialize.
if (openh264_encoder_->InitializeExt(&encoder_params) != 0) {
LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder";
@ -377,6 +391,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);
@ -445,19 +460,50 @@ 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 kH264PacketizationMode0:
#if (OPENH264_MAJOR == 1) && (OPENH264_MINOR <= 5)
// Slice num according to number of threads.
encoder_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_AUTO_SLICE;
// Limit the size of packets produced.
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.
encoder_params.sSpatialLayers[0]
.sSliceCfg.sSliceArgument.uiSliceSizeConstraint =
static_cast<unsigned int>(max_payload_size_ - 50);
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;
// When uiSliceMode = SM_FIXEDSLCNUM_SLICE, uiSliceNum = 0 means auto
// design
// it with cpu core number.
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 kH264PacketizationMode1:
#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;
default:
RTC_NOTREACHED() << "Illegal packetization mode specified";
}
return encoder_params;
}

View File

@ -39,7 +39,7 @@ class H264EncoderImpl : public H264Encoder {
// - height
int32_t InitEncode(const VideoCodec* codec_settings,
int32_t number_of_cores,
size_t /*max_payload_size*/) override;
size_t max_payload_size) override;
int32_t Release() override;
int32_t RegisterEncodeCompleteCallback(
@ -80,7 +80,9 @@ class H264EncoderImpl : public H264Encoder {
// H.264 specifc parameters
bool frame_dropping_on_;
int key_frame_interval_;
H264PacketizationMode packetization_mode_;
size_t max_payload_size_;
int32_t number_of_cores_;
EncodedImage encoded_image_;

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*
*/
#include "webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h"
#include "webrtc/test/gtest.h"
namespace webrtc {
namespace {
const int kMaxPayloadSize = 1024;
void SetDefaultSettings(VideoCodec* codec_settings) {
codec_settings->codecType = kVideoCodecH264;
codec_settings->maxFramerate = 60;
codec_settings->width = 640;
codec_settings->height = 480;
codec_settings->H264()->packetization_mode = kH264PacketizationMode1;
// If frame dropping is false, we get a warning that bitrate can't
// be controlled for RC_QUALITY_MODE; RC_BITRATE_MODE and RC_TIMESTAMP_MODE
codec_settings->H264()->frameDroppingOn = true;
codec_settings->targetBitrate = 2000;
codec_settings->maxBitrate = 4000;
}
TEST(H264EncoderImplTest, CanInitializeWithDefaultParameters) {
H264EncoderImpl encoder;
VideoCodec codec_settings;
SetDefaultSettings(&codec_settings);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder.InitEncode(&codec_settings, 1, kMaxPayloadSize));
}
TEST(H264EncoderImplTest, CanInitializeWithPacketizationMode0) {
H264EncoderImpl encoder;
VideoCodec codec_settings;
SetDefaultSettings(&codec_settings);
codec_settings.H264()->packetization_mode = kH264PacketizationMode0;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder.InitEncode(&codec_settings, 1, kMaxPayloadSize));
}
} // anonymous namespace
} // namespace webrtc

View File

@ -77,7 +77,9 @@ struct CodecSpecificInfoGeneric {
uint8_t simulcast_idx;
};
struct CodecSpecificInfoH264 {};
struct CodecSpecificInfoH264 {
H264PacketizationMode packetization_mode;
};
union CodecSpecificInfoUnion {
CodecSpecificInfoGeneric generic;