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

Side by Side Diff: media/mp4/mp4_stream_parser.cc

Issue 10886022: Fix encrypted AAC in BMFF by adding subsample info. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use constant in ConvertEsdsToADTS Created 8 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « media/mp4/mp4_stream_parser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "media/mp4/mp4_stream_parser.h" 5 #include "media/mp4/mp4_stream_parser.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/time.h" 10 #include "base/time.h"
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 std::vector<uint8> param_sets; 302 std::vector<uint8> param_sets;
303 RCHECK(AVC::ConvertConfigToAnnexB(avc_config, &param_sets)); 303 RCHECK(AVC::ConvertConfigToAnnexB(avc_config, &param_sets));
304 frame_buf->insert(frame_buf->begin(), 304 frame_buf->insert(frame_buf->begin(),
305 param_sets.begin(), param_sets.end()); 305 param_sets.begin(), param_sets.end());
306 if (!subsamples->empty()) 306 if (!subsamples->empty())
307 (*subsamples)[0].clear_bytes += param_sets.size(); 307 (*subsamples)[0].clear_bytes += param_sets.size();
308 } 308 }
309 return true; 309 return true;
310 } 310 }
311 311
312 bool MP4StreamParser::PrepareAACBuffer(
313 const AAC& aac_config, std::vector<uint8>* frame_buf,
314 std::vector<SubsampleEntry>* subsamples) const {
315 // Append an ADTS header to every audio sample.
316 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf));
317
318 // As above, adjust subsample information to account for the headers. AAC is
319 // not required to use subsample encryption, so we may need to add an entry.
320 if (subsamples->empty()) {
321 SubsampleEntry entry;
322 entry.clear_bytes = AAC::kADTSHeaderSize;
323 entry.cypher_bytes = frame_buf->size() - AAC::kADTSHeaderSize;
324 subsamples->push_back(entry);
325 } else {
326 (*subsamples)[0].clear_bytes += AAC::kADTSHeaderSize;
327 }
328 return true;
329 }
330
312 bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, 331 bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers,
313 BufferQueue* video_buffers, 332 BufferQueue* video_buffers,
314 bool* err) { 333 bool* err) {
315 if (!runs_->IsRunValid()) { 334 if (!runs_->IsRunValid()) {
316 // Flush any buffers we've gotten in this chunk so that buffers don't 335 // Flush any buffers we've gotten in this chunk so that buffers don't
317 // cross NewSegment() calls 336 // cross NewSegment() calls
318 *err = !SendAndFlushSamples(audio_buffers, video_buffers); 337 *err = !SendAndFlushSamples(audio_buffers, video_buffers);
319 if (*err) 338 if (*err)
320 return false; 339 return false;
321 340
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 queue_.PeekAt(runs_->aux_info_offset() + moof_head_, &buf, &buf_size); 378 queue_.PeekAt(runs_->aux_info_offset() + moof_head_, &buf, &buf_size);
360 if (buf_size < runs_->aux_info_size()) return false; 379 if (buf_size < runs_->aux_info_size()) return false;
361 *err = !runs_->CacheAuxInfo(buf, buf_size); 380 *err = !runs_->CacheAuxInfo(buf, buf_size);
362 return !*err; 381 return !*err;
363 } 382 }
364 383
365 queue_.PeekAt(runs_->sample_offset() + moof_head_, &buf, &buf_size); 384 queue_.PeekAt(runs_->sample_offset() + moof_head_, &buf, &buf_size);
366 if (buf_size < runs_->sample_size()) return false; 385 if (buf_size < runs_->sample_size()) return false;
367 386
368 scoped_ptr<DecryptConfig> decrypt_config; 387 scoped_ptr<DecryptConfig> decrypt_config;
369 if (runs_->is_encrypted()) 388 std::vector<SubsampleEntry> subsamples;
389 if (runs_->is_encrypted()) {
370 decrypt_config = runs_->GetDecryptConfig(); 390 decrypt_config = runs_->GetDecryptConfig();
391 subsamples = decrypt_config->subsamples();
392 }
371 393
372 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); 394 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size());
373 if (video) { 395 if (video) {
374 std::vector<SubsampleEntry> subsamples;
375 if (decrypt_config.get())
376 subsamples = decrypt_config->subsamples();
377 if (!PrepareAVCBuffer(runs_->video_description().avcc, 396 if (!PrepareAVCBuffer(runs_->video_description().avcc,
378 &frame_buf, &subsamples)) { 397 &frame_buf, &subsamples)) {
379 DLOG(ERROR) << "Failed to prepare AVC sample for decode"; 398 DLOG(ERROR) << "Failed to prepare AVC sample for decode";
380 *err = true; 399 *err = true;
381 return false; 400 return false;
382 } 401 }
383 if (!subsamples.empty()) {
384 decrypt_config.reset(new DecryptConfig(
385 decrypt_config->key_id(),
386 decrypt_config->iv(),
387 decrypt_config->checksum(),
388 decrypt_config->data_offset(),
389 subsamples));
390 }
391 } 402 }
392 403
393 if (audio) { 404 if (audio) {
394 const AAC& aac = runs_->audio_description().esds.aac; 405 if (!PrepareAACBuffer(runs_->audio_description().esds.aac,
395 if (!aac.ConvertEsdsToADTS(&frame_buf)) { 406 &frame_buf, &subsamples)) {
396 DLOG(ERROR) << "Failed to convert ESDS to ADTS"; 407 DLOG(ERROR) << "Failed to prepare AAC sample for decode";
397 *err = true; 408 *err = true;
398 return false; 409 return false;
399 } 410 }
400 } 411 }
401 412
413 if (decrypt_config.get() != NULL && !subsamples.empty()) {
414 decrypt_config.reset(new DecryptConfig(
415 decrypt_config->key_id(),
416 decrypt_config->iv(),
417 decrypt_config->checksum(),
418 decrypt_config->data_offset(),
419 subsamples));
420 }
421
402 scoped_refptr<StreamParserBuffer> stream_buf = 422 scoped_refptr<StreamParserBuffer> stream_buf =
403 StreamParserBuffer::CopyFrom(&frame_buf[0], frame_buf.size(), 423 StreamParserBuffer::CopyFrom(&frame_buf[0], frame_buf.size(),
404 runs_->is_keyframe()); 424 runs_->is_keyframe());
405 425
406 if (runs_->is_encrypted()) 426 if (runs_->is_encrypted())
407 stream_buf->SetDecryptConfig(decrypt_config.Pass()); 427 stream_buf->SetDecryptConfig(decrypt_config.Pass());
408 428
409 stream_buf->SetDuration(runs_->duration()); 429 stream_buf->SetDuration(runs_->duration());
410 stream_buf->SetTimestamp(runs_->cts()); 430 stream_buf->SetTimestamp(runs_->cts());
411 stream_buf->SetDecodeTimestamp(runs_->dts()); 431 stream_buf->SetDecodeTimestamp(runs_->dts());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 return !err; 483 return !err;
464 } 484 }
465 485
466 void MP4StreamParser::ChangeState(State new_state) { 486 void MP4StreamParser::ChangeState(State new_state) {
467 DVLOG(2) << "Changing state: " << new_state; 487 DVLOG(2) << "Changing state: " << new_state;
468 state_ = new_state; 488 state_ = new_state;
469 } 489 }
470 490
471 } // namespace mp4 491 } // namespace mp4
472 } // namespace media 492 } // namespace media
OLDNEW
« no previous file with comments | « media/mp4/mp4_stream_parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698