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

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: 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 if (sps->second.data && pps->second.data) {
92 required_size += pps->second.size + sizeof(start_code_h264); 81 RTC_DCHECK_LE(0, sps->second.size);
93 required_size += sps->second.size + sizeof(start_code_h264); 82 RTC_DCHECK_LE(0, pps->second.size);
stefan-webrtc 2017/06/20 08:56:31 I'd prefer RTC_DCHECK_GT(sps->second.size, 0)
philipel 2017/06/20 11:27:34 Done.
83 append_sps_pps = true;
84 }
94 } 85 }
95 FALLTHROUGH(); 86 FALLTHROUGH();
stefan-webrtc 2017/06/20 08:56:31 No point in FALLTHROUGH now, right? Might as well
philipel 2017/06/20 11:27:34 Done.
96 } 87 }
97 default: { 88 default: { break; }
stefan-webrtc 2017/06/20 08:56:31 Remove {}
philipel 2017/06/20 11:27:34 Done.
98 // Something other than an SPS/PPS nalu in this packet, then the SPS/PPS
99 // should be appended.
100 append_sps_pps = true;
101 }
102 } 89 }
103 } 90 }
104 91
105 if (!append_sps_pps) { 92 RTC_CHECK(!append_sps_pps ||
106 // Two things: Firstly, when we receive a packet the data pointed at by 93 (sps != sps_data_.end() && pps != pps_data_.end()));
107 // |dataPtr| is volatile, meaning we have to copy the data into our own 94
108 // buffer if we want to use it at a later stage. Secondly, when a packet is 95 // 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 96 size_t required_size = 0;
110 // buffer, and this function copies (and fix) the bitstream of the packet 97 if (append_sps_pps) {
111 // into its own buffer. 98 required_size += sps->second.size + sizeof(start_code_h264);
112 // 99 required_size += pps->second.size + sizeof(start_code_h264);
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 } 100 }
120 101
121 // Calculate how much space we need for the rest of the bitstream.
122 if (codec_header.packetization_type == kH264StapA) { 102 if (codec_header.packetization_type == kH264StapA) {
123 const uint8_t* nalu_ptr = data + 1; 103 const uint8_t* nalu_ptr = data + 1;
124 while (nalu_ptr < data + data_size) { 104 while (nalu_ptr < data + data_size) {
125 RTC_DCHECK(video_header.is_first_packet_in_frame); 105 RTC_DCHECK(video_header.is_first_packet_in_frame);
126 required_size += sizeof(start_code_h264); 106 required_size += sizeof(start_code_h264);
127 107
128 // The first two bytes describe the length of a segment. 108 // The first two bytes describe the length of a segment.
129 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1]; 109 uint16_t segment_length = nalu_ptr[0] << 8 | nalu_ptr[1];
130 nalu_ptr += 2; 110 nalu_ptr += 2;
131 111
132 required_size += segment_length; 112 required_size += segment_length;
133 nalu_ptr += segment_length; 113 nalu_ptr += segment_length;
134 } 114 }
135 } else { 115 } else {
136 if (video_header.is_first_packet_in_frame) 116 if (video_header.is_first_packet_in_frame)
137 required_size += sizeof(start_code_h264); 117 required_size += sizeof(start_code_h264);
138 required_size += data_size; 118 required_size += data_size;
139 } 119 }
140 120
141 // Then we copy to the new buffer. 121 // Then we copy to the new buffer.
142 uint8_t* buffer = new uint8_t[required_size]; 122 uint8_t* buffer = new uint8_t[required_size];
143 uint8_t* insert_at = buffer; 123 uint8_t* insert_at = buffer;
144 124
145 // If pps_id != -1 then we have the SPS/PPS and they should be prepended 125 if (append_sps_pps) {
146 // to the bitstream with start codes inserted.
147 if (pps_id != -1) {
148 // Insert SPS. 126 // Insert SPS.
149 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 127 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
150 insert_at += sizeof(start_code_h264); 128 insert_at += sizeof(start_code_h264);
151 memcpy(insert_at, sps_data_[pps_data_[pps_id].sps_id].data.get(), 129 memcpy(insert_at, sps->second.data.get(), sps->second.size);
152 sps_data_[pps_data_[pps_id].sps_id].size); 130 insert_at += sps->second.size;
153 insert_at += sps_data_[pps_data_[pps_id].sps_id].size;
154 131
155 // Insert PPS. 132 // Insert PPS.
156 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 133 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
157 insert_at += sizeof(start_code_h264); 134 insert_at += sizeof(start_code_h264);
158 memcpy(insert_at, pps_data_[pps_id].data.get(), pps_data_[pps_id].size); 135 memcpy(insert_at, pps->second.data.get(), pps->second.size);
159 insert_at += pps_data_[pps_id].size; 136 insert_at += pps->second.size;
160 } 137 }
161 138
162 // Copy the rest of the bitstream and insert start codes. 139 // Copy the rest of the bitstream and insert start codes.
163 if (codec_header.packetization_type == kH264StapA) { 140 if (codec_header.packetization_type == kH264StapA) {
164 const uint8_t* nalu_ptr = data + 1; 141 const uint8_t* nalu_ptr = data + 1;
165 while (nalu_ptr < data + data_size) { 142 while (nalu_ptr < data + data_size) {
166 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 143 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
167 insert_at += sizeof(start_code_h264); 144 insert_at += sizeof(start_code_h264);
168 145
169 // The first two bytes describe the length of a segment. 146 // The first two bytes describe the length of a segment.
(...skipping 11 matching lines...) Expand all
181 nalu_ptr += segment_length; 158 nalu_ptr += segment_length;
182 } 159 }
183 } else { 160 } else {
184 if (video_header.is_first_packet_in_frame) { 161 if (video_header.is_first_packet_in_frame) {
185 memcpy(insert_at, start_code_h264, sizeof(start_code_h264)); 162 memcpy(insert_at, start_code_h264, sizeof(start_code_h264));
186 insert_at += sizeof(start_code_h264); 163 insert_at += sizeof(start_code_h264);
187 } 164 }
188 memcpy(insert_at, data, data_size); 165 memcpy(insert_at, data, data_size);
189 } 166 }
190 167
191 if (sps_id != -1) { 168 if (sps != sps_data_.end()) {
192 packet->width = sps_data_[sps_id].width; 169 packet->width = sps->second.width;
193 packet->height = sps_data_[sps_id].height; 170 packet->height = sps->second.height;
stefan-webrtc 2017/06/20 08:56:31 Should this be moved up lines 125-137? Maybe also
philipel 2017/06/20 11:27:34 Done.
194 } 171 }
195 172
196 packet->dataPtr = buffer; 173 packet->dataPtr = buffer;
197 packet->sizeBytes = required_size; 174 packet->sizeBytes = required_size;
198 return kInsert; 175 return kInsert;
199 } 176 }
200 177
201 void H264SpsPpsTracker::InsertSpsPpsNalus(const std::vector<uint8_t>& sps, 178 void H264SpsPpsTracker::InsertSpsPpsNalus(const std::vector<uint8_t>& sps,
202 const std::vector<uint8_t>& pps) { 179 const std::vector<uint8_t>& pps) {
203 constexpr size_t kNaluHeaderOffset = 1; 180 constexpr size_t kNaluHeaderOffset = 1;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 pps_info.data.reset(pps_data); 230 pps_info.data.reset(pps_data);
254 pps_data_[parsed_pps->id] = std::move(pps_info); 231 pps_data_[parsed_pps->id] = std::move(pps_info);
255 232
256 LOG(LS_INFO) << "Inserted SPS id " << parsed_sps->id << " and PPS id " 233 LOG(LS_INFO) << "Inserted SPS id " << parsed_sps->id << " and PPS id "
257 << parsed_pps->id << " (referencing SPS " << parsed_pps->sps_id 234 << parsed_pps->id << " (referencing SPS " << parsed_pps->sps_id
258 << ")"; 235 << ")";
259 } 236 }
260 237
261 } // namespace video_coding 238 } // namespace video_coding
262 } // namespace webrtc 239 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698