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

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: Created 3 years, 8 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 "media/base/media_tracks.h" 12 #include "media/base/media_tracks.h"
13 #include "media/base/stream_parser_buffer.h" 13 #include "media/base/stream_parser_buffer.h"
14 #include "media/base/text_track_config.h" 14 #include "media/base/text_track_config.h"
15 #include "media/base/timestamp_constants.h" 15 #include "media/base/timestamp_constants.h"
16 #include "media/formats/mp2t/descriptors.h"
16 #include "media/formats/mp2t/es_parser.h" 17 #include "media/formats/mp2t/es_parser.h"
17 #include "media/formats/mp2t/es_parser_adts.h" 18 #include "media/formats/mp2t/es_parser_adts.h"
18 #include "media/formats/mp2t/es_parser_h264.h" 19 #include "media/formats/mp2t/es_parser_h264.h"
19 #include "media/formats/mp2t/es_parser_mpeg1audio.h" 20 #include "media/formats/mp2t/es_parser_mpeg1audio.h"
20 #include "media/formats/mp2t/mp2t_common.h" 21 #include "media/formats/mp2t/mp2t_common.h"
21 #include "media/formats/mp2t/ts_packet.h" 22 #include "media/formats/mp2t/ts_packet.h"
22 #include "media/formats/mp2t/ts_section.h" 23 #include "media/formats/mp2t/ts_section.h"
23 #include "media/formats/mp2t/ts_section_pat.h" 24 #include "media/formats/mp2t/ts_section_pat.h"
24 #include "media/formats/mp2t/ts_section_pes.h" 25 #include "media/formats/mp2t/ts_section_pes.h"
25 #include "media/formats/mp2t/ts_section_pmt.h" 26 #include "media/formats/mp2t/ts_section_pmt.h"
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 PidState* pid_state = pid_pair.second.get(); 362 PidState* pid_state = pid_pair.second.get();
362 if (pid_state->pid_type() == PidState::kPidPmt) { 363 if (pid_state->pid_type() == PidState::kPidPmt) {
363 DVLOG_IF(1, pmt_pid != pid_pair.first) 364 DVLOG_IF(1, pmt_pid != pid_pair.first)
364 << "More than one program is defined"; 365 << "More than one program is defined";
365 return; 366 return;
366 } 367 }
367 } 368 }
368 369
369 // Create the PMT state here if needed. 370 // Create the PMT state here if needed.
370 DVLOG(1) << "Create a new PMT parser"; 371 DVLOG(1) << "Create a new PMT parser";
371 std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(base::Bind( 372 std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(
372 &Mp2tStreamParser::RegisterPes, base::Unretained(this), pmt_pid))); 373 base::Bind(&Mp2tStreamParser::RegisterPes, base::Unretained(this))));
373 std::unique_ptr<PidState> pmt_pid_state( 374 std::unique_ptr<PidState> pmt_pid_state(
374 new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser))); 375 new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser)));
375 pmt_pid_state->Enable(); 376 pmt_pid_state->Enable();
376 pids_.insert(std::make_pair(pmt_pid, std::move(pmt_pid_state))); 377 pids_.insert(std::make_pair(pmt_pid, std::move(pmt_pid_state)));
377 378
378 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) 379 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
379 // Take the opportunity to clean up any PIDs that were involved in importing 380 // Take the opportunity to clean up any PIDs that were involved in importing
380 // encryption metadata for HLS with SampleAES. This prevents the possibility 381 // encryption metadata for HLS with SampleAES. This prevents the possibility
381 // of interference with actual PIDs that might be declared in the PMT. 382 // of interference with actual PIDs that might be declared in the PMT.
382 // TODO(dougsteed): if in the future the appropriate PIDs are embedded in the 383 // TODO(dougsteed): if in the future the appropriate PIDs are embedded in the
383 // source stream, this will not be necessary. 384 // source stream, this will not be necessary.
384 UnregisterCat(); 385 UnregisterCat();
385 UnregisterCencPids(); 386 UnregisterCencPids();
386 #endif 387 #endif
387 } 388 }
388 389
389 void Mp2tStreamParser::RegisterPes(int pmt_pid, 390 std::unique_ptr<EsParser> Mp2tStreamParser::MaybeCreateH264Parser(
390 int pes_pid, 391 int pes_pid,
392 int stream_type,
393 const Descriptors& descriptors) {
394 bool is_h264 = stream_type == kStreamTypeAVC;
395 bool enable_hls = false;
396 std::unique_ptr<EsParser> es_parser;
397
398 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
399 if (is_h264 && !is_initialized_ && initial_scheme_.is_encrypted()) {
400 enable_hls = true;
401 } else if (stream_type == kStreamTypeAVCWithSampleAES &&
402 descriptors.HasPrivateDataIndicator(
403 kSampleAESPrivateDataIndicatorAVC)) {
404 is_h264 = true;
405 enable_hls = true;
406 }
407 #endif
408
409 if (!is_h264)
410 return nullptr;
411
412 auto on_video_config_changed = base::Bind(
413 &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid);
414 auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
415 base::Unretained(this), pes_pid);
416 if (!enable_hls) {
417 es_parser.reset(
418 new EsParserH264(on_video_config_changed, on_emit_video_buffer));
419 }
420 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
421 else {
422 auto get_decrypt_config =
423 base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
424 es_parser.reset(new EsParserH264(on_video_config_changed,
425 on_emit_video_buffer, true,
426 get_decrypt_config));
427 }
428 #endif
429 return es_parser;
430 }
431
432 std::unique_ptr<EsParser> Mp2tStreamParser::MaybeCreateAACParser(
433 int pes_pid,
434 int stream_type,
435 const Descriptors& descriptors) {
436 bool is_AAC = stream_type == kStreamTypeAAC;
437 bool enable_hls = false;
438 std::unique_ptr<EsParser> es_parser;
439 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
440 if (is_AAC && !is_initialized_ && initial_scheme_.is_encrypted()) {
kqyang 2017/04/07 23:33:43 I understand that Marvel does not support switchin
dougsteed 2017/04/26 20:34:14 On this platform, we always need to initialize a d
kqyang 2017/05/06 00:06:12 Is this a limitation of Chromium media pipeline or
441 enable_hls = true;
442 } else if (stream_type == kStreamTypeAACWithSampleAES &&
443 descriptors.HasPrivateDataIndicator(
444 kSampleAESPrivateDataIndicatorAAC)) {
445 is_AAC = true;
446 enable_hls = true;
447 }
448 #endif
449
450 if (!is_AAC)
451 return nullptr;
452
453 auto on_audio_config_changed = base::Bind(
454 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
455 auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
456 base::Unretained(this), pes_pid);
457 if (!enable_hls) {
458 es_parser.reset(new EsParserAdts(on_audio_config_changed,
459 on_emit_audio_buffer, sbr_in_mimetype_));
460 }
461 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
462 else {
463 auto get_decrypt_config =
464 base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
465 es_parser.reset(new EsParserAdts(on_audio_config_changed,
466 on_emit_audio_buffer, get_decrypt_config,
467 true, sbr_in_mimetype_));
468 }
469 #endif
470 return es_parser;
471 }
472
473 std::unique_ptr<EsParser> Mp2tStreamParser::MaybeCreateMpeg1AudioParser(
474 int pes_pid,
475 int stream_type) {
476 if (stream_type != kStreamTypeMpeg1Audio)
servolk 2017/04/04 20:08:18 && stream_type != kStreamTypeMpeg2Audio
dougsteed 2017/04/26 20:34:14 Done.
477 return nullptr;
478 auto on_audio_config_changed = base::Bind(
479 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
480 auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
481 base::Unretained(this), pes_pid);
482 std::unique_ptr<EsParser> es_parser(new EsParserMpeg1Audio(
483 on_audio_config_changed, on_emit_audio_buffer, media_log_));
484 return es_parser;
485 }
486
487 void Mp2tStreamParser::RegisterPes(int pes_pid,
391 int stream_type, 488 int stream_type,
392 const Descriptors& descriptors) { 489 const Descriptors& descriptors) {
393 // TODO(damienv): check there is no mismatch if the entry already exists. 490 // TODO(damienv): check there is no mismatch if the entry already exists.
394 DVLOG(1) << "RegisterPes:" 491 DVLOG(1) << "RegisterPes:"
395 << " pes_pid=" << pes_pid 492 << " pes_pid=" << pes_pid
396 << " stream_type=" << std::hex << stream_type << std::dec; 493 << " stream_type=" << std::hex << stream_type << std::dec;
397 auto it = pids_.find(pes_pid); 494 auto it = pids_.find(pes_pid);
398 if (it != pids_.end()) 495 if (it != pids_.end())
399 return; 496 return;
400 497
401 // Create a stream parser corresponding to the stream type. 498 // Create a stream parser corresponding to the stream type.
402 bool is_audio = false; 499 bool is_audio = true;
403 std::unique_ptr<EsParser> es_parser; 500 std::unique_ptr<EsParser> es_parser;
404 if (stream_type == kStreamTypeAVC) { 501
405 es_parser.reset( 502 es_parser = MaybeCreateH264Parser(pes_pid, stream_type, descriptors);
406 new EsParserH264( 503 if (es_parser)
407 base::Bind(&Mp2tStreamParser::OnVideoConfigChanged, 504 is_audio = false;
408 base::Unretained(this), 505 else
409 pes_pid), 506 es_parser = MaybeCreateAACParser(pes_pid, stream_type, descriptors);
410 base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer, 507
411 base::Unretained(this), 508 if (!es_parser)
412 pes_pid))); 509 es_parser = MaybeCreateMpeg1AudioParser(pes_pid, stream_type);
413 } else if (stream_type == kStreamTypeAAC) { 510
414 es_parser.reset( 511 if (!es_parser)
kqyang 2017/04/07 23:33:43 I think the code would be cleaner and easier to ma
dougsteed 2017/04/26 20:34:14 Adopted this general approach, but with some varia
415 new EsParserAdts(
416 base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
417 base::Unretained(this),
418 pes_pid),
419 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
420 base::Unretained(this),
421 pes_pid),
422 sbr_in_mimetype_));
423 is_audio = true;
424 } else if (stream_type == kStreamTypeMpeg1Audio) {
425 es_parser.reset(new EsParserMpeg1Audio(
426 base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
427 base::Unretained(this), pes_pid),
428 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this),
429 pes_pid),
430 media_log_));
431 is_audio = true;
432 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
433 } else if (stream_type == kStreamTypeAVCWithSampleAES &&
434 descriptors.HasPrivateDataIndicator(
435 kSampleAESPrivateDataIndicatorAVC)) {
436 es_parser.reset(
437 new EsParserH264(base::Bind(&Mp2tStreamParser::OnVideoConfigChanged,
438 base::Unretained(this), pes_pid),
439 base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
440 base::Unretained(this), pes_pid),
441 true, base::Bind(&Mp2tStreamParser::GetDecryptConfig,
442 base::Unretained(this))));
443 } else if (stream_type == kStreamTypeAACWithSampleAES &&
444 descriptors.HasPrivateDataIndicator(
445 kSampleAESPrivateDataIndicatorAAC)) {
446 es_parser.reset(new EsParserAdts(
447 base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
448 base::Unretained(this), pes_pid),
449 base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this),
450 pes_pid),
451 base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this)),
452 true, sbr_in_mimetype_));
453 is_audio = true;
454 #endif
455 } else {
456 return; 512 return;
457 }
458 513
459 // Create the PES state here. 514 // Create the PES state here.
460 DVLOG(1) << "Create a new PES state"; 515 DVLOG(1) << "Create a new PES state";
461 std::unique_ptr<TsSection> pes_section_parser( 516 std::unique_ptr<TsSection> pes_section_parser(
462 new TsSectionPes(std::move(es_parser), &timestamp_unroller_)); 517 new TsSectionPes(std::move(es_parser), &timestamp_unroller_));
463 PidState::PidType pid_type = 518 PidState::PidType pid_type =
464 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes; 519 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes;
465 std::unique_ptr<PidState> pes_pid_state( 520 std::unique_ptr<PidState> pes_pid_state(
466 new PidState(pes_pid, pid_type, std::move(pes_section_parser))); 521 new PidState(pes_pid, pid_type, std::move(pes_section_parser)));
467 pids_.insert(std::make_pair(pes_pid, std::move(pes_pid_state))); 522 pids_.insert(std::make_pair(pes_pid, std::move(pes_pid_state)));
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 BufferQueueWithConfig queue_with_config( 800 BufferQueueWithConfig queue_with_config(
746 true, last_audio_config, last_video_config); 801 true, last_audio_config, last_video_config);
747 buffer_queue_chain_.push_back(queue_with_config); 802 buffer_queue_chain_.push_back(queue_with_config);
748 803
749 return true; 804 return true;
750 } 805 }
751 806
752 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) 807 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
753 std::unique_ptr<PidState> Mp2tStreamParser::MakeCatPidState() { 808 std::unique_ptr<PidState> Mp2tStreamParser::MakeCatPidState() {
754 std::unique_ptr<TsSection> cat_section_parser(new TsSectionCat( 809 std::unique_ptr<TsSection> cat_section_parser(new TsSectionCat(
755 base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this)))); 810 base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this)),
811 base::Bind(&Mp2tStreamParser::RegisterEncryptionScheme,
812 base::Unretained(this))));
756 std::unique_ptr<PidState> cat_pid_state(new PidState( 813 std::unique_ptr<PidState> cat_pid_state(new PidState(
757 TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser))); 814 TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser)));
758 cat_pid_state->Enable(); 815 cat_pid_state->Enable();
759 return cat_pid_state; 816 return cat_pid_state;
760 } 817 }
761 818
762 void Mp2tStreamParser::UnregisterCat() { 819 void Mp2tStreamParser::UnregisterCat() {
763 for (auto& pid : pids_) { 820 for (auto& pid : pids_) {
764 if (pid.second->pid_type() == PidState::kPidCat) { 821 if (pid.second->pid_type() == PidState::kPidCat) {
765 pids_.erase(pid.first); 822 pids_.erase(pid.first);
(...skipping 27 matching lines...) Expand all
793 } 850 }
794 } 851 }
795 for (auto& pid : pids_) { 852 for (auto& pid : pids_) {
796 if (pid.second->pid_type() == PidState::kPidCetsPssh) { 853 if (pid.second->pid_type() == PidState::kPidCetsPssh) {
797 pids_.erase(pid.first); 854 pids_.erase(pid.first);
798 break; 855 break;
799 } 856 }
800 } 857 }
801 } 858 }
802 859
860 void Mp2tStreamParser::RegisterEncryptionScheme(
861 const EncryptionScheme& scheme) {
862 // We only need to record this for the initial decoder config.
863 if (!is_initialized_) {
864 initial_scheme_ = scheme;
865 }
866 // Reset the DecryptConfig, so that unless and until a CENC-ECM (containing
867 // key id and IV) is seen, media data will be considered unencrypted. This is
868 // similar to the way clear leaders can occur in MP4 containers.
869 decrypt_config_.reset(nullptr);
870 }
871
803 void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) { 872 void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) {
804 decrypt_config_.reset( 873 decrypt_config_.reset(
805 new DecryptConfig(config.key_id(), config.iv(), config.subsamples())); 874 new DecryptConfig(config.key_id(), config.iv(), config.subsamples()));
806 } 875 }
807 876
808 void Mp2tStreamParser::RegisterPsshBoxes( 877 void Mp2tStreamParser::RegisterPsshBoxes(
809 const std::vector<uint8_t>& init_data) { 878 const std::vector<uint8_t>& init_data) {
810 encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data); 879 encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data);
811 } 880 }
812 881
813 #endif 882 #endif
814 883
815 } // namespace mp2t 884 } // namespace mp2t
816 } // namespace media 885 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698