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

Side by Side Diff: media/filters/h264_parser.cc

Issue 379983002: Fix AnnexB validation logic to work with encrypted content. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address CR comment Created 6 years, 4 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
« no previous file with comments | « media/filters/h264_parser.h ('k') | media/formats/mp4/avc.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/logging.h" 5 #include "base/logging.h"
6 #include "base/memory/scoped_ptr.h" 6 #include "base/memory/scoped_ptr.h"
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 8
9 #include "media/base/decrypt_config.h"
9 #include "media/filters/h264_parser.h" 10 #include "media/filters/h264_parser.h"
10 11
11 namespace media { 12 namespace media {
12 13
13 bool H264SliceHeader::IsPSlice() const { 14 bool H264SliceHeader::IsPSlice() const {
14 return (slice_type % 5 == kPSlice); 15 return (slice_type % 5 == kPSlice);
15 } 16 }
16 17
17 bool H264SliceHeader::IsBSlice() const { 18 bool H264SliceHeader::IsBSlice() const {
18 return (slice_type % 5 == kBSlice); 19 return (slice_type % 5 == kBSlice);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 } 123 }
123 124
124 H264Parser::~H264Parser() { 125 H264Parser::~H264Parser() {
125 STLDeleteValues(&active_SPSes_); 126 STLDeleteValues(&active_SPSes_);
126 STLDeleteValues(&active_PPSes_); 127 STLDeleteValues(&active_PPSes_);
127 } 128 }
128 129
129 void H264Parser::Reset() { 130 void H264Parser::Reset() {
130 stream_ = NULL; 131 stream_ = NULL;
131 bytes_left_ = 0; 132 bytes_left_ = 0;
133 encrypted_ranges_.clear();
132 } 134 }
133 135
134 void H264Parser::SetStream(const uint8* stream, off_t stream_size) { 136 void H264Parser::SetStream(const uint8* stream, off_t stream_size) {
137 std::vector<SubsampleEntry> subsamples;
138 SetEncryptedStream(stream, stream_size, subsamples);
139 }
140
141 void H264Parser::SetEncryptedStream(
142 const uint8* stream, off_t stream_size,
143 const std::vector<SubsampleEntry>& subsamples) {
135 DCHECK(stream); 144 DCHECK(stream);
136 DCHECK_GT(stream_size, 0); 145 DCHECK_GT(stream_size, 0);
137 146
138 stream_ = stream; 147 stream_ = stream;
139 bytes_left_ = stream_size; 148 bytes_left_ = stream_size;
149
150 encrypted_ranges_.clear();
151 const uint8* start = stream;
152 const uint8* stream_end = stream_ + bytes_left_;
153 for (size_t i = 0; i < subsamples.size() && start < stream_end; ++i) {
154 start += subsamples[i].clear_bytes;
155
156 const uint8* end = std::min(start + subsamples[i].cypher_bytes, stream_end);
157 encrypted_ranges_.Add(start, end);
158 start = end;
159 }
140 } 160 }
141 161
142 const H264PPS* H264Parser::GetPPS(int pps_id) { 162 const H264PPS* H264Parser::GetPPS(int pps_id) {
143 return active_PPSes_[pps_id]; 163 return active_PPSes_[pps_id];
144 } 164 }
145 165
146 const H264SPS* H264Parser::GetSPS(int sps_id) { 166 const H264SPS* H264Parser::GetSPS(int sps_id) {
147 return active_SPSes_[sps_id]; 167 return active_SPSes_[sps_id];
148 } 168 }
149 169
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 // |*offset| is equal to 0 (valid offset). 204 // |*offset| is equal to 0 (valid offset).
185 *offset = data_size - bytes_left; 205 *offset = data_size - bytes_left;
186 *start_code_size = 0; 206 *start_code_size = 0;
187 return false; 207 return false;
188 } 208 }
189 209
190 bool H264Parser::LocateNALU(off_t* nalu_size, off_t* start_code_size) { 210 bool H264Parser::LocateNALU(off_t* nalu_size, off_t* start_code_size) {
191 // Find the start code of next NALU. 211 // Find the start code of next NALU.
192 off_t nalu_start_off = 0; 212 off_t nalu_start_off = 0;
193 off_t annexb_start_code_size = 0; 213 off_t annexb_start_code_size = 0;
194 if (!FindStartCode(stream_, bytes_left_, 214
195 &nalu_start_off, &annexb_start_code_size)) { 215 if (!FindStartCodeInClearRanges(stream_, bytes_left_,
216 &nalu_start_off, &annexb_start_code_size)) {
196 DVLOG(4) << "Could not find start code, end of stream?"; 217 DVLOG(4) << "Could not find start code, end of stream?";
197 return false; 218 return false;
198 } 219 }
199 220
200 // Move the stream to the beginning of the NALU (pointing at the start code). 221 // Move the stream to the beginning of the NALU (pointing at the start code).
201 stream_ += nalu_start_off; 222 stream_ += nalu_start_off;
202 bytes_left_ -= nalu_start_off; 223 bytes_left_ -= nalu_start_off;
203 224
204 const uint8* nalu_data = stream_ + annexb_start_code_size; 225 const uint8* nalu_data = stream_ + annexb_start_code_size;
205 off_t max_nalu_data_size = bytes_left_ - annexb_start_code_size; 226 off_t max_nalu_data_size = bytes_left_ - annexb_start_code_size;
206 if (max_nalu_data_size <= 0) { 227 if (max_nalu_data_size <= 0) {
207 DVLOG(3) << "End of stream"; 228 DVLOG(3) << "End of stream";
208 return false; 229 return false;
209 } 230 }
210 231
211 // Find the start code of next NALU; 232 // Find the start code of next NALU;
212 // if successful, |nalu_size_without_start_code| is the number of bytes from 233 // if successful, |nalu_size_without_start_code| is the number of bytes from
213 // after previous start code to before this one; 234 // after previous start code to before this one;
214 // if next start code is not found, it is still a valid NALU since there 235 // if next start code is not found, it is still a valid NALU since there
215 // are some bytes left after the first start code: all the remaining bytes 236 // are some bytes left after the first start code: all the remaining bytes
216 // belong to the current NALU. 237 // belong to the current NALU.
217 off_t next_start_code_size = 0; 238 off_t next_start_code_size = 0;
218 off_t nalu_size_without_start_code = 0; 239 off_t nalu_size_without_start_code = 0;
219 if (!FindStartCode(nalu_data, max_nalu_data_size, 240 if (!FindStartCodeInClearRanges(nalu_data, max_nalu_data_size,
220 &nalu_size_without_start_code, &next_start_code_size)) { 241 &nalu_size_without_start_code,
242 &next_start_code_size)) {
221 nalu_size_without_start_code = max_nalu_data_size; 243 nalu_size_without_start_code = max_nalu_data_size;
222 } 244 }
223 *nalu_size = nalu_size_without_start_code + annexb_start_code_size; 245 *nalu_size = nalu_size_without_start_code + annexb_start_code_size;
224 *start_code_size = annexb_start_code_size; 246 *start_code_size = annexb_start_code_size;
225 return true; 247 return true;
226 } 248 }
227 249
250 bool H264Parser::FindStartCodeInClearRanges(
251 const uint8* data,
252 off_t data_size,
253 off_t* offset,
254 off_t* start_code_size) {
255 if (encrypted_ranges_.size() == 0)
256 return FindStartCode(data, data_size, offset, start_code_size);
257
258 DCHECK_GE(data_size, 0);
259 const uint8* start = data;
260 do {
261 off_t bytes_left = data_size - (start - data);
262
263 if (!FindStartCode(start, bytes_left, offset, start_code_size))
264 return false;
265
266 // Construct a Ranges object that represents the region occupied
267 // by the start code and the 1 byte needed to read the NAL unit type.
268 const uint8* start_code = start + *offset;
269 const uint8* start_code_end = start_code + *start_code_size;
270 Ranges<const uint8*> start_code_range;
271 start_code_range.Add(start_code, start_code_end + 1);
272
273 if (encrypted_ranges_.IntersectionWith(start_code_range).size() > 0) {
274 // The start code is inside an encrypted section so we need to scan
275 // for another start code.
276 *start_code_size = 0;
277 start += std::min(*offset + 1, bytes_left);
278 }
279 } while (*start_code_size == 0);
280
281 // Update |*offset| to include the data we skipped over.
282 *offset += start - data;
283 return true;
284 }
285
228 H264Parser::Result H264Parser::ReadUE(int* val) { 286 H264Parser::Result H264Parser::ReadUE(int* val) {
229 int num_bits = -1; 287 int num_bits = -1;
230 int bit; 288 int bit;
231 int rest; 289 int rest;
232 290
233 // Count the number of contiguous zero bits. 291 // Count the number of contiguous zero bits.
234 do { 292 do {
235 READ_BITS_OR_RETURN(1, &bit); 293 READ_BITS_OR_RETURN(1, &bit);
236 num_bits++; 294 num_bits++;
237 } while (bit == 0); 295 } while (bit == 0);
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 1309
1252 default: 1310 default:
1253 DVLOG(4) << "Unsupported SEI message"; 1311 DVLOG(4) << "Unsupported SEI message";
1254 break; 1312 break;
1255 } 1313 }
1256 1314
1257 return kOk; 1315 return kOk;
1258 } 1316 }
1259 1317
1260 } // namespace media 1318 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/h264_parser.h ('k') | media/formats/mp4/avc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698