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

Side by Side Diff: media/formats/mp2t/mp2t_stream_parser.cc

Issue 2783703002: Declare intent to use sample-aes later in the stream. (Closed)
Patch Set: tweak needed for flush Created 3 years, 2 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 // 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 "media/formats/mp2t/mp2t_stream_parser.h" 5 #include "media/formats/mp2t/mp2t_stream_parser.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
12 #include "base/memory/ptr_util.h"
12 #include "media/base/media_tracks.h" 13 #include "media/base/media_tracks.h"
13 #include "media/base/stream_parser_buffer.h" 14 #include "media/base/stream_parser_buffer.h"
14 #include "media/base/text_track_config.h" 15 #include "media/base/text_track_config.h"
15 #include "media/base/timestamp_constants.h" 16 #include "media/base/timestamp_constants.h"
17 #include "media/formats/mp2t/descriptors.h"
16 #include "media/formats/mp2t/es_parser.h" 18 #include "media/formats/mp2t/es_parser.h"
17 #include "media/formats/mp2t/es_parser_adts.h" 19 #include "media/formats/mp2t/es_parser_adts.h"
18 #include "media/formats/mp2t/es_parser_h264.h" 20 #include "media/formats/mp2t/es_parser_h264.h"
19 #include "media/formats/mp2t/es_parser_mpeg1audio.h" 21 #include "media/formats/mp2t/es_parser_mpeg1audio.h"
20 #include "media/formats/mp2t/mp2t_common.h" 22 #include "media/formats/mp2t/mp2t_common.h"
21 #include "media/formats/mp2t/ts_packet.h" 23 #include "media/formats/mp2t/ts_packet.h"
22 #include "media/formats/mp2t/ts_section.h" 24 #include "media/formats/mp2t/ts_section.h"
23 #include "media/formats/mp2t/ts_section_pat.h" 25 #include "media/formats/mp2t/ts_section_pat.h"
24 #include "media/formats/mp2t/ts_section_pes.h" 26 #include "media/formats/mp2t/ts_section_pes.h"
25 #include "media/formats/mp2t/ts_section_pmt.h" 27 #include "media/formats/mp2t/ts_section_pmt.h"
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 PidState* pid_state = pid_pair.second.get(); 365 PidState* pid_state = pid_pair.second.get();
364 if (pid_state->pid_type() == PidState::kPidPmt) { 366 if (pid_state->pid_type() == PidState::kPidPmt) {
365 DVLOG_IF(1, pmt_pid != pid_pair.first) 367 DVLOG_IF(1, pmt_pid != pid_pair.first)
366 << "More than one program is defined"; 368 << "More than one program is defined";
367 return; 369 return;
368 } 370 }
369 } 371 }
370 372
371 // Create the PMT state here if needed. 373 // Create the PMT state here if needed.
372 DVLOG(1) << "Create a new PMT parser"; 374 DVLOG(1) << "Create a new PMT parser";
373 std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(base::Bind( 375 std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(
374 &Mp2tStreamParser::RegisterPes, base::Unretained(this), pmt_pid))); 376 base::Bind(&Mp2tStreamParser::RegisterPes, base::Unretained(this))));
375 std::unique_ptr<PidState> pmt_pid_state( 377 std::unique_ptr<PidState> pmt_pid_state(
376 new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser))); 378 new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser)));
377 pmt_pid_state->Enable(); 379 pmt_pid_state->Enable();
378 pids_.insert(std::make_pair(pmt_pid, std::move(pmt_pid_state))); 380 pids_.insert(std::make_pair(pmt_pid, std::move(pmt_pid_state)));
379 381
380 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) 382 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
381 // Take the opportunity to clean up any PIDs that were involved in importing 383 // Take the opportunity to clean up any PIDs that were involved in importing
382 // encryption metadata for HLS with SampleAES. This prevents the possibility 384 // encryption metadata for HLS with SampleAES. This prevents the possibility
383 // of interference with actual PIDs that might be declared in the PMT. 385 // of interference with actual PIDs that might be declared in the PMT.
384 // TODO(dougsteed): if in the future the appropriate PIDs are embedded in the 386 // TODO(dougsteed): if in the future the appropriate PIDs are embedded in the
385 // source stream, this will not be necessary. 387 // source stream, this will not be necessary.
386 UnregisterCat(); 388 UnregisterCat();
387 UnregisterCencPids(); 389 UnregisterCencPids();
388 #endif 390 #endif
389 } 391 }
390 392
391 void Mp2tStreamParser::RegisterPes(int pmt_pid, 393 std::unique_ptr<EsParser> Mp2tStreamParser::CreateH264Parser(int pes_pid) {
392 int pes_pid, 394 auto on_video_config_changed = base::Bind(
395 &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid);
396 auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
397 base::Unretained(this), pes_pid);
398
399 return base::MakeUnique<EsParserH264>(on_video_config_changed,
400 on_emit_video_buffer);
401 }
402
403 std::unique_ptr<EsParser> Mp2tStreamParser::CreateAacParser(int pes_pid) {
404 auto on_audio_config_changed = base::Bind(
405 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
406 auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
407 base::Unretained(this), pes_pid);
408 return base::MakeUnique<EsParserAdts>(on_audio_config_changed,
409 on_emit_audio_buffer, sbr_in_mimetype_);
410 }
411
412 std::unique_ptr<EsParser> Mp2tStreamParser::CreateMpeg1AudioParser(
413 int pes_pid) {
414 auto on_audio_config_changed = base::Bind(
415 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
416 auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
417 base::Unretained(this), pes_pid);
418 return base::MakeUnique<EsParserMpeg1Audio>(on_audio_config_changed,
419 on_emit_audio_buffer, media_log_);
420 }
421
422 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
423 bool Mp2tStreamParser::ShouldForceEncryptedParser() {
424 // If we expect to handle encrypted data later in the stream, then force the
425 // use of the encrypted parser variant so that the initial configuration
426 // reflects the intended encryption scheme (even if the initial segment itself
427 // is not encrypted).
428 return initial_scheme_.is_encrypted();
429 }
430
431 std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedH264Parser(
432 int pes_pid) {
433 auto on_video_config_changed = base::Bind(
434 &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid);
435 auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
436 base::Unretained(this), pes_pid);
437 auto get_decrypt_config =
438 base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
439 return base::MakeUnique<EsParserH264>(
440 on_video_config_changed, on_emit_video_buffer, true, get_decrypt_config);
441 }
442
443 std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedAacParser(
444 int pes_pid) {
445 auto on_audio_config_changed = base::Bind(
446 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
447 auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
448 base::Unretained(this), pes_pid);
449 auto get_decrypt_config =
450 base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
451 return base::MakeUnique<EsParserAdts>(
452 on_audio_config_changed, on_emit_audio_buffer, get_decrypt_config, true,
453 sbr_in_mimetype_);
454 }
455 #endif
456
457 void Mp2tStreamParser::RegisterPes(int pes_pid,
393 int stream_type, 458 int stream_type,
394 const Descriptors& descriptors) { 459 const Descriptors& descriptors) {
395 // TODO(damienv): check there is no mismatch if the entry already exists. 460 // TODO(damienv): check there is no mismatch if the entry already exists.
396 DVLOG(1) << "RegisterPes:" 461 DVLOG(1) << "RegisterPes:"
397 << " pes_pid=" << pes_pid 462 << " pes_pid=" << pes_pid
398 << " stream_type=" << std::hex << stream_type << std::dec; 463 << " stream_type=" << std::hex << stream_type << std::dec;
399 auto it = pids_.find(pes_pid); 464 auto it = pids_.find(pes_pid);
400 if (it != pids_.end()) 465 if (it != pids_.end())
401 return; 466 return;
402 467
403 // Create a stream parser corresponding to the stream type. 468 // Create a stream parser corresponding to the stream type.
404 bool is_audio = false; 469 bool is_audio = true;
405 std::unique_ptr<EsParser> es_parser; 470 std::unique_ptr<EsParser> es_parser;
406 if (stream_type == kStreamTypeAVC) { 471
407 es_parser.reset( 472 switch (stream_type) {
408 new EsParserH264( 473 case kStreamTypeAVC:
409 base::Bind(&Mp2tStreamParser::OnVideoConfigChanged,
410 base::Unretained(this),
411 pes_pid),
412 base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
413 base::Unretained(this),
414 pes_pid)));
415 } else if (stream_type == kStreamTypeAAC) {
416 es_parser.reset(
417 new EsParserAdts(
418 base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
419 base::Unretained(this),
420 pes_pid),
421 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
422 base::Unretained(this),
423 pes_pid),
424 sbr_in_mimetype_));
425 is_audio = true;
426 } else if (stream_type == kStreamTypeMpeg1Audio ||
427 stream_type == kStreamTypeMpeg2Audio) {
428 es_parser.reset(new EsParserMpeg1Audio(
429 base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
430 base::Unretained(this), pes_pid),
431 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this),
432 pes_pid),
433 media_log_));
434 is_audio = true;
435 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) 474 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
436 } else if (stream_type == kStreamTypeAVCWithSampleAES && 475 is_audio = false;
437 descriptors.HasPrivateDataIndicator( 476 if (ShouldForceEncryptedParser()) {
438 kSampleAESPrivateDataIndicatorAVC)) { 477 es_parser = CreateEncryptedH264Parser(pes_pid);
439 es_parser.reset( 478 break;
440 new EsParserH264(base::Bind(&Mp2tStreamParser::OnVideoConfigChanged, 479 }
441 base::Unretained(this), pes_pid),
442 base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
443 base::Unretained(this), pes_pid),
444 true, base::Bind(&Mp2tStreamParser::GetDecryptConfig,
445 base::Unretained(this))));
446 } else if (stream_type == kStreamTypeAACWithSampleAES &&
447 descriptors.HasPrivateDataIndicator(
448 kSampleAESPrivateDataIndicatorAAC)) {
449 es_parser.reset(new EsParserAdts(
450 base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
451 base::Unretained(this), pes_pid),
452 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this),
453 pes_pid),
454 base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this)),
455 true, sbr_in_mimetype_));
456 is_audio = true;
457 #endif 480 #endif
458 } else { 481 es_parser = CreateH264Parser(pes_pid);
482 break;
483
484 case kStreamTypeAAC:
485 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
486 if (ShouldForceEncryptedParser()) {
487 es_parser = CreateEncryptedAacParser(pes_pid);
488 break;
489 }
490 #endif
491 es_parser = CreateAacParser(pes_pid);
492 break;
493
494 case kStreamTypeMpeg1Audio:
495 case kStreamTypeMpeg2Audio:
496 es_parser = CreateMpeg1AudioParser(pes_pid);
497 break;
498
499 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
500 case kStreamTypeAVCWithSampleAES:
501 if (descriptors.HasPrivateDataIndicator(
502 kSampleAESPrivateDataIndicatorAVC)) {
503 is_audio = false;
504 es_parser = CreateEncryptedH264Parser(pes_pid);
505 } else {
506 VLOG(2) << "HLS: stream_type in PMT indicates AVC with Sample-AES, but "
507 << "corresponding private data indicator is not present.";
508 }
509 break;
510
511 case kStreamTypeAACWithSampleAES:
512 if (descriptors.HasPrivateDataIndicator(
513 kSampleAESPrivateDataIndicatorAAC)) {
514 es_parser = CreateEncryptedAacParser(pes_pid);
515 } else {
516 VLOG(2) << "HLS: stream_type in PMT indicates AAC with Sample-AES, but "
517 << "corresponding private data indicator is not present.";
518 }
519 break;
520 #endif
521
522 default:
523 // Unknown stream_type, so can't create a parser. Logged below.
524 break;
525 }
526
527 if (!es_parser) {
528 VLOG(1) << "Parser could not be created for stream_type: " << stream_type;
459 return; 529 return;
460 } 530 }
461 531
462 // Create the PES state here. 532 // Create the PES state here.
463 DVLOG(1) << "Create a new PES state"; 533 DVLOG(1) << "Create a new PES state";
464 std::unique_ptr<TsSection> pes_section_parser( 534 std::unique_ptr<TsSection> pes_section_parser(
465 new TsSectionPes(std::move(es_parser), &timestamp_unroller_)); 535 new TsSectionPes(std::move(es_parser), &timestamp_unroller_));
466 PidState::PidType pid_type = 536 PidState::PidType pid_type =
467 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes; 537 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes;
468 std::unique_ptr<PidState> pes_pid_state( 538 std::unique_ptr<PidState> pes_pid_state(
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 BufferQueueWithConfig queue_with_config( 818 BufferQueueWithConfig queue_with_config(
749 true, last_audio_config, last_video_config); 819 true, last_audio_config, last_video_config);
750 buffer_queue_chain_.push_back(queue_with_config); 820 buffer_queue_chain_.push_back(queue_with_config);
751 821
752 return true; 822 return true;
753 } 823 }
754 824
755 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) 825 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
756 std::unique_ptr<PidState> Mp2tStreamParser::MakeCatPidState() { 826 std::unique_ptr<PidState> Mp2tStreamParser::MakeCatPidState() {
757 std::unique_ptr<TsSection> cat_section_parser(new TsSectionCat( 827 std::unique_ptr<TsSection> cat_section_parser(new TsSectionCat(
758 base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this)))); 828 base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this)),
829 base::Bind(&Mp2tStreamParser::RegisterEncryptionScheme,
830 base::Unretained(this))));
759 std::unique_ptr<PidState> cat_pid_state(new PidState( 831 std::unique_ptr<PidState> cat_pid_state(new PidState(
760 TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser))); 832 TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser)));
761 cat_pid_state->Enable(); 833 cat_pid_state->Enable();
762 return cat_pid_state; 834 return cat_pid_state;
763 } 835 }
764 836
765 void Mp2tStreamParser::UnregisterCat() { 837 void Mp2tStreamParser::UnregisterCat() {
766 for (auto& pid : pids_) { 838 for (auto& pid : pids_) {
767 if (pid.second->pid_type() == PidState::kPidCat) { 839 if (pid.second->pid_type() == PidState::kPidCat) {
768 pids_.erase(pid.first); 840 pids_.erase(pid.first);
(...skipping 27 matching lines...) Expand all
796 } 868 }
797 } 869 }
798 for (auto& pid : pids_) { 870 for (auto& pid : pids_) {
799 if (pid.second->pid_type() == PidState::kPidCetsPssh) { 871 if (pid.second->pid_type() == PidState::kPidCetsPssh) {
800 pids_.erase(pid.first); 872 pids_.erase(pid.first);
801 break; 873 break;
802 } 874 }
803 } 875 }
804 } 876 }
805 877
878 void Mp2tStreamParser::RegisterEncryptionScheme(
879 const EncryptionScheme& scheme) {
880 // We only need to record this for the initial decoder config.
881 if (!is_initialized_) {
882 initial_scheme_ = scheme;
883 }
884 // Reset the DecryptConfig, so that unless and until a CENC-ECM (containing
885 // key id and IV) is seen, media data will be considered unencrypted. This is
886 // similar to the way clear leaders can occur in MP4 containers.
887 decrypt_config_.reset(nullptr);
888 }
889
806 void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) { 890 void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) {
807 decrypt_config_.reset( 891 decrypt_config_.reset(
808 new DecryptConfig(config.key_id(), config.iv(), config.subsamples())); 892 new DecryptConfig(config.key_id(), config.iv(), config.subsamples()));
809 } 893 }
810 894
811 void Mp2tStreamParser::RegisterPsshBoxes( 895 void Mp2tStreamParser::RegisterPsshBoxes(
812 const std::vector<uint8_t>& init_data) { 896 const std::vector<uint8_t>& init_data) {
813 encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data); 897 encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data);
814 } 898 }
815 899
816 #endif 900 #endif
817 901
818 } // namespace mp2t 902 } // namespace mp2t
819 } // namespace media 903 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/mp2t/mp2t_stream_parser.h ('k') | media/formats/mp2t/mp2t_stream_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698