Revert of H.264 packetization mode 0 (try 3) (patchset #13 id:490001 of https://codereview.webrtc.org/2528343002/ )

Reason for revert:
Failures on the Linux Memcheck bot

Original issue's description:
> This approach passes packetization mode to the encoder as part of
> a cricket::VideoCodec structure, rather than as part of struct VideoCodecH264 inside webrtc::VideoCodec.
>
> BUG=600254
>
> Committed: https://crrev.com/e59647b991f61cf1cf61b020356705e6c0f81257
> Cr-Commit-Position: refs/heads/master@{#15437}

TBR=hbos@webrtc.org,sprang@webrtc.org,mflodman@webrtc.org,magjed@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=600254

Review-Url: https://codereview.webrtc.org/2558453002
Cr-Commit-Position: refs/heads/master@{#15441}
This commit is contained in:
hta
2016-12-06 04:21:58 -08:00
committed by Commit bot
parent dbc960c045
commit 243a0a7a7f
19 changed files with 67 additions and 360 deletions

View File

@ -210,13 +210,10 @@ std::string VideoCodec::ToString() const {
} }
VideoCodec::VideoCodec(int id, const std::string& name) VideoCodec::VideoCodec(int id, const std::string& name)
: Codec(id, name, kVideoCodecClockrate) { : Codec(id, name, kVideoCodecClockrate) {}
SetDefaultParameters();
}
VideoCodec::VideoCodec(const std::string& name) : VideoCodec(0 /* id */, name) { VideoCodec::VideoCodec(const std::string& name)
SetDefaultParameters(); : VideoCodec(0 /* id */, name) {}
}
VideoCodec::VideoCodec() : Codec() { VideoCodec::VideoCodec() : Codec() {
clockrate = kVideoCodecClockrate; clockrate = kVideoCodecClockrate;
@ -227,16 +224,6 @@ VideoCodec::VideoCodec(VideoCodec&& c) = default;
VideoCodec& VideoCodec::operator=(const VideoCodec& c) = default; VideoCodec& VideoCodec::operator=(const VideoCodec& c) = default;
VideoCodec& VideoCodec::operator=(VideoCodec&& c) = default; VideoCodec& VideoCodec::operator=(VideoCodec&& c) = default;
void VideoCodec::SetDefaultParameters() {
if (_stricmp(kH264CodecName, name.c_str()) == 0) {
// This default is set for all H.264 codecs created because
// that was the default before packetization mode support was added.
// TODO(hta): Move this to the places that create VideoCodecs from
// SDP or from knowledge of implementation capabilities.
SetParam(kH264FmtpPacketizationMode, "1");
}
}
bool VideoCodec::operator==(const VideoCodec& c) const { bool VideoCodec::operator==(const VideoCodec& c) const {
return Codec::operator==(c); return Codec::operator==(c);
} }

View File

@ -184,9 +184,6 @@ struct VideoCodec : public Codec {
// don't make sense (such as max < min bitrate), and error is logged and // don't make sense (such as max < min bitrate), and error is logged and
// ValidateCodecFormat returns false. // ValidateCodecFormat returns false.
bool ValidateCodecFormat() const; bool ValidateCodecFormat() const;
private:
void SetDefaultParameters();
}; };
struct DataCodec : public Codec { struct DataCodec : public Codec {

View File

@ -37,9 +37,11 @@ InternalEncoderFactory::InternalEncoderFactory() {
cricket::VideoCodec codec(kH264CodecName); cricket::VideoCodec codec(kH264CodecName);
// TODO(magjed): Move setting these parameters into webrtc::H264Encoder // TODO(magjed): Move setting these parameters into webrtc::H264Encoder
// instead. // instead.
// TODO(hta): Set FMTP parameters for all codecs of type H264.
codec.SetParam(kH264FmtpProfileLevelId, codec.SetParam(kH264FmtpProfileLevelId,
kH264ProfileLevelConstrainedBaseline); kH264ProfileLevelConstrainedBaseline);
codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1");
codec.SetParam(kH264FmtpPacketizationMode, "1");
supported_codecs_.push_back(std::move(codec)); supported_codecs_.push_back(std::move(codec));
} }

View File

@ -544,10 +544,6 @@ if (rtc_include_tests) {
[ "video_coding/codecs/vp9/vp9_screenshare_layers_unittest.cc" ] [ "video_coding/codecs/vp9/vp9_screenshare_layers_unittest.cc" ]
} }
if (rtc_use_h264) {
sources += [ "video_coding/codecs/h264/h264_encoder_impl_unittest.cc" ]
}
if (rtc_desktop_capture_supported || is_android) { if (rtc_desktop_capture_supported || is_android) {
deps += [ "desktop_capture" ] deps += [ "desktop_capture" ]
sources += [ sources += [

View File

@ -262,15 +262,6 @@ enum H264PacketizationTypes {
// that was too large to fit into a single packet. // that was too large to fit into a single packet.
}; };
// Packetization modes are defined in RFC 6184 section 6
// Due to the structure containing this being initialized with zeroes
// in some places, and mode 1 being default, mode 1 needs to have the value
// zero. https://crbug.com/webrtc/6803
enum class H264PacketizationMode {
NonInterleaved = 0, // Mode 1 - STAP-A, FU-A is allowed
SingleNalUnit // Mode 0 - only single NALU allowed
};
struct NaluInfo { struct NaluInfo {
uint8_t type; uint8_t type;
int sps_id; int sps_id;
@ -284,19 +275,14 @@ struct NaluInfo {
const size_t kMaxNalusPerPacket = 10; const size_t kMaxNalusPerPacket = 10;
struct RTPVideoHeaderH264 { struct RTPVideoHeaderH264 {
// The NAL unit type. If this is a header for a uint8_t nalu_type; // The NAL unit type. If this is a header for a
// fragmented packet, it's the NAL unit type of // fragmented packet, it's the NAL unit type of
// the original data. If this is the header for an // the original data. If this is the header for an
// aggregated packet, it's the NAL unit type of // aggregated packet, it's the NAL unit type of
// the first NAL unit in the packet. // the first NAL unit in the packet.
uint8_t nalu_type;
// The packetization type of this buffer - single, aggregated or fragmented.
H264PacketizationTypes packetization_type; H264PacketizationTypes packetization_type;
NaluInfo nalus[kMaxNalusPerPacket]; NaluInfo nalus[kMaxNalusPerPacket];
size_t nalus_length; size_t nalus_length;
// The packetization mode of this transport. Packetization mode
// determines which packetization types are allowed when packetizing.
H264PacketizationMode packetization_mode;
}; };
union RTPVideoTypeHeader { union RTPVideoTypeHeader {

View File

@ -10,8 +10,6 @@
#include "webrtc/modules/rtp_rtcp/source/rtp_format.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format.h"
#include <utility>
#include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
@ -24,19 +22,17 @@ RtpPacketizer* RtpPacketizer::Create(RtpVideoCodecTypes type,
FrameType frame_type) { FrameType frame_type) {
switch (type) { switch (type) {
case kRtpVideoH264: case kRtpVideoH264:
RTC_CHECK(rtp_type_header); return new RtpPacketizerH264(frame_type, max_payload_len);
return new RtpPacketizerH264(max_payload_len,
rtp_type_header->H264.packetization_mode);
case kRtpVideoVp8: case kRtpVideoVp8:
RTC_CHECK(rtp_type_header); assert(rtp_type_header != NULL);
return new RtpPacketizerVp8(rtp_type_header->VP8, max_payload_len); return new RtpPacketizerVp8(rtp_type_header->VP8, max_payload_len);
case kRtpVideoVp9: case kRtpVideoVp9:
RTC_CHECK(rtp_type_header); assert(rtp_type_header != NULL);
return new RtpPacketizerVp9(rtp_type_header->VP9, max_payload_len); return new RtpPacketizerVp9(rtp_type_header->VP9, max_payload_len);
case kRtpVideoGeneric: case kRtpVideoGeneric:
return new RtpPacketizerGeneric(frame_type, max_payload_len); return new RtpPacketizerGeneric(frame_type, max_payload_len);
case kRtpVideoNone: case kRtpVideoNone:
RTC_NOTREACHED(); assert(false);
} }
return NULL; return NULL;
} }

View File

@ -78,10 +78,9 @@ bool ParseStapAStartOffsets(const uint8_t* nalu_ptr,
} // namespace } // namespace
RtpPacketizerH264::RtpPacketizerH264(size_t max_payload_len, RtpPacketizerH264::RtpPacketizerH264(FrameType frame_type,
H264PacketizationMode packetization_mode) size_t max_payload_len)
: max_payload_len_(max_payload_len), : max_payload_len_(max_payload_len) {}
packetization_mode_(packetization_mode) {}
RtpPacketizerH264::~RtpPacketizerH264() { RtpPacketizerH264::~RtpPacketizerH264() {
} }
@ -164,19 +163,11 @@ void RtpPacketizerH264::SetPayloadData(
void RtpPacketizerH264::GeneratePackets() { void RtpPacketizerH264::GeneratePackets() {
for (size_t i = 0; i < input_fragments_.size();) { for (size_t i = 0; i < input_fragments_.size();) {
switch (packetization_mode_) { if (input_fragments_[i].length > max_payload_len_) {
case H264PacketizationMode::SingleNalUnit: PacketizeFuA(i);
PacketizeSingleNalu(i); ++i;
++i; } else {
break; i = PacketizeStapA(i);
case H264PacketizationMode::NonInterleaved:
if (input_fragments_[i].length > max_payload_len_) {
PacketizeFuA(i);
++i;
} else {
i = PacketizeStapA(i);
}
break;
} }
} }
} }
@ -239,21 +230,6 @@ size_t RtpPacketizerH264::PacketizeStapA(size_t fragment_index) {
return fragment_index; return fragment_index;
} }
void RtpPacketizerH264::PacketizeSingleNalu(size_t fragment_index) {
// Add a single NALU to the queue, no aggregation.
size_t payload_size_left = max_payload_len_;
const Fragment* fragment = &input_fragments_[fragment_index];
RTC_CHECK_GE(payload_size_left, fragment->length)
<< "Payload size left " << payload_size_left << ", fragment length "
<< fragment->length << ", packetization mode "
<< (packetization_mode_ == H264PacketizationMode::SingleNalUnit
? "SingleNalUnit"
: "NonInterleaved");
RTC_CHECK_GT(fragment->length, 0u);
packets_.push(PacketUnit(*fragment, true /* first */, true /* last */,
false /* aggregated */, fragment->buffer[0]));
}
bool RtpPacketizerH264::NextPacket(RtpPacketToSend* rtp_packet, bool RtpPacketizerH264::NextPacket(RtpPacketToSend* rtp_packet,
bool* last_packet) { bool* last_packet) {
RTC_DCHECK(rtp_packet); RTC_DCHECK(rtp_packet);
@ -272,10 +248,8 @@ bool RtpPacketizerH264::NextPacket(RtpPacketToSend* rtp_packet,
packets_.pop(); packets_.pop();
input_fragments_.pop_front(); input_fragments_.pop_front();
} else if (packet.aggregated) { } else if (packet.aggregated) {
RTC_CHECK(packetization_mode_ == H264PacketizationMode::NonInterleaved);
NextAggregatePacket(rtp_packet); NextAggregatePacket(rtp_packet);
} else { } else {
RTC_CHECK(packetization_mode_ == H264PacketizationMode::NonInterleaved);
NextFragmentPacket(rtp_packet); NextFragmentPacket(rtp_packet);
} }
RTC_DCHECK_LE(rtp_packet->payload_size(), max_payload_len_); RTC_DCHECK_LE(rtp_packet->payload_size(), max_payload_len_);

View File

@ -26,8 +26,7 @@ class RtpPacketizerH264 : public RtpPacketizer {
public: public:
// Initialize with payload from encoder. // Initialize with payload from encoder.
// The payload_data must be exactly one encoded H264 frame. // The payload_data must be exactly one encoded H264 frame.
RtpPacketizerH264(size_t max_payload_len, RtpPacketizerH264(FrameType frame_type, size_t max_payload_len);
H264PacketizationMode packetization_mode);
virtual ~RtpPacketizerH264(); virtual ~RtpPacketizerH264();
@ -87,12 +86,10 @@ class RtpPacketizerH264 : public RtpPacketizer {
void GeneratePackets(); void GeneratePackets();
void PacketizeFuA(size_t fragment_index); void PacketizeFuA(size_t fragment_index);
size_t PacketizeStapA(size_t fragment_index); size_t PacketizeStapA(size_t fragment_index);
void PacketizeSingleNalu(size_t fragment_index);
void NextAggregatePacket(RtpPacketToSend* rtp_packet); void NextAggregatePacket(RtpPacketToSend* rtp_packet);
void NextFragmentPacket(RtpPacketToSend* rtp_packet); void NextFragmentPacket(RtpPacketToSend* rtp_packet);
const size_t max_payload_len_; const size_t max_payload_len_;
const H264PacketizationMode packetization_mode_;
std::deque<Fragment> input_fragments_; std::deque<Fragment> input_fragments_;
std::queue<PacketUnit> packets_; std::queue<PacketUnit> packets_;

View File

@ -49,27 +49,6 @@ enum NalDefs { kFBit = 0x80, kNriMask = 0x60, kTypeMask = 0x1F };
// Bit masks for FU (A and B) headers. // Bit masks for FU (A and B) headers.
enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 }; enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 };
void CreateThreeFragments(RTPFragmentationHeader* fragmentation,
size_t frameSize,
size_t payloadOffset) {
fragmentation->VerifyAndAllocateFragmentationHeader(3);
fragmentation->fragmentationOffset[0] = 0;
fragmentation->fragmentationLength[0] = 2;
fragmentation->fragmentationOffset[1] = 2;
fragmentation->fragmentationLength[1] = 2;
fragmentation->fragmentationOffset[2] = 4;
fragmentation->fragmentationLength[2] =
kNalHeaderSize + frameSize - payloadOffset;
}
RtpPacketizer* CreateH264Packetizer(H264PacketizationMode mode,
size_t max_payload_size) {
RTPVideoTypeHeader type_header;
type_header.H264.packetization_mode = mode;
return RtpPacketizer::Create(kRtpVideoH264, max_payload_size, &type_header,
kEmptyFrame);
}
void VerifyFua(size_t fua_index, void VerifyFua(size_t fua_index,
const uint8_t* expected_payload, const uint8_t* expected_payload,
int offset, int offset,
@ -109,8 +88,8 @@ void TestFua(size_t frame_size,
fragmentation.VerifyAndAllocateFragmentationHeader(1); fragmentation.VerifyAndAllocateFragmentationHeader(1);
fragmentation.fragmentationOffset[0] = 0; fragmentation.fragmentationOffset[0] = 0;
fragmentation.fragmentationLength[0] = frame_size; fragmentation.fragmentationLength[0] = frame_size;
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
H264PacketizationMode::NonInterleaved, max_payload_size)); kRtpVideoH264, max_payload_size, NULL, kEmptyFrame));
packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation); packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation);
RtpPacketToSend packet(kNoExtensions); RtpPacketToSend packet(kNoExtensions);
@ -170,19 +149,14 @@ void VerifySingleNaluPayload(const RTPFragmentationHeader& fragmentation,
} }
} // namespace } // namespace
// Tests that should work with both packetization mode 0 and TEST(RtpPacketizerH264Test, TestSingleNalu) {
// packetization mode 1.
class RtpPacketizerH264ModeTest
: public ::testing::TestWithParam<H264PacketizationMode> {};
TEST_P(RtpPacketizerH264ModeTest, TestSingleNalu) {
const uint8_t frame[2] = {0x05, 0xFF}; // F=0, NRI=0, Type=5. const uint8_t frame[2] = {0x05, 0xFF}; // F=0, NRI=0, Type=5.
RTPFragmentationHeader fragmentation; RTPFragmentationHeader fragmentation;
fragmentation.VerifyAndAllocateFragmentationHeader(1); fragmentation.VerifyAndAllocateFragmentationHeader(1);
fragmentation.fragmentationOffset[0] = 0; fragmentation.fragmentationOffset[0] = 0;
fragmentation.fragmentationLength[0] = sizeof(frame); fragmentation.fragmentationLength[0] = sizeof(frame);
std::unique_ptr<RtpPacketizer> packetizer( std::unique_ptr<RtpPacketizer> packetizer(
CreateH264Packetizer(GetParam(), kMaxPayloadSize)); RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation); packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation);
RtpPacketToSend packet(kNoExtensions); RtpPacketToSend packet(kNoExtensions);
ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity()); ASSERT_LE(kMaxPayloadSize, packet.FreeCapacity());
@ -194,7 +168,7 @@ TEST_P(RtpPacketizerH264ModeTest, TestSingleNalu) {
EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
} }
TEST_P(RtpPacketizerH264ModeTest, TestSingleNaluTwoPackets) { TEST(RtpPacketizerH264Test, TestSingleNaluTwoPackets) {
const size_t kFrameSize = kMaxPayloadSize + 100; const size_t kFrameSize = kMaxPayloadSize + 100;
uint8_t frame[kFrameSize] = {0}; uint8_t frame[kFrameSize] = {0};
for (size_t i = 0; i < kFrameSize; ++i) for (size_t i = 0; i < kFrameSize; ++i)
@ -210,7 +184,7 @@ TEST_P(RtpPacketizerH264ModeTest, TestSingleNaluTwoPackets) {
frame[fragmentation.fragmentationOffset[1]] = 0x01; frame[fragmentation.fragmentationOffset[1]] = 0x01;
std::unique_ptr<RtpPacketizer> packetizer( std::unique_ptr<RtpPacketizer> packetizer(
CreateH264Packetizer(GetParam(), kMaxPayloadSize)); RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
RtpPacketToSend packet(kNoExtensions); RtpPacketToSend packet(kNoExtensions);
@ -227,12 +201,6 @@ TEST_P(RtpPacketizerH264ModeTest, TestSingleNaluTwoPackets) {
EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
} }
INSTANTIATE_TEST_CASE_P(
PacketMode,
RtpPacketizerH264ModeTest,
::testing::Values(H264PacketizationMode::SingleNalUnit,
H264PacketizationMode::NonInterleaved));
TEST(RtpPacketizerH264Test, TestStapA) { TEST(RtpPacketizerH264Test, TestStapA) {
const size_t kFrameSize = const size_t kFrameSize =
kMaxPayloadSize - 3 * kLengthFieldLength - kNalHeaderSize; kMaxPayloadSize - 3 * kLengthFieldLength - kNalHeaderSize;
@ -243,9 +211,16 @@ TEST(RtpPacketizerH264Test, TestStapA) {
for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i) for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i)
frame[i + kPayloadOffset] = i; frame[i + kPayloadOffset] = i;
RTPFragmentationHeader fragmentation; RTPFragmentationHeader fragmentation;
CreateThreeFragments(&fragmentation, kFrameSize, kPayloadOffset); fragmentation.VerifyAndAllocateFragmentationHeader(3);
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( fragmentation.fragmentationOffset[0] = 0;
H264PacketizationMode::NonInterleaved, kMaxPayloadSize)); fragmentation.fragmentationLength[0] = 2;
fragmentation.fragmentationOffset[1] = 2;
fragmentation.fragmentationLength[1] = 2;
fragmentation.fragmentationOffset[2] = 4;
fragmentation.fragmentationLength[2] =
kNalHeaderSize + kFrameSize - kPayloadOffset;
std::unique_ptr<RtpPacketizer> packetizer(
RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
RtpPacketToSend packet(kNoExtensions); RtpPacketToSend packet(kNoExtensions);
@ -262,31 +237,6 @@ TEST(RtpPacketizerH264Test, TestStapA) {
EXPECT_FALSE(packetizer->NextPacket(&packet, &last)); EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
} }
TEST(RtpPacketizerH264Test, TestSingleNalUnitModeHasNoStapA) {
// This is the same setup as for the TestStapA test.
const size_t kFrameSize =
kMaxPayloadSize - 3 * kLengthFieldLength - kNalHeaderSize;
uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7 (SPS).
0x08, 0xFF, // F=0, NRI=0, Type=8 (PPS).
0x05}; // F=0, NRI=0, Type=5 (IDR).
const size_t kPayloadOffset = 5;
for (size_t i = 0; i < kFrameSize - kPayloadOffset; ++i)
frame[i + kPayloadOffset] = i;
RTPFragmentationHeader fragmentation;
CreateThreeFragments(&fragmentation, kFrameSize, kPayloadOffset);
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer(
H264PacketizationMode::SingleNalUnit, kMaxPayloadSize));
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
RtpPacketToSend packet(kNoExtensions);
bool last = false;
// The three fragments should be returned as three packets.
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
ASSERT_TRUE(packetizer->NextPacket(&packet, &last));
EXPECT_FALSE(packetizer->NextPacket(&packet, &last));
}
TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) { TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) {
const size_t kFrameSize = kMaxPayloadSize - 1; const size_t kFrameSize = kMaxPayloadSize - 1;
uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7. uint8_t frame[kFrameSize] = {0x07, 0xFF, // F=0, NRI=0, Type=7.
@ -304,8 +254,8 @@ TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) {
fragmentation.fragmentationOffset[2] = 4; fragmentation.fragmentationOffset[2] = 4;
fragmentation.fragmentationLength[2] = fragmentation.fragmentationLength[2] =
kNalHeaderSize + kFrameSize - kPayloadOffset; kNalHeaderSize + kFrameSize - kPayloadOffset;
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( std::unique_ptr<RtpPacketizer> packetizer(
H264PacketizationMode::NonInterleaved, kMaxPayloadSize)); RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
RtpPacketToSend packet(kNoExtensions); RtpPacketToSend packet(kNoExtensions);
@ -352,8 +302,8 @@ TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) {
frame[nalu_offset + j] = i + j; frame[nalu_offset + j] = i + j;
} }
} }
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer( std::unique_ptr<RtpPacketizer> packetizer(
H264PacketizationMode::NonInterleaved, kMaxPayloadSize)); RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kEmptyFrame));
packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
// First expecting two FU-A packets. // First expecting two FU-A packets.
@ -426,28 +376,6 @@ TEST(RtpPacketizerH264Test, TestFUABig) {
sizeof(kExpectedPayloadSizes) / sizeof(size_t))); sizeof(kExpectedPayloadSizes) / sizeof(size_t)));
} }
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(RtpPacketizerH264DeathTest, SendOverlongDataInPacketizationMode0) {
const size_t kFrameSize = kMaxPayloadSize + 1;
uint8_t frame[kFrameSize] = {0};
for (size_t i = 0; i < kFrameSize; ++i)
frame[i] = i;
RTPFragmentationHeader fragmentation;
fragmentation.VerifyAndAllocateFragmentationHeader(1);
fragmentation.fragmentationOffset[0] = 0;
fragmentation.fragmentationLength[0] = kFrameSize;
// Set NAL headers.
frame[fragmentation.fragmentationOffset[0]] = 0x01;
std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer(
H264PacketizationMode::SingleNalUnit, kMaxPayloadSize));
EXPECT_DEATH(packetizer->SetPayloadData(frame, kFrameSize, &fragmentation),
"payload_size");
}
#endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
namespace { namespace {
const uint8_t kStartSequence[] = {0x00, 0x00, 0x00, 0x01}; const uint8_t kStartSequence[] = {0x00, 0x00, 0x00, 0x01};
const uint8_t kOriginalSps[] = {kSps, 0x00, 0x00, 0x03, 0x03, const uint8_t kOriginalSps[] = {kSps, 0x00, 0x00, 0x03, 0x03,
@ -488,9 +416,9 @@ TEST_F(RtpPacketizerH264TestSpsRewriting, FuASps) {
const size_t kHeaderOverhead = kFuAHeaderSize + 1; const size_t kHeaderOverhead = kFuAHeaderSize + 1;
// Set size to fragment SPS into two FU-A packets. // Set size to fragment SPS into two FU-A packets.
packetizer_.reset( packetizer_.reset(RtpPacketizer::Create(
CreateH264Packetizer(H264PacketizationMode::NonInterleaved, kRtpVideoH264, sizeof(kOriginalSps) - 2 + kHeaderOverhead, nullptr,
sizeof(kOriginalSps) - 2 + kHeaderOverhead)); kEmptyFrame));
packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(),
&fragmentation_header_); &fragmentation_header_);
@ -522,8 +450,9 @@ TEST_F(RtpPacketizerH264TestSpsRewriting, StapASps) {
sizeof(kIdrTwo) + (kLengthFieldLength * 3); sizeof(kIdrTwo) + (kLengthFieldLength * 3);
// Set size to include SPS and the rest of the packets in a Stap-A package. // Set size to include SPS and the rest of the packets in a Stap-A package.
packetizer_.reset(CreateH264Packetizer(H264PacketizationMode::NonInterleaved, packetizer_.reset(RtpPacketizer::Create(kRtpVideoH264,
kExpectedTotalSize + kHeaderOverhead)); kExpectedTotalSize + kHeaderOverhead,
nullptr, kEmptyFrame));
packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(), packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(),
&fragmentation_header_); &fragmentation_header_);

View File

@ -158,7 +158,6 @@ rtc_static_library("webrtc_h264") {
] ]
deps += [ deps += [
"../../common_video", "../../common_video",
"../../media:rtc_media_base",
"//third_party/ffmpeg:ffmpeg", "//third_party/ffmpeg:ffmpeg",
"//third_party/openh264:encoder", "//third_party/openh264:encoder",
] ]

View File

@ -49,7 +49,7 @@ H264Encoder* H264Encoder::Create(const cricket::VideoCodec& codec) {
#if defined(WEBRTC_USE_H264) #if defined(WEBRTC_USE_H264)
RTC_CHECK(g_rtc_use_h264); RTC_CHECK(g_rtc_use_h264);
LOG(LS_INFO) << "Creating H264EncoderImpl."; LOG(LS_INFO) << "Creating H264EncoderImpl.";
return new H264EncoderImpl(codec); return new H264EncoderImpl();
#else #else
RTC_NOTREACHED(); RTC_NOTREACHED();
return nullptr; return nullptr;

View File

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

View File

@ -27,7 +27,7 @@ namespace webrtc {
class H264EncoderImpl : public H264Encoder { class H264EncoderImpl : public H264Encoder {
public: public:
explicit H264EncoderImpl(const cricket::VideoCodec& codec); H264EncoderImpl();
~H264EncoderImpl() override; ~H264EncoderImpl() override;
// |max_payload_size| is ignored. // |max_payload_size| is ignored.
@ -39,7 +39,7 @@ class H264EncoderImpl : public H264Encoder {
// - height // - height
int32_t InitEncode(const VideoCodec* codec_settings, int32_t InitEncode(const VideoCodec* codec_settings,
int32_t number_of_cores, int32_t number_of_cores,
size_t max_payload_size) override; size_t /*max_payload_size*/) override;
int32_t Release() override; int32_t Release() override;
int32_t RegisterEncodeCompleteCallback( int32_t RegisterEncodeCompleteCallback(
@ -61,11 +61,6 @@ class H264EncoderImpl : public H264Encoder {
int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
int32_t SetPeriodicKeyFrames(bool enable) override; int32_t SetPeriodicKeyFrames(bool enable) override;
// Exposed for testing.
H264PacketizationMode PacketizationModeForTesting() const {
return packetization_mode_;
}
private: private:
bool IsInitialized() const; bool IsInitialized() const;
SEncParamExt CreateEncoderParams() const; SEncParamExt CreateEncoderParams() const;
@ -86,9 +81,7 @@ class H264EncoderImpl : public H264Encoder {
// H.264 specifc parameters // H.264 specifc parameters
bool frame_dropping_on_; bool frame_dropping_on_;
int key_frame_interval_; int key_frame_interval_;
H264PacketizationMode packetization_mode_;
size_t max_payload_size_;
int32_t number_of_cores_; int32_t number_of_cores_;
EncodedImage encoded_image_; EncodedImage encoded_image_;

View File

@ -1,83 +0,0 @@
/*
* 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;
const int kNumCores = 1;
void SetDefaultSettings(VideoCodec* codec_settings) {
codec_settings->codecType = kVideoCodecH264;
codec_settings->maxFramerate = 60;
codec_settings->width = 640;
codec_settings->height = 480;
// 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(cricket::VideoCodec("H264"));
VideoCodec codec_settings;
SetDefaultSettings(&codec_settings);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
EXPECT_EQ(H264PacketizationMode::NonInterleaved,
encoder.PacketizationModeForTesting());
}
TEST(H264EncoderImplTest, CanInitializeWithNonInterleavedModeExplicitly) {
cricket::VideoCodec codec("H264");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
H264EncoderImpl encoder(codec);
VideoCodec codec_settings;
SetDefaultSettings(&codec_settings);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
EXPECT_EQ(H264PacketizationMode::NonInterleaved,
encoder.PacketizationModeForTesting());
}
TEST(H264EncoderImplTest, CanInitializeWithSingleNalUnitModeExplicitly) {
cricket::VideoCodec codec("H264");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
H264EncoderImpl encoder(codec);
VideoCodec codec_settings;
SetDefaultSettings(&codec_settings);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
EXPECT_EQ(H264PacketizationMode::SingleNalUnit,
encoder.PacketizationModeForTesting());
}
TEST(H264EncoderImplTest, CanInitializeWithRemovedParameter) {
cricket::VideoCodec codec("H264");
codec.RemoveParam(cricket::kH264FmtpPacketizationMode);
H264EncoderImpl encoder(codec);
VideoCodec codec_settings;
SetDefaultSettings(&codec_settings);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder.InitEncode(&codec_settings, kNumCores, kMaxPayloadSize));
EXPECT_EQ(H264PacketizationMode::SingleNalUnit,
encoder.PacketizationModeForTesting());
}
} // anonymous namespace
} // namespace webrtc

View File

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

View File

@ -200,8 +200,6 @@ EncodedImageCallback::Result FakeH264Encoder::OnEncodedImage(
CodecSpecificInfo specifics; CodecSpecificInfo specifics;
memset(&specifics, 0, sizeof(specifics)); memset(&specifics, 0, sizeof(specifics));
specifics.codecType = kVideoCodecH264; specifics.codecType = kVideoCodecH264;
specifics.codecSpecific.H264.packetization_mode =
H264PacketizationMode::NonInterleaved;
return callback_->OnEncodedImage(encoded_image, &specifics, &fragmentation); return callback_->OnEncodedImage(encoded_image, &specifics, &fragmentation);
} }

View File

@ -144,7 +144,6 @@ if (rtc_include_tests) {
# TODO(pbos): Rename test suite. # TODO(pbos): Rename test suite.
rtc_source_set("video_tests") { rtc_source_set("video_tests") {
testonly = true testonly = true
defines = []
sources = [ sources = [
"call_stats_unittest.cc", "call_stats_unittest.cc",
"encoder_rtcp_feedback_unittest.cc", "encoder_rtcp_feedback_unittest.cc",
@ -172,7 +171,7 @@ if (rtc_include_tests) {
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
} }
if (rtc_use_h264) { if (rtc_use_h264) {
defines += [ "WEBRTC_USE_H264" ] defines = [ "WEBRTC_USE_H264" ]
} }
} }
} }

View File

@ -404,23 +404,6 @@ TEST_P(EndToEndTest, SendsAndReceivesH264VideoRotation90) {
H264Decoder::Create()); H264Decoder::Create());
RunBaseTest(&test); RunBaseTest(&test);
} }
TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode0) {
cricket::VideoCodec codec = cricket::VideoCodec("H264");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "0");
CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
H264Decoder::Create());
RunBaseTest(&test);
}
TEST_P(EndToEndTest, SendsAndReceivesH264PacketizationMode1) {
cricket::VideoCodec codec = cricket::VideoCodec("H264");
codec.SetParam(cricket::kH264FmtpPacketizationMode, "1");
CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(codec),
H264Decoder::Create());
RunBaseTest(&test);
}
#endif // defined(WEBRTC_USE_H264) #endif // defined(WEBRTC_USE_H264)
TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) { TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) {

View File

@ -75,8 +75,6 @@ void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader* rtp) {
} }
case kVideoCodecH264: case kVideoCodecH264:
rtp->codec = kRtpVideoH264; rtp->codec = kRtpVideoH264;
rtp->codecHeader.H264.packetization_mode =
info->codecSpecific.H264.packetization_mode;
return; return;
case kVideoCodecGeneric: case kVideoCodecGeneric:
rtp->codec = kRtpVideoGeneric; rtp->codec = kRtpVideoGeneric;