Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit b9ca680

Browse files
Check H264 NALUs for frametype and insert SPS/PPS packets into the PacketBuffer.
BUG=chromium:719095 Review-Url: https://codereview.webrtc.org/2889163003 Cr-Original-Commit-Position: refs/heads/master@{#18214} Review-Url: https://codereview.webrtc.org/2916433003 . Cr-Commit-Position: refs/branch-heads/59@{#14} Cr-Branched-From: 10d095d-refs/heads/master@{#17657}
1 parent ab7f856 commit b9ca680

File tree

3 files changed

+66
-33
lines changed

3 files changed

+66
-33
lines changed

webrtc/modules/video_coding/frame_object.cc

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
#include "webrtc/base/checks.h"
12+
#include "webrtc/common_video/h264/h264_common.h"
1213
#include "webrtc/modules/video_coding/frame_object.h"
1314
#include "webrtc/modules/video_coding/packet_buffer.h"
1415

@@ -65,7 +66,32 @@ RtpFrameObject::RtpFrameObject(PacketBuffer* packet_buffer,
6566

6667
_buffer = new uint8_t[_size];
6768
_length = frame_size;
68-
_frameType = first_packet->frameType;
69+
70+
// For H264 frames we can't determine the frame type by just looking at the
71+
// first packet. Instead we consider the frame to be a keyframe if it
72+
// contains an IDR NALU.
73+
if (codec_type_ == kVideoCodecH264) {
74+
_frameType = kVideoFrameDelta;
75+
frame_type_ = kVideoFrameDelta;
76+
for (uint16_t seq_num = first_seq_num;
77+
seq_num != last_seq_num + 1 && _frameType == kVideoFrameDelta;
78+
++seq_num) {
79+
VCMPacket* packet = packet_buffer_->GetPacket(seq_num);
80+
RTC_DCHECK(packet);
81+
const RTPVideoHeaderH264& header = packet->video_header.codecHeader.H264;
82+
for (size_t i = 0; i < header.nalus_length; ++i) {
83+
if (header.nalus[i].type == H264::NaluType::kIdr) {
84+
_frameType = kVideoFrameKey;
85+
frame_type_ = kVideoFrameKey;
86+
break;
87+
}
88+
}
89+
}
90+
} else {
91+
_frameType = first_packet->frameType;
92+
frame_type_ = first_packet->frameType;
93+
}
94+
6995
GetBitstream(_buffer);
7096
_encodedWidth = first_packet->width;
7197
_encodedHeight = first_packet->height;

webrtc/modules/video_coding/h264_sps_pps_tracker.cc

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,9 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream(
3737
const RTPVideoHeader& video_header = packet->video_header;
3838
const RTPVideoHeaderH264& codec_header = video_header.codecHeader.H264;
3939

40-
// Packets that only contains SPS/PPS are not decodable by themselves, and
41-
// to avoid frames being created containing only these two nalus we don't
42-
// insert them into the PacketBuffer. Instead we save the SPS/PPS and
43-
// prepend the bitstream of first packet of an IDR referring to the
44-
// corresponding SPS/PPS id.
45-
bool insert_packet = codec_header.nalus_length == 0 ? true : false;
46-
4740
int pps_id = -1;
4841
int sps_id = -1;
42+
bool append_sps_pps = codec_header.nalus_length == 0;
4943
size_t required_size = 0;
5044
for (size_t i = 0; i < codec_header.nalus_length; ++i) {
5145
const NaluInfo& nalu = codec_header.nalus[i];
@@ -101,15 +95,28 @@ H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream(
10195
FALLTHROUGH();
10296
}
10397
default: {
104-
// Something other than an SPS/PPS nalu in this packet, then it should
105-
// be inserted into the PacketBuffer.
106-
insert_packet = true;
98+
// Something other than an SPS/PPS nalu in this packet, then the SPS/PPS
99+
// should be appended.
100+
append_sps_pps = true;
107101
}
108102
}
109103
}
110104

111-
if (!insert_packet)
112-
return kDrop;
105+
if (!append_sps_pps) {
106+
// Two things: Firstly, when we receive a packet the data pointed at by
107+
// |dataPtr| is volatile, meaning we have to copy the data into our own
108+
// buffer if we want to use it at a later stage. Secondly, when a packet is
109+
// inserted into the PacketBuffer it expects the packet to own its own
110+
// buffer, and this function copies (and fix) the bitstream of the packet
111+
// into its own buffer.
112+
//
113+
// SPS/PPS packets is a special case. Since we save the SPS/PPS NALU and
114+
// append it to the first packet of every IDR frame the SPS/PPS packet
115+
// doesn't actually need to contain any bitstream data.
116+
packet->dataPtr = nullptr;
117+
packet->sizeBytes = 0;
118+
return kInsert;
119+
}
113120

114121
// Calculate how much space we need for the rest of the bitstream.
115122
if (codec_header.packetization_type == kH264StapA) {

webrtc/modules/video_coding/h264_sps_pps_tracker_unittest.cc

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ TEST_F(TestH264SpsPpsTracker, SpsPpsPacketThenIdrFirstPacket) {
198198
AddPps(&sps_pps_packet, 0, 1, &data);
199199
sps_pps_packet.dataPtr = data.data();
200200
sps_pps_packet.sizeBytes = data.size();
201-
EXPECT_EQ(H264SpsPpsTracker::kDrop,
201+
EXPECT_EQ(H264SpsPpsTracker::kInsert,
202202
tracker_.CopyAndFixBitstream(&sps_pps_packet));
203203
data.clear();
204204

@@ -335,28 +335,28 @@ TEST_F(TestH264SpsPpsTracker, SaveRestoreWidthHeight) {
335335

336336
// Insert an SPS/PPS packet with width/height and make sure
337337
// that information is set on the first IDR packet.
338-
VCMPacket sps_pps_packet1 = GetDefaultPacket();
339-
AddSps(&sps_pps_packet1, 0, &data);
340-
AddPps(&sps_pps_packet1, 0, 1, &data);
341-
sps_pps_packet1.dataPtr = data.data();
342-
sps_pps_packet1.sizeBytes = data.size();
343-
sps_pps_packet1.width = 320;
344-
sps_pps_packet1.height = 240;
345-
EXPECT_EQ(H264SpsPpsTracker::kDrop,
346-
tracker_.CopyAndFixBitstream(&sps_pps_packet1));
347-
348-
VCMPacket idr_packet1 = GetDefaultPacket();
349-
idr_packet1.video_header.is_first_packet_in_frame = true;
350-
AddIdr(&idr_packet1, 1);
338+
VCMPacket sps_pps_packet = GetDefaultPacket();
339+
AddSps(&sps_pps_packet, 0, &data);
340+
AddPps(&sps_pps_packet, 0, 1, &data);
341+
sps_pps_packet.dataPtr = data.data();
342+
sps_pps_packet.sizeBytes = data.size();
343+
sps_pps_packet.width = 320;
344+
sps_pps_packet.height = 240;
345+
EXPECT_EQ(H264SpsPpsTracker::kInsert,
346+
tracker_.CopyAndFixBitstream(&sps_pps_packet));
347+
348+
VCMPacket idr_packet = GetDefaultPacket();
349+
idr_packet.video_header.is_first_packet_in_frame = true;
350+
AddIdr(&idr_packet, 1);
351351
data.insert(data.end(), {1, 2, 3});
352-
idr_packet1.dataPtr = data.data();
353-
idr_packet1.sizeBytes = data.size();
352+
idr_packet.dataPtr = data.data();
353+
idr_packet.sizeBytes = data.size();
354354
EXPECT_EQ(H264SpsPpsTracker::kInsert,
355-
tracker_.CopyAndFixBitstream(&idr_packet1));
355+
tracker_.CopyAndFixBitstream(&idr_packet));
356356

357-
EXPECT_EQ(320, idr_packet1.width);
358-
EXPECT_EQ(240, idr_packet1.height);
359-
delete[] idr_packet1.dataPtr;
357+
EXPECT_EQ(320, idr_packet.width);
358+
EXPECT_EQ(240, idr_packet.height);
359+
delete[] idr_packet.dataPtr;
360360
}
361361

362362
} // namespace video_coding

0 commit comments

Comments
 (0)