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())); |