diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn index e5e80d19d3..dd202ce0a1 100644 --- a/modules/video_coding/BUILD.gn +++ b/modules/video_coding/BUILD.gn @@ -80,6 +80,7 @@ rtc_library("video_coding") { visibility = [ "*" ] deps = [ "..:module_fec_api", + "../../api:array_view", "../../api:scoped_refptr", "../../api/video:encoded_image", "../../api/video:video_bitrate_allocation", diff --git a/modules/video_coding/h264_sps_pps_tracker.cc b/modules/video_coding/h264_sps_pps_tracker.cc index 9c0e52178e..26a070530d 100644 --- a/modules/video_coding/h264_sps_pps_tracker.cc +++ b/modules/video_coding/h264_sps_pps_tracker.cc @@ -10,15 +10,15 @@ #include "modules/video_coding/h264_sps_pps_tracker.h" +#include #include #include +#include "absl/types/variant.h" #include "common_video/h264/h264_common.h" #include "common_video/h264/pps_parser.h" #include "common_video/h264/sps_parser.h" #include "modules/video_coding/codecs/h264/include/h264_globals.h" -#include "modules/video_coding/frame_object.h" -#include "modules/video_coding/packet_buffer.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" @@ -44,15 +44,14 @@ H264SpsPpsTracker::SpsInfo& H264SpsPpsTracker::SpsInfo::operator=( SpsInfo&& rhs) = default; H264SpsPpsTracker::SpsInfo::~SpsInfo() = default; -H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( - VCMPacket* packet) { - RTC_DCHECK(packet->codec() == kVideoCodecH264); +H264SpsPpsTracker::FixedBitstream H264SpsPpsTracker::CopyAndFixBitstream( + rtc::ArrayView bitstream, + RTPVideoHeader* video_header) { + RTC_DCHECK(video_header); + RTC_DCHECK(video_header->codec == kVideoCodecH264); - const uint8_t* data = packet->dataPtr; - const size_t data_size = packet->sizeBytes; - const RTPVideoHeader& video_header = packet->video_header; auto& h264_header = - absl::get(packet->video_header.video_type_header); + absl::get(video_header->video_type_header); bool append_sps_pps = false; auto sps = sps_data_.end(); @@ -62,8 +61,9 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( const NaluInfo& nalu = h264_header.nalus[i]; switch (nalu.type) { case H264::NaluType::kSps: { - sps_data_[nalu.sps_id].width = packet->width(); - sps_data_[nalu.sps_id].height = packet->height(); + SpsInfo& sps_info = sps_data_[nalu.sps_id]; + sps_info.width = video_header->width; + sps_info.height = video_header->height; break; } case H264::NaluType::kPps: { @@ -74,31 +74,31 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( // If this is the first packet of an IDR, make sure we have the required // SPS/PPS and also calculate how much extra space we need in the buffer // to prepend the SPS/PPS to the bitstream with start codes. - if (video_header.is_first_packet_in_frame) { + if (video_header->is_first_packet_in_frame) { if (nalu.pps_id == -1) { RTC_LOG(LS_WARNING) << "No PPS id in IDR nalu."; - return kRequestKeyframe; + return {kRequestKeyframe}; } pps = pps_data_.find(nalu.pps_id); if (pps == pps_data_.end()) { RTC_LOG(LS_WARNING) << "No PPS with id << " << nalu.pps_id << " received"; - return kRequestKeyframe; + return {kRequestKeyframe}; } sps = sps_data_.find(pps->second.sps_id); if (sps == sps_data_.end()) { RTC_LOG(LS_WARNING) << "No SPS with id << " << pps->second.sps_id << " received"; - return kRequestKeyframe; + return {kRequestKeyframe}; } // Since the first packet of every keyframe should have its width and // height set we set it here in the case of it being supplied out of // band. - packet->video_header.width = sps->second.width; - packet->video_header.height = sps->second.height; + video_header->width = sps->second.width; + video_header->height = sps->second.height; // If the SPS/PPS was supplied out of band then we will have saved // the actual bitstream in |data|. @@ -127,9 +127,9 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( } if (h264_header.packetization_type == kH264StapA) { - const uint8_t* nalu_ptr = data + 1; - while (nalu_ptr < data + data_size) { - RTC_DCHECK(video_header.is_first_packet_in_frame); + const uint8_t* nalu_ptr = bitstream.data() + 1; + while (nalu_ptr < bitstream.data() + bitstream.size()) { + RTC_DCHECK(video_header->is_first_packet_in_frame); required_size += sizeof(start_code_h264); // The first two bytes describe the length of a segment. @@ -143,12 +143,14 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( if (h264_header.nalus_length > 0) { required_size += sizeof(start_code_h264); } - required_size += data_size; + required_size += bitstream.size(); } // Then we copy to the new buffer. - uint8_t* buffer = new uint8_t[required_size]; - uint8_t* insert_at = buffer; + H264SpsPpsTracker::FixedBitstream fixed; + fixed.data = std::make_unique(required_size); + fixed.size = required_size; + uint8_t* insert_at = fixed.data.get(); if (append_sps_pps) { // Insert SPS. @@ -183,8 +185,8 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( // Copy the rest of the bitstream and insert start codes. if (h264_header.packetization_type == kH264StapA) { - const uint8_t* nalu_ptr = data + 1; - while (nalu_ptr < data + data_size) { + const uint8_t* nalu_ptr = bitstream.data() + 1; + while (nalu_ptr < bitstream.data() + bitstream.size()) { memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); insert_at += sizeof(start_code_h264); @@ -192,10 +194,9 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1]; nalu_ptr += 2; - size_t copy_end = nalu_ptr - data + segment_length; - if (copy_end > data_size) { - delete[] buffer; - return kDrop; + size_t copy_end = nalu_ptr - bitstream.data() + segment_length; + if (copy_end > bitstream.size()) { + return {kDrop}; } memcpy(insert_at, nalu_ptr, segment_length); @@ -207,12 +208,11 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); insert_at += sizeof(start_code_h264); } - memcpy(insert_at, data, data_size); + memcpy(insert_at, bitstream.data(), bitstream.size()); } - packet->dataPtr = buffer; - packet->sizeBytes = required_size; - return kInsert; + fixed.action = kInsert; + return fixed; } void H264SpsPpsTracker::InsertSpsPpsNalus(const std::vector& sps, diff --git a/modules/video_coding/h264_sps_pps_tracker.h b/modules/video_coding/h264_sps_pps_tracker.h index 88fc8ca632..0d1815b99f 100644 --- a/modules/video_coding/h264_sps_pps_tracker.h +++ b/modules/video_coding/h264_sps_pps_tracker.h @@ -11,25 +11,33 @@ #ifndef MODULES_VIDEO_CODING_H264_SPS_PPS_TRACKER_H_ #define MODULES_VIDEO_CODING_H264_SPS_PPS_TRACKER_H_ +#include #include #include #include #include +#include "api/array_view.h" +#include "modules/rtp_rtcp/source/rtp_video_header.h" + namespace webrtc { - -class VCMPacket; - namespace video_coding { class H264SpsPpsTracker { public: enum PacketAction { kInsert, kDrop, kRequestKeyframe }; + struct FixedBitstream { + PacketAction action; + std::unique_ptr data; + size_t size; + }; H264SpsPpsTracker(); ~H264SpsPpsTracker(); - PacketAction CopyAndFixBitstream(VCMPacket* packet); + // Returns fixed bitstream and modifies |video_header|. + FixedBitstream CopyAndFixBitstream(rtc::ArrayView bitstream, + RTPVideoHeader* video_header); void InsertSpsPpsNalus(const std::vector& sps, const std::vector& pps); diff --git a/modules/video_coding/h264_sps_pps_tracker_unittest.cc b/modules/video_coding/h264_sps_pps_tracker_unittest.cc index 7857aa7efc..00a95ec90d 100644 --- a/modules/video_coding/h264_sps_pps_tracker_unittest.cc +++ b/modules/video_coding/h264_sps_pps_tracker_unittest.cc @@ -19,14 +19,22 @@ #include "modules/rtp_rtcp/source/rtp_video_header.h" #include "modules/video_coding/codecs/h264/include/h264_globals.h" #include "modules/video_coding/packet.h" +#include "test/gmock.h" #include "test/gtest.h" namespace webrtc { namespace video_coding { - namespace { + +using ::testing::ElementsAreArray; + const uint8_t start_code[] = {0, 0, 0, 1}; +rtc::ArrayView Bitstream( + const H264SpsPpsTracker::FixedBitstream& fixed) { + return rtc::MakeArrayView(fixed.data.get(), fixed.size); +} + void ExpectSpsPpsIdr(const RTPVideoHeaderH264& codec_header, uint8_t sps_id, uint8_t pps_id) { @@ -51,19 +59,18 @@ void ExpectSpsPpsIdr(const RTPVideoHeaderH264& codec_header, EXPECT_TRUE(contains_idr); } -class H264VcmPacket : public VCMPacket { +class H264VideoHeader : public RTPVideoHeader { public: - H264VcmPacket() { - video_header.codec = kVideoCodecH264; - video_header.is_first_packet_in_frame = false; - auto& type_header = - video_header.video_type_header.emplace(); - type_header.nalus_length = 0; - type_header.packetization_type = kH264SingleNalu; + H264VideoHeader() { + codec = kVideoCodecH264; + is_first_packet_in_frame = false; + auto& h264_header = video_type_header.emplace(); + h264_header.nalus_length = 0; + h264_header.packetization_type = kH264SingleNalu; } RTPVideoHeaderH264& h264() { - return absl::get(video_header.video_type_header); + return absl::get(video_type_header); } }; @@ -71,7 +78,7 @@ class H264VcmPacket : public VCMPacket { class TestH264SpsPpsTracker : public ::testing::Test { public: - void AddSps(H264VcmPacket* packet, + void AddSps(H264VideoHeader* header, uint8_t sps_id, std::vector* data) { NaluInfo info; @@ -81,10 +88,10 @@ class TestH264SpsPpsTracker : public ::testing::Test { data->push_back(H264::NaluType::kSps); data->push_back(sps_id); // The sps data, just a single byte. - packet->h264().nalus[packet->h264().nalus_length++] = info; + header->h264().nalus[header->h264().nalus_length++] = info; } - void AddPps(H264VcmPacket* packet, + void AddPps(H264VideoHeader* header, uint8_t sps_id, uint8_t pps_id, std::vector* data) { @@ -95,16 +102,16 @@ class TestH264SpsPpsTracker : public ::testing::Test { data->push_back(H264::NaluType::kPps); data->push_back(pps_id); // The pps data, just a single byte. - packet->h264().nalus[packet->h264().nalus_length++] = info; + header->h264().nalus[header->h264().nalus_length++] = info; } - void AddIdr(H264VcmPacket* packet, int pps_id) { + void AddIdr(H264VideoHeader* header, int pps_id) { NaluInfo info; info.type = H264::NaluType::kIdr; info.sps_id = -1; info.pps_id = pps_id; - packet->h264().nalus[packet->h264().nalus_length++] = info; + header->h264().nalus[header->h264().nalus_length++] = info; } protected: @@ -113,165 +120,149 @@ class TestH264SpsPpsTracker : public ::testing::Test { TEST_F(TestH264SpsPpsTracker, NoNalus) { uint8_t data[] = {1, 2, 3}; - H264VcmPacket packet; - packet.h264().packetization_type = kH264FuA; - packet.dataPtr = data; - packet.sizeBytes = sizeof(data); + H264VideoHeader header; + header.h264().packetization_type = kH264FuA; - EXPECT_EQ(H264SpsPpsTracker::kInsert, tracker_.CopyAndFixBitstream(&packet)); - EXPECT_EQ(memcmp(packet.dataPtr, data, sizeof(data)), 0); - delete[] packet.dataPtr; + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(data, &header); + + EXPECT_EQ(fixed.action, H264SpsPpsTracker::kInsert); + EXPECT_THAT(Bitstream(fixed), ElementsAreArray(data)); } TEST_F(TestH264SpsPpsTracker, FuAFirstPacket) { uint8_t data[] = {1, 2, 3}; - H264VcmPacket packet; - packet.h264().packetization_type = kH264FuA; - packet.h264().nalus_length = 1; - packet.video_header.is_first_packet_in_frame = true; - packet.dataPtr = data; - packet.sizeBytes = sizeof(data); + H264VideoHeader header; + header.h264().packetization_type = kH264FuA; + header.h264().nalus_length = 1; + header.is_first_packet_in_frame = true; - EXPECT_EQ(H264SpsPpsTracker::kInsert, tracker_.CopyAndFixBitstream(&packet)); + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(data, &header); + + EXPECT_EQ(fixed.action, H264SpsPpsTracker::kInsert); std::vector expected; expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); expected.insert(expected.end(), {1, 2, 3}); - EXPECT_EQ(memcmp(packet.dataPtr, expected.data(), expected.size()), 0); - delete[] packet.dataPtr; + EXPECT_THAT(Bitstream(fixed), ElementsAreArray(expected)); } TEST_F(TestH264SpsPpsTracker, StapAIncorrectSegmentLength) { uint8_t data[] = {0, 0, 2, 0}; - H264VcmPacket packet; - packet.h264().packetization_type = kH264StapA; - packet.video_header.is_first_packet_in_frame = true; - packet.dataPtr = data; - packet.sizeBytes = sizeof(data); + H264VideoHeader header; + header.h264().packetization_type = kH264StapA; + header.is_first_packet_in_frame = true; - EXPECT_EQ(H264SpsPpsTracker::kDrop, tracker_.CopyAndFixBitstream(&packet)); + EXPECT_EQ(tracker_.CopyAndFixBitstream(data, &header).action, + H264SpsPpsTracker::kDrop); } TEST_F(TestH264SpsPpsTracker, SingleNaluInsertStartCode) { uint8_t data[] = {1, 2, 3}; - H264VcmPacket packet; - packet.h264().nalus_length = 1; - packet.dataPtr = data; - packet.sizeBytes = sizeof(data); + H264VideoHeader header; + header.h264().nalus_length = 1; - EXPECT_EQ(H264SpsPpsTracker::kInsert, tracker_.CopyAndFixBitstream(&packet)); + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(data, &header); + + EXPECT_EQ(fixed.action, H264SpsPpsTracker::kInsert); std::vector expected; expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); expected.insert(expected.end(), {1, 2, 3}); - EXPECT_EQ(memcmp(packet.dataPtr, expected.data(), expected.size()), 0); - delete[] packet.dataPtr; + EXPECT_THAT(Bitstream(fixed), ElementsAreArray(expected)); } TEST_F(TestH264SpsPpsTracker, NoStartCodeInsertedForSubsequentFuAPacket) { std::vector data = {1, 2, 3}; - H264VcmPacket packet; - packet.h264().packetization_type = kH264FuA; - + H264VideoHeader header; + header.h264().packetization_type = kH264FuA; // Since no NALU begin in this packet the nalus_length is zero. - packet.h264().nalus_length = 0; + header.h264().nalus_length = 0; - packet.dataPtr = data.data(); - packet.sizeBytes = data.size(); + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(data, &header); - EXPECT_EQ(H264SpsPpsTracker::kInsert, tracker_.CopyAndFixBitstream(&packet)); - EXPECT_EQ(memcmp(packet.dataPtr, data.data(), data.size()), 0); - delete[] packet.dataPtr; + EXPECT_EQ(fixed.action, H264SpsPpsTracker::kInsert); + EXPECT_THAT(Bitstream(fixed), ElementsAreArray(data)); } TEST_F(TestH264SpsPpsTracker, IdrFirstPacketNoSpsPpsInserted) { std::vector data = {1, 2, 3}; - H264VcmPacket packet; - packet.video_header.is_first_packet_in_frame = true; + H264VideoHeader header; + header.is_first_packet_in_frame = true; + AddIdr(&header, 0); - AddIdr(&packet, 0); - packet.dataPtr = data.data(); - packet.sizeBytes = data.size(); - - EXPECT_EQ(H264SpsPpsTracker::kRequestKeyframe, - tracker_.CopyAndFixBitstream(&packet)); + EXPECT_EQ(tracker_.CopyAndFixBitstream(data, &header).action, + H264SpsPpsTracker::kRequestKeyframe); } TEST_F(TestH264SpsPpsTracker, IdrFirstPacketNoPpsInserted) { std::vector data = {1, 2, 3}; - H264VcmPacket packet; - packet.video_header.is_first_packet_in_frame = true; + H264VideoHeader header; + header.is_first_packet_in_frame = true; + AddSps(&header, 0, &data); + AddIdr(&header, 0); - AddSps(&packet, 0, &data); - AddIdr(&packet, 0); - packet.dataPtr = data.data(); - packet.sizeBytes = data.size(); - - EXPECT_EQ(H264SpsPpsTracker::kRequestKeyframe, - tracker_.CopyAndFixBitstream(&packet)); + EXPECT_EQ(tracker_.CopyAndFixBitstream(data, &header).action, + H264SpsPpsTracker::kRequestKeyframe); } TEST_F(TestH264SpsPpsTracker, IdrFirstPacketNoSpsInserted) { std::vector data = {1, 2, 3}; - H264VcmPacket packet; - packet.video_header.is_first_packet_in_frame = true; + H264VideoHeader header; + header.is_first_packet_in_frame = true; + AddPps(&header, 0, 0, &data); + AddIdr(&header, 0); - AddPps(&packet, 0, 0, &data); - AddIdr(&packet, 0); - packet.dataPtr = data.data(); - packet.sizeBytes = data.size(); - - EXPECT_EQ(H264SpsPpsTracker::kRequestKeyframe, - tracker_.CopyAndFixBitstream(&packet)); + EXPECT_EQ(tracker_.CopyAndFixBitstream(data, &header).action, + H264SpsPpsTracker::kRequestKeyframe); } TEST_F(TestH264SpsPpsTracker, SpsPpsPacketThenIdrFirstPacket) { std::vector data; - H264VcmPacket sps_pps_packet; - + H264VideoHeader sps_pps_header; // Insert SPS/PPS - AddSps(&sps_pps_packet, 0, &data); - AddPps(&sps_pps_packet, 0, 1, &data); - sps_pps_packet.dataPtr = data.data(); - sps_pps_packet.sizeBytes = data.size(); - EXPECT_EQ(H264SpsPpsTracker::kInsert, - tracker_.CopyAndFixBitstream(&sps_pps_packet)); - delete[] sps_pps_packet.dataPtr; - data.clear(); + AddSps(&sps_pps_header, 0, &data); + AddPps(&sps_pps_header, 0, 1, &data); + + EXPECT_EQ(tracker_.CopyAndFixBitstream(data, &sps_pps_header).action, + H264SpsPpsTracker::kInsert); // Insert first packet of the IDR - H264VcmPacket idr_packet; - idr_packet.video_header.is_first_packet_in_frame = true; - AddIdr(&idr_packet, 1); - data.insert(data.end(), {1, 2, 3}); - idr_packet.dataPtr = data.data(); - idr_packet.sizeBytes = data.size(); - EXPECT_EQ(H264SpsPpsTracker::kInsert, - tracker_.CopyAndFixBitstream(&idr_packet)); + H264VideoHeader idr_header; + idr_header.is_first_packet_in_frame = true; + AddIdr(&idr_header, 1); + data = {1, 2, 3}; + + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(data, &idr_header); + EXPECT_EQ(fixed.action, H264SpsPpsTracker::kInsert); std::vector expected; expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); expected.insert(expected.end(), {1, 2, 3}); - EXPECT_EQ(memcmp(idr_packet.dataPtr, expected.data(), expected.size()), 0); - delete[] idr_packet.dataPtr; + EXPECT_THAT(Bitstream(fixed), ElementsAreArray(expected)); } TEST_F(TestH264SpsPpsTracker, SpsPpsIdrInStapA) { std::vector data; - H264VcmPacket packet; - packet.h264().packetization_type = kH264StapA; - packet.video_header.is_first_packet_in_frame = true; // Always true for StapA + H264VideoHeader header; + header.h264().packetization_type = kH264StapA; + header.is_first_packet_in_frame = true; // Always true for StapA data.insert(data.end(), {0}); // First byte is ignored data.insert(data.end(), {0, 2}); // Length of segment - AddSps(&packet, 13, &data); + AddSps(&header, 13, &data); data.insert(data.end(), {0, 2}); // Length of segment - AddPps(&packet, 13, 27, &data); + AddPps(&header, 13, 27, &data); data.insert(data.end(), {0, 5}); // Length of segment - AddIdr(&packet, 27); + AddIdr(&header, 27); data.insert(data.end(), {1, 2, 3, 2, 1}); - packet.dataPtr = data.data(); - packet.sizeBytes = data.size(); - EXPECT_EQ(H264SpsPpsTracker::kInsert, tracker_.CopyAndFixBitstream(&packet)); + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(data, &header); + + EXPECT_THAT(fixed.action, H264SpsPpsTracker::kInsert); std::vector expected; expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); @@ -280,9 +271,7 @@ TEST_F(TestH264SpsPpsTracker, SpsPpsIdrInStapA) { expected.insert(expected.end(), {H264::NaluType::kPps, 27}); expected.insert(expected.end(), start_code, start_code + sizeof(start_code)); expected.insert(expected.end(), {1, 2, 3, 2, 1}); - - EXPECT_EQ(memcmp(packet.dataPtr, expected.data(), expected.size()), 0); - delete[] packet.dataPtr; + EXPECT_THAT(Bitstream(fixed), ElementsAreArray(expected)); } TEST_F(TestH264SpsPpsTracker, SpsPpsOutOfBand) { @@ -297,25 +286,18 @@ TEST_F(TestH264SpsPpsTracker, SpsPpsOutOfBand) { tracker_.InsertSpsPpsNalus(sps, pps); // Insert first packet of the IDR. - H264VcmPacket idr_packet; - idr_packet.video_header.is_first_packet_in_frame = true; - AddIdr(&idr_packet, 0); - idr_packet.dataPtr = kData; - idr_packet.sizeBytes = sizeof(kData); - EXPECT_EQ(1u, idr_packet.h264().nalus_length); - EXPECT_EQ(H264SpsPpsTracker::kInsert, - tracker_.CopyAndFixBitstream(&idr_packet)); - EXPECT_EQ(3u, idr_packet.h264().nalus_length); - EXPECT_EQ(320, idr_packet.width()); - EXPECT_EQ(240, idr_packet.height()); - ExpectSpsPpsIdr(idr_packet.h264(), 0, 0); + H264VideoHeader idr_header; + idr_header.is_first_packet_in_frame = true; + AddIdr(&idr_header, 0); + EXPECT_EQ(idr_header.h264().nalus_length, 1u); - if (idr_packet.dataPtr != kData) { - // In case CopyAndFixBitStream() prepends SPS/PPS nalus to the packet, it - // uses new uint8_t[] to allocate memory. Caller of CopyAndFixBitStream() - // needs to take care of freeing the memory. - delete[] idr_packet.dataPtr; - } + H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(kData, &idr_header); + + EXPECT_EQ(idr_header.h264().nalus_length, 3u); + EXPECT_EQ(idr_header.width, 320u); + EXPECT_EQ(idr_header.height, 240u); + ExpectSpsPpsIdr(idr_header.h264(), 0, 0); } TEST_F(TestH264SpsPpsTracker, SpsPpsOutOfBandWrongNaluHeader) { @@ -330,13 +312,12 @@ TEST_F(TestH264SpsPpsTracker, SpsPpsOutOfBandWrongNaluHeader) { tracker_.InsertSpsPpsNalus(sps, pps); // Insert first packet of the IDR. - H264VcmPacket idr_packet; - idr_packet.video_header.is_first_packet_in_frame = true; - AddIdr(&idr_packet, 0); - idr_packet.dataPtr = kData; - idr_packet.sizeBytes = sizeof(kData); - EXPECT_EQ(H264SpsPpsTracker::kRequestKeyframe, - tracker_.CopyAndFixBitstream(&idr_packet)); + H264VideoHeader idr_header; + idr_header.is_first_packet_in_frame = true; + AddIdr(&idr_header, 0); + + EXPECT_EQ(tracker_.CopyAndFixBitstream(kData, &idr_header).action, + H264SpsPpsTracker::kRequestKeyframe); } TEST_F(TestH264SpsPpsTracker, SpsPpsOutOfBandIncompleteNalu) { @@ -349,13 +330,12 @@ TEST_F(TestH264SpsPpsTracker, SpsPpsOutOfBandIncompleteNalu) { tracker_.InsertSpsPpsNalus(sps, pps); // Insert first packet of the IDR. - H264VcmPacket idr_packet; - idr_packet.video_header.is_first_packet_in_frame = true; - AddIdr(&idr_packet, 0); - idr_packet.dataPtr = kData; - idr_packet.sizeBytes = sizeof(kData); - EXPECT_EQ(H264SpsPpsTracker::kRequestKeyframe, - tracker_.CopyAndFixBitstream(&idr_packet)); + H264VideoHeader idr_header; + idr_header.is_first_packet_in_frame = true; + AddIdr(&idr_header, 0); + + EXPECT_EQ(tracker_.CopyAndFixBitstream(kData, &idr_header).action, + H264SpsPpsTracker::kRequestKeyframe); } TEST_F(TestH264SpsPpsTracker, SaveRestoreWidthHeight) { @@ -363,29 +343,25 @@ TEST_F(TestH264SpsPpsTracker, SaveRestoreWidthHeight) { // Insert an SPS/PPS packet with width/height and make sure // that information is set on the first IDR packet. - H264VcmPacket sps_pps_packet; - AddSps(&sps_pps_packet, 0, &data); - AddPps(&sps_pps_packet, 0, 1, &data); - sps_pps_packet.dataPtr = data.data(); - sps_pps_packet.sizeBytes = data.size(); - sps_pps_packet.video_header.width = 320; - sps_pps_packet.video_header.height = 240; - EXPECT_EQ(H264SpsPpsTracker::kInsert, - tracker_.CopyAndFixBitstream(&sps_pps_packet)); - delete[] sps_pps_packet.dataPtr; + H264VideoHeader sps_pps_header; + AddSps(&sps_pps_header, 0, &data); + AddPps(&sps_pps_header, 0, 1, &data); + sps_pps_header.width = 320; + sps_pps_header.height = 240; - H264VcmPacket idr_packet; - idr_packet.video_header.is_first_packet_in_frame = true; - AddIdr(&idr_packet, 1); + EXPECT_EQ(tracker_.CopyAndFixBitstream(data, &sps_pps_header).action, + H264SpsPpsTracker::kInsert); + + H264VideoHeader idr_header; + idr_header.is_first_packet_in_frame = true; + AddIdr(&idr_header, 1); data.insert(data.end(), {1, 2, 3}); - idr_packet.dataPtr = data.data(); - idr_packet.sizeBytes = data.size(); - EXPECT_EQ(H264SpsPpsTracker::kInsert, - tracker_.CopyAndFixBitstream(&idr_packet)); - EXPECT_EQ(320, idr_packet.width()); - EXPECT_EQ(240, idr_packet.height()); - delete[] idr_packet.dataPtr; + EXPECT_EQ(tracker_.CopyAndFixBitstream(data, &idr_header).action, + H264SpsPpsTracker::kInsert); + + EXPECT_EQ(idr_header.width, 320); + EXPECT_EQ(idr_header.height, 240); } } // namespace video_coding diff --git a/video/rtp_video_stream_receiver.cc b/video/rtp_video_stream_receiver.cc index 18a7c57f87..65047ad18d 100644 --- a/video/rtp_video_stream_receiver.cc +++ b/video/rtp_video_stream_receiver.cc @@ -443,7 +443,10 @@ void RtpVideoStreamReceiver::OnReceivedPayloadData( InsertSpsPpsIntoTracker(packet.payloadType); } - switch (tracker_.CopyAndFixBitstream(&packet)) { + video_coding::H264SpsPpsTracker::FixedBitstream fixed = + tracker_.CopyAndFixBitstream(codec_payload, &packet.video_header); + + switch (fixed.action) { case video_coding::H264SpsPpsTracker::kRequestKeyframe: rtcp_feedback_buffer_.RequestKeyFrame(); rtcp_feedback_buffer_.SendBufferedRtcpFeedback(); @@ -451,6 +454,8 @@ void RtpVideoStreamReceiver::OnReceivedPayloadData( case video_coding::H264SpsPpsTracker::kDrop: return; case video_coding::H264SpsPpsTracker::kInsert: + packet.dataPtr = fixed.data.release(); + packet.sizeBytes = fixed.size; break; }