Chromium Code Reviews| Index: media/formats/mp2t/mp2t_stream_parser.cc |
| diff --git a/media/formats/mp2t/mp2t_stream_parser.cc b/media/formats/mp2t/mp2t_stream_parser.cc |
| index 615f5c46e19138cdeae0ac382aefc49da2625517..79d666e32e6cfb795b5279c01eff8e54d7821b03 100644 |
| --- a/media/formats/mp2t/mp2t_stream_parser.cc |
| +++ b/media/formats/mp2t/mp2t_stream_parser.cc |
| @@ -13,6 +13,7 @@ |
| #include "media/base/stream_parser_buffer.h" |
| #include "media/base/text_track_config.h" |
| #include "media/base/timestamp_constants.h" |
| +#include "media/formats/mp2t/descriptors.h" |
| #include "media/formats/mp2t/es_parser.h" |
| #include "media/formats/mp2t/es_parser_adts.h" |
| #include "media/formats/mp2t/es_parser_h264.h" |
| @@ -368,8 +369,8 @@ void Mp2tStreamParser::RegisterPmt(int program_number, int pmt_pid) { |
| // Create the PMT state here if needed. |
| DVLOG(1) << "Create a new PMT parser"; |
| - std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt(base::Bind( |
| - &Mp2tStreamParser::RegisterPes, base::Unretained(this), pmt_pid))); |
| + std::unique_ptr<TsSection> pmt_section_parser(new TsSectionPmt( |
| + base::Bind(&Mp2tStreamParser::RegisterPes, base::Unretained(this)))); |
| std::unique_ptr<PidState> pmt_pid_state( |
| new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser))); |
| pmt_pid_state->Enable(); |
| @@ -386,8 +387,104 @@ void Mp2tStreamParser::RegisterPmt(int program_number, int pmt_pid) { |
| #endif |
| } |
| -void Mp2tStreamParser::RegisterPes(int pmt_pid, |
| - int pes_pid, |
| +std::unique_ptr<EsParser> Mp2tStreamParser::MaybeCreateH264Parser( |
| + int pes_pid, |
| + int stream_type, |
| + const Descriptors& descriptors) { |
| + bool is_h264 = stream_type == kStreamTypeAVC; |
| + bool enable_hls = false; |
| + std::unique_ptr<EsParser> es_parser; |
| + |
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| + if (is_h264 && !is_initialized_ && initial_scheme_.is_encrypted()) { |
| + enable_hls = true; |
| + } else if (stream_type == kStreamTypeAVCWithSampleAES && |
| + descriptors.HasPrivateDataIndicator( |
| + kSampleAESPrivateDataIndicatorAVC)) { |
| + is_h264 = true; |
| + enable_hls = true; |
| + } |
| +#endif |
| + |
| + if (!is_h264) |
| + return nullptr; |
| + |
| + auto on_video_config_changed = base::Bind( |
| + &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid); |
| + auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer, |
| + base::Unretained(this), pes_pid); |
| + if (!enable_hls) { |
| + es_parser.reset( |
| + new EsParserH264(on_video_config_changed, on_emit_video_buffer)); |
| + } |
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| + else { |
| + auto get_decrypt_config = |
| + base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this)); |
| + es_parser.reset(new EsParserH264(on_video_config_changed, |
| + on_emit_video_buffer, true, |
| + get_decrypt_config)); |
| + } |
| +#endif |
| + return es_parser; |
| +} |
| + |
| +std::unique_ptr<EsParser> Mp2tStreamParser::MaybeCreateAACParser( |
| + int pes_pid, |
| + int stream_type, |
| + const Descriptors& descriptors) { |
| + bool is_AAC = stream_type == kStreamTypeAAC; |
| + bool enable_hls = false; |
| + std::unique_ptr<EsParser> es_parser; |
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| + 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
|
| + enable_hls = true; |
| + } else if (stream_type == kStreamTypeAACWithSampleAES && |
| + descriptors.HasPrivateDataIndicator( |
| + kSampleAESPrivateDataIndicatorAAC)) { |
| + is_AAC = true; |
| + enable_hls = true; |
| + } |
| +#endif |
| + |
| + if (!is_AAC) |
| + return nullptr; |
| + |
| + auto on_audio_config_changed = base::Bind( |
| + &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid); |
| + auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, |
| + base::Unretained(this), pes_pid); |
| + if (!enable_hls) { |
| + es_parser.reset(new EsParserAdts(on_audio_config_changed, |
| + on_emit_audio_buffer, sbr_in_mimetype_)); |
| + } |
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| + else { |
| + auto get_decrypt_config = |
| + base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this)); |
| + es_parser.reset(new EsParserAdts(on_audio_config_changed, |
| + on_emit_audio_buffer, get_decrypt_config, |
| + true, sbr_in_mimetype_)); |
| + } |
| +#endif |
| + return es_parser; |
| +} |
| + |
| +std::unique_ptr<EsParser> Mp2tStreamParser::MaybeCreateMpeg1AudioParser( |
| + int pes_pid, |
| + int stream_type) { |
| + if (stream_type != kStreamTypeMpeg1Audio) |
|
servolk
2017/04/04 20:08:18
&& stream_type != kStreamTypeMpeg2Audio
dougsteed
2017/04/26 20:34:14
Done.
|
| + return nullptr; |
| + auto on_audio_config_changed = base::Bind( |
| + &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid); |
| + auto on_emit_audio_buffer = base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, |
| + base::Unretained(this), pes_pid); |
| + std::unique_ptr<EsParser> es_parser(new EsParserMpeg1Audio( |
| + on_audio_config_changed, on_emit_audio_buffer, media_log_)); |
| + return es_parser; |
| +} |
| + |
| +void Mp2tStreamParser::RegisterPes(int pes_pid, |
| int stream_type, |
| const Descriptors& descriptors) { |
| // TODO(damienv): check there is no mismatch if the entry already exists. |
| @@ -399,62 +496,20 @@ void Mp2tStreamParser::RegisterPes(int pmt_pid, |
| return; |
| // Create a stream parser corresponding to the stream type. |
| - bool is_audio = false; |
| + bool is_audio = true; |
| std::unique_ptr<EsParser> es_parser; |
| - if (stream_type == kStreamTypeAVC) { |
| - es_parser.reset( |
| - new EsParserH264( |
| - base::Bind(&Mp2tStreamParser::OnVideoConfigChanged, |
| - base::Unretained(this), |
| - pes_pid), |
| - base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer, |
| - base::Unretained(this), |
| - pes_pid))); |
| - } else if (stream_type == kStreamTypeAAC) { |
| - es_parser.reset( |
| - new EsParserAdts( |
| - base::Bind(&Mp2tStreamParser::OnAudioConfigChanged, |
| - base::Unretained(this), |
| - pes_pid), |
| - base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, |
| - base::Unretained(this), |
| - pes_pid), |
| - sbr_in_mimetype_)); |
| - is_audio = true; |
| - } else if (stream_type == kStreamTypeMpeg1Audio) { |
| - es_parser.reset(new EsParserMpeg1Audio( |
| - base::Bind(&Mp2tStreamParser::OnAudioConfigChanged, |
| - base::Unretained(this), pes_pid), |
| - base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this), |
| - pes_pid), |
| - media_log_)); |
| - is_audio = true; |
| -#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| - } else if (stream_type == kStreamTypeAVCWithSampleAES && |
| - descriptors.HasPrivateDataIndicator( |
| - kSampleAESPrivateDataIndicatorAVC)) { |
| - es_parser.reset( |
| - new EsParserH264(base::Bind(&Mp2tStreamParser::OnVideoConfigChanged, |
| - base::Unretained(this), pes_pid), |
| - base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer, |
| - base::Unretained(this), pes_pid), |
| - true, base::Bind(&Mp2tStreamParser::GetDecryptConfig, |
| - base::Unretained(this)))); |
| - } else if (stream_type == kStreamTypeAACWithSampleAES && |
| - descriptors.HasPrivateDataIndicator( |
| - kSampleAESPrivateDataIndicatorAAC)) { |
| - es_parser.reset(new EsParserAdts( |
| - base::Bind(&Mp2tStreamParser::OnAudioConfigChanged, |
| - base::Unretained(this), pes_pid), |
| - base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this), |
| - pes_pid), |
| - base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this)), |
| - true, sbr_in_mimetype_)); |
| - is_audio = true; |
| -#endif |
| - } else { |
| + |
| + es_parser = MaybeCreateH264Parser(pes_pid, stream_type, descriptors); |
| + if (es_parser) |
| + is_audio = false; |
| + else |
| + es_parser = MaybeCreateAACParser(pes_pid, stream_type, descriptors); |
| + |
| + if (!es_parser) |
| + es_parser = MaybeCreateMpeg1AudioParser(pes_pid, stream_type); |
| + |
| + 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
|
| return; |
| - } |
| // Create the PES state here. |
| DVLOG(1) << "Create a new PES state"; |
| @@ -752,7 +807,9 @@ bool Mp2tStreamParser::EmitRemainingBuffers() { |
| #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) |
| std::unique_ptr<PidState> Mp2tStreamParser::MakeCatPidState() { |
| std::unique_ptr<TsSection> cat_section_parser(new TsSectionCat( |
| - base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this)))); |
| + base::Bind(&Mp2tStreamParser::RegisterCencPids, base::Unretained(this)), |
| + base::Bind(&Mp2tStreamParser::RegisterEncryptionScheme, |
| + base::Unretained(this)))); |
| std::unique_ptr<PidState> cat_pid_state(new PidState( |
| TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser))); |
| cat_pid_state->Enable(); |
| @@ -800,6 +857,18 @@ void Mp2tStreamParser::UnregisterCencPids() { |
| } |
| } |
| +void Mp2tStreamParser::RegisterEncryptionScheme( |
| + const EncryptionScheme& scheme) { |
| + // We only need to record this for the initial decoder config. |
| + if (!is_initialized_) { |
| + initial_scheme_ = scheme; |
| + } |
| + // Reset the DecryptConfig, so that unless and until a CENC-ECM (containing |
| + // key id and IV) is seen, media data will be considered unencrypted. This is |
| + // similar to the way clear leaders can occur in MP4 containers. |
| + decrypt_config_.reset(nullptr); |
| +} |
| + |
| void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) { |
| decrypt_config_.reset( |
| new DecryptConfig(config.key_id(), config.iv(), config.subsamples())); |