| OLD | NEW |
| 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 Loading... |
| 302 std::vector<uint8> param_sets; | 302 std::vector<uint8> param_sets; |
| 303 RCHECK(AVC::ConvertConfigToAnnexB(avc_config, ¶m_sets)); | 303 RCHECK(AVC::ConvertConfigToAnnexB(avc_config, ¶m_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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |