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

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

Issue 2945853002: Only append SPS/PPS to bitstream if supplied out of bound. (Closed)
Patch Set: delete[] sps/pps data in unittests Created 3 years, 6 months 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
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 19 matching lines...) Expand all
30 30
31 H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream( 31 H264SpsPpsTracker::PacketAction H264SpsPpsTracker::CopyAndFixBitstream(
32 VCMPacket* packet) { 32 VCMPacket* packet) {
33 RTC_DCHECK(packet->codec == kVideoCodecH264); 33 RTC_DCHECK(packet->codec == kVideoCodecH264);
34 34
35 const uint8_t* data = packet->dataPtr; 35 const uint8_t* data = packet->dataPtr;
36 const size_t data_size = packet->sizeBytes; 36 const size_t data_size = packet->sizeBytes;
37 const RTPVideoHeader& video_header = packet->video_header; 37 const RTPVideoHeader& video_header = packet->video_header;
38 const RTPVideoHeaderH264& codec_header = video_header.codecHeader.H264; 38 const RTPVideoHeaderH264& codec_header = video_header.codecHeader.H264;
39 39
40 int pps_id = -1; 40 bool append_sps_pps = false;
41 int sps_id = -1; 41 auto sps = sps_data_.end();
42 bool append_sps_pps = codec_header.nalus_length == 0; 42 auto pps = pps_data_.end();
43 size_t required_size = 0; 43
44 for (size_t i = 0; i < codec_header.nalus_length; ++i) { 44 for (size_t i = 0; i < codec_header.nalus_length; ++i) {
45 const NaluInfo& nalu = codec_header.nalus[i]; 45 const NaluInfo& nalu = codec_header.nalus[i];
46 switch (nalu.type) { 46 switch (nalu.type) {
47 case H264::NaluType::kSps: { 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 sps_data_[nalu.sps_id].width = packet->width; 48 sps_data_[nalu.sps_id].width = packet->width;
54 sps_data_[nalu.sps_id].height = packet->height; 49 sps_data_[nalu.sps_id].height = packet->height;
55 break; 50 break;
56 } 51 }
57 case H264::NaluType::kPps: { 52 case H264::NaluType::kPps: {
58 // Save PPS.
59 pps_data_[nalu.pps_id].sps_id = nalu.sps_id; 53 pps_data_[nalu.pps_id].sps_id = nalu.sps_id;
60 pps_data_[nalu.pps_id].size = nalu.size;
61 pps_data_[nalu.pps_id].data.reset(new uint8_t[nalu.size]);
62 memcpy(pps_data_[nalu.pps_id].data.get(), data + nalu.offset,
63 nalu.size);
64 break; 54 break;
65 } 55 }
66 case H264::NaluType::kIdr: { 56 case H264::NaluType::kIdr: {
67 // If this is the first packet of an IDR, make sure we have the required 57 // If this is the first packet of an IDR, make sure we have the required
68 // SPS/PPS and also calculate how much extra space we need in the buffer 58 // SPS/PPS and also calculate how much extra space we need in the buffer
69 // to prepend the SPS/PPS to the bitstream with start codes. 59 // to prepend the SPS/PPS to the bitstream with start codes.
70 if (video_header.is_first_packet_in_frame) { 60 if (video_header.is_first_packet_in_frame) {
71 if (nalu.pps_id == -1) { 61 if (nalu.pps_id == -1) {
72 LOG(LS_WARNING) << "No PPS id in IDR nalu."; 62 LOG(LS_WARNING) << "No PPS id in IDR nalu.";
73 return kRequestKeyframe; 63 return kRequestKeyframe;
74 } 64 }
75 65
76 auto pps = pps_data_.find(nalu.pps_id); 66 pps = pps_data_.find(nalu.pps_id);
77 if (pps == pps_data_.end()) { 67 if (pps == pps_data_.end()) {
78 LOG(LS_WARNING) << "No PPS with id << " << nalu.pps_id 68 LOG(LS_WARNING) << "No PPS with id << " << nalu.pps_id
79 << " received"; 69 << " received";
80 return kRequestKeyframe; 70 return kRequestKeyframe;
81 } 71 }
82 72
83 sps_id = pps->second.sps_id; 73 sps = sps_data_.find(pps->second.sps_id);
84 auto sps = sps_data_.find(sps_id);
85 if (sps == sps_data_.end()) { 74 if (sps == sps_data_.end()) {
86 LOG(LS_WARNING) << "No SPS with id << " 75 LOG(LS_WARNING)
87 << pps_data_[nalu.pps_id].sps_id << " received"; 76 << "No SPS with id << " << pps->second.sps_id << " received";
88 return kRequestKeyframe; 77 return kRequestKeyframe;
89 } 78 }
90 79
91 pps_id = nalu.pps_id; 80 // Since the first packet of every keyframe should have its width and
92 required_size += pps->second.size + sizeof(start_code_h264); 81 // height set we set it here in the case of it being supplied out of
93 required_size += sps->second.size + sizeof(start_code_h264); 82 // band.
83 packet->width = sps->second.width;
84 packet->height = sps->second.height;
85
86 // If the SPS/PPS was supplied out of band then we will have saved
87 // the actual bitstream in |data|.
88 if (sps->second.data && pps->second.data) {
89 RTC_DCHECK_GT(sps->second.size, 0);
90 RTC_DCHECK_GT(pps->second.size, 0);
91 append_sps_pps = true;
92 }
94 } 93 }
95 FALLTHROUGH(); 94 break;
96 } 95 }
97 default: { 96 default:
98 // Something other than an SPS/PPS nalu in this packet, then the SPS/PPS 97 break;
99 // should be appended.
100 append_sps_pps = true;
101 }
102 } 98 }
103 } 99 }
104 100
105 if (!append_sps_pps) { 101 RTC_CHECK(!append_sps_pps ||
106 // Two things: Firstly, when we receive a packet the data pointed at by 102 (sps != sps_data_.end() && pps != pps_data_.end()));
107 // |dataPtr| is volatile, meaning we have to copy the data into our own 103
108 // buffer if we want to use it at a later stage. Secondly, when a packet is 104 // Calculate how much space we need for the rest of the bitstream.
109 // inserted into the PacketBuffer it expects the packet to own its own 105 size_t required_size = 0;
110 // buffer, and this function copies (and fix) the bitstream of the packet 106
111 // into its own buffer. 107 if (append_sps_pps) {
112 // 108 required_size += sps->second.size + sizeof(start_code_h264);
113 // SPS/PPS packets is a special case. Since we save the SPS/PPS NALU and 109 required_size += pps->second.size + sizeof(start_code_h264);
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 } 110 }
120 111
121 // Calculate how much space we need for the rest of the bitstream.
122 if (codec_header.packetization_type == kH264StapA) { 112 if (codec_header.packetization_type == kH264StapA) {
123 const uint8_t* nalu_ptr = data + 1; 113 const uint8_t* nalu_ptr = data + 1;
124 while (nalu_ptr < data + data_size) { 114 while (nalu_ptr < data + data_size) {
125 RTC_DCHECK(video_header.is_first_packet_in_frame); 115 RTC_DCHECK(video_header.is_first_packet_in_frame);
126 required_size += sizeof(start_code_h264); 116 required_size += sizeof(start_code_h264);
127 117
128 // The first two bytes describe the length of a segment. 118 // The first two bytes describe the length of a segment.
129 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1]; 119 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
130 nalu_ptr += 2; 120 nalu_ptr += 2;
131 121
132 required_size += segment_length; 122 required_size += segment_length;
133 nalu_ptr += segment_length; 123 nalu_ptr += segment_length;
134 } 124 }
135 } else { 125 } else {
136 if (video_header.is_first_packet_in_frame) 126 if (video_header.is_first_packet_in_frame)
137 required_size += sizeof(start_code_h264); 127 required_size += sizeof(start_code_h264);
138 required_size += data_size; 128 required_size += data_size;
139 } 129 }
140 130
141 // Then we copy to the new buffer. 131 // Then we copy to the new buffer.
142 uint8_t* buffer = new uint8_t[required_size]; 132 uint8_t* buffer = new uint8_t[required_size];
143 uint8_t* insert_at = buffer; 133 uint8_t* insert_at = buffer;
144 134
145 // If pps_id != -1 then we have the SPS/PPS and they should be prepended 135 if (append_sps_pps) {
146 // to the bitstream with start codes inserted.
147 if (pps_id != -1) {
148 // Insert SPS. 136 // Insert SPS.
149 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 137 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
150 insert_at += sizeof(start_code_h264); 138 insert_at += sizeof(start_code_h264);
151 memcpy(insert_at, sps_data_[pps_data_[pps_id].sps_id].data.get(), 139 memcpy(insert_at, sps->second.data.get(), sps->second.size);
152 sps_data_[pps_data_[pps_id].sps_id].size); 140 insert_at += sps->second.size;
153 insert_at += sps_data_[pps_data_[pps_id].sps_id].size;
154 141
155 // Insert PPS. 142 // Insert PPS.
156 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 143 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
157 insert_at += sizeof(start_code_h264); 144 insert_at += sizeof(start_code_h264);
158 memcpy(insert_at, pps_data_[pps_id].data.get(), pps_data_[pps_id].size); 145 memcpy(insert_at, pps->second.data.get(), pps->second.size);
159 insert_at += pps_data_[pps_id].size; 146 insert_at += pps->second.size;
160 } 147 }
161 148
162 // Copy the rest of the bitstream and insert start codes. 149 // Copy the rest of the bitstream and insert start codes.
163 if (codec_header.packetization_type == kH264StapA) { 150 if (codec_header.packetization_type == kH264StapA) {
164 const uint8_t* nalu_ptr = data + 1; 151 const uint8_t* nalu_ptr = data + 1;
165 while (nalu_ptr < data + data_size) { 152 while (nalu_ptr < data + data_size) {
166 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 153 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
167 insert_at += sizeof(start_code_h264); 154 insert_at += sizeof(start_code_h264);
168 155
169 // The first two bytes describe the length of a segment. 156 // The first two bytes describe the length of a segment.
(...skipping 11 matching lines...) Expand all
181 nalu_ptr += segment_length; 168 nalu_ptr += segment_length;
182 } 169 }
183 } else { 170 } else {
184 if (video_header.is_first_packet_in_frame) { 171 if (video_header.is_first_packet_in_frame) {
185 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 172 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
186 insert_at += sizeof(start_code_h264); 173 insert_at += sizeof(start_code_h264);
187 } 174 }
188 memcpy(insert_at, data, data_size); 175 memcpy(insert_at, data, data_size);
189 } 176 }
190 177
191 if (sps_id != -1) {
192 packet->width = sps_data_[sps_id].width;
193 packet->height = sps_data_[sps_id].height;
194 }
195
196 packet->dataPtr = buffer; 178 packet->dataPtr = buffer;
197 packet->sizeBytes = required_size; 179 packet->sizeBytes = required_size;
198 return kInsert; 180 return kInsert;
199 } 181 }
200 182
201 void H264SpsPpsTracker::InsertSpsPpsNalus(const std::vector<uint8_t>& sps, 183 void H264SpsPpsTracker::InsertSpsPpsNalus(const std::vector<uint8_t>& sps,
202 const std::vector<uint8_t>& pps) { 184 const std::vector<uint8_t>& pps) {
203 constexpr size_t kNaluHeaderOffset = 1; 185 constexpr size_t kNaluHeaderOffset = 1;
204 if (sps.size() < kNaluHeaderOffset) { 186 if (sps.size() < kNaluHeaderOffset) {
205 LOG(LS_WARNING) << "SPS size " << sps.size() << " is smaller than " 187 LOG(LS_WARNING) << "SPS size " << sps.size() << " is smaller than "
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 pps_info.data.reset(pps_data); 235 pps_info.data.reset(pps_data);
254 pps_data_[parsed_pps->id] = std::move(pps_info); 236 pps_data_[parsed_pps->id] = std::move(pps_info);
255 237
256 LOG(LS_INFO) << "Inserted SPS id " << parsed_sps->id << " and PPS id " 238 LOG(LS_INFO) << "Inserted SPS id " << parsed_sps->id << " and PPS id "
257 << parsed_pps->id << " (referencing SPS " << parsed_pps->sps_id 239 << parsed_pps->id << " (referencing SPS " << parsed_pps->sps_id
258 << ")"; 240 << ")";
259 } 241 }
260 242
261 } // namespace video_coding 243 } // namespace video_coding
262 } // namespace webrtc 244 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698