Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: webrtc/modules/video_coding/h264_sps_pps_tracker.cc

Issue 2466993003: H264SpsPpsTracker class which keep tracks of SPS/PPS. (Closed)
Patch Set: Feedback fixes. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/video_coding/h264_sps_pps_tracker.h"
12
13 #include <string>
14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/base/logging.h"
17 #include "webrtc/common_video/h264/h264_common.h"
18 #include "webrtc/modules/video_coding/frame_object.h"
19 #include "webrtc/modules/video_coding/packet_buffer.h"
20
21 namespace webrtc {
22 namespace video_coding {
23
24 namespace {
25 const uint8_t start_code_h264[] = {0, 0, 0, 1};
26 } // namespace
27
28 bool H264SpsPpsTracker::CopyAndFixBitstream(VCMPacket* packet) {
29 RTC_DCHECK(packet->codec == kVideoCodecH264);
30
31 const uint8_t* data = packet->dataPtr;
32 const size_t data_size = packet->sizeBytes;
33 const RTPVideoHeader& video_header = packet->video_header;
34 const RTPVideoHeaderH264& codec_header = video_header.codecHeader.H264;
35
36 // Packets that only contains SPS/PPS are not decodable by themself, and
37 // to avoid frames being created contining only these two nalus we don't
stefan-webrtc 2016/11/02 14:54:38 containing
philipel 2016/11/02 15:11:07 Done.
38 // insert them into the PacketBuffer. Instead we save the SPS/PPS and
39 // prepend the bitstream of first packet of an IDR with the SPS/PPS instead.
stefan-webrtc 2016/11/02 14:54:38 "of an IDR referring to the corresponding sps/pps
philipel 2016/11/02 15:11:07 Done.
40 bool insert_packet = codec_header.nalus_length == 0 ? true : false;
41
42 int pps_id = -1;
43 size_t required_size = 0;
44 for (size_t i = 0; i < codec_header.nalus_length; ++i) {
45 const NaluInfo& nalu = codec_header.nalus[i];
46 switch (nalu.type) {
47 case H264::NaluType::kSps: {
48 // Save SPS.
49 sps_data_[nalu.sps_id].size = nalu.size;
50 sps_data_[nalu.sps_id].data.reset(new uint8_t[nalu.size]);
51 memcpy(sps_data_[nalu.sps_id].data.get(), data + nalu.offset,
52 nalu.size);
53 break;
54 }
55 case H264::NaluType::kPps: {
56 // Save PPS.
57 pps_data_[nalu.pps_id].sps_id = nalu.sps_id;
58 pps_data_[nalu.pps_id].size = nalu.size;
59 pps_data_[nalu.pps_id].data.reset(new uint8_t[nalu.size]);
60 memcpy(pps_data_[nalu.pps_id].data.get(), data + nalu.offset,
61 nalu.size);
62 break;
63 }
64 case H264::NaluType::kIdr: {
65 // If this is the first packet of an IDR, make sure we have the required
66 // SPS/PPS and also calculate how much extra space we need in the buffer
67 // to prepend the SPS/PPS to the bitstream with start codes.
68 if (video_header.isFirstPacket) {
69 if (nalu.pps_id == -1) {
70 LOG(LS_WARNING) << "No PPS id in IDR nalu.";
71 return false;
72 }
73
74 auto pps = pps_data_.find(nalu.pps_id);
75 if (pps == pps_data_.end()) {
76 LOG(LS_WARNING) << "No PPS with id << " << nalu.pps_id
77 << " received";
78 return false;
79 }
80
81 auto sps = sps_data_.find(pps->second.sps_id);
82 if (sps == sps_data_.end()) {
83 LOG(LS_WARNING) << "No SPS with id << "
84 << pps_data_[nalu.pps_id].sps_id << " received";
85 return false;
86 }
87
88 pps_id = nalu.pps_id;
89 required_size += pps->second.size + sizeof(start_code_h264);
90 required_size += sps->second.size + sizeof(start_code_h264);
91 }
92 FALLTHROUGH();
93 }
94 default: {
95 // Something other than an SPS/PPS nalu in this packet, then it should
96 // be inserted into the PacketBuffer.
97 insert_packet = true;
98 }
99 }
100 }
101
102 if (!insert_packet)
103 return false;
104
105 // Calculate how much space we need for the rest of the bitstream.
106 switch (codec_header.packetization_type) {
107 case kH264StapA: {
108 const uint8_t* nalu_ptr = data + 1;
109 while (nalu_ptr < data + data_size) {
110 RTC_DCHECK(video_header.isFirstPacket);
111 required_size += sizeof(start_code_h264);
112
113 // The first two bytes describe the length of a segment.
114 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
115 nalu_ptr += 2;
116
117 required_size += segment_length;
118 nalu_ptr += segment_length;
119 }
120 break;
121 }
122 case kH264SingleNalu: {
123 required_size += sizeof(start_code_h264);
124 FALLTHROUGH();
125 }
126 case kH264FuA: {
127 required_size += data_size;
stefan-webrtc 2016/11/02 14:54:38 You still need to add start code if this is the fi
philipel 2016/11/02 15:11:07 Yes, added a unittest for this case.
128 }
129 }
130
131 // Then we copy to the new buffer.
132 uint8_t* buffer = new uint8_t[required_size];
133 uint8_t* insert_at = buffer;
134
135 // If pps_id != -1 then we have the SPS/PPS and they should be prepended
136 // to the bitstream with start codes inserted.
137 if (pps_id != -1) {
138 // Insert SPS.
139 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
140 insert_at += sizeof(start_code_h264);
141 memcpy(insert_at, sps_data_[pps_data_[pps_id].sps_id].data.get(),
142 sps_data_[pps_data_[pps_id].sps_id].size);
143 insert_at += sps_data_[pps_data_[pps_id].sps_id].size;
144
145 // Insert PPS.
146 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
147 insert_at += sizeof(start_code_h264);
148 memcpy(insert_at, pps_data_[pps_id].data.get(), pps_data_[pps_id].size);
149 insert_at += pps_data_[pps_id].size;
150 }
151
152 // Copy the rest of the bitstream and insert start codes.
153 switch (codec_header.packetization_type) {
154 case kH264StapA: {
155 const uint8_t* nalu_ptr = data + 1;
156 while (nalu_ptr < data + data_size) {
157 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
158 insert_at += sizeof(start_code_h264);
159
160 // The first two bytes describes the length of a segment.
161 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
162 nalu_ptr += 2;
163
164 memcpy(insert_at, nalu_ptr, segment_length);
165 insert_at += segment_length;
166 nalu_ptr += segment_length;
167 }
168 break;
169 }
170 case kH264SingleNalu: {
171 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
172 insert_at += sizeof(start_code_h264);
173 FALLTHROUGH();
174 }
175 case kH264FuA: {
176 memcpy(insert_at, data, data_size);
177 }
178 }
179
180 packet->dataPtr = buffer;
181 packet->sizeBytes = required_size;
182 return true;
183 }
184
185 } // namespace video_coding
186 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/h264_sps_pps_tracker.h ('k') | webrtc/modules/video_coding/h264_sps_pps_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698