| 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 d0392de3ae5b0c9776f23e0b187a693d852b77cb..1fcc86a52f295a3dd1ca4a26ffe2e7328dc2d8a2 100644
|
| --- a/media/formats/mp2t/mp2t_stream_parser.cc
|
| +++ b/media/formats/mp2t/mp2t_stream_parser.cc
|
| @@ -9,10 +9,12 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/callback_helpers.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "media/base/media_tracks.h"
|
| #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"
|
| @@ -370,8 +372,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();
|
| @@ -388,8 +390,71 @@ void Mp2tStreamParser::RegisterPmt(int program_number, int pmt_pid) {
|
| #endif
|
| }
|
|
|
| -void Mp2tStreamParser::RegisterPes(int pmt_pid,
|
| - int pes_pid,
|
| +std::unique_ptr<EsParser> Mp2tStreamParser::CreateH264Parser(int pes_pid) {
|
| + 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);
|
| +
|
| + return base::MakeUnique<EsParserH264>(on_video_config_changed,
|
| + on_emit_video_buffer);
|
| +}
|
| +
|
| +std::unique_ptr<EsParser> Mp2tStreamParser::CreateAacParser(int pes_pid) {
|
| + 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);
|
| + return base::MakeUnique<EsParserAdts>(on_audio_config_changed,
|
| + on_emit_audio_buffer, sbr_in_mimetype_);
|
| +}
|
| +
|
| +std::unique_ptr<EsParser> Mp2tStreamParser::CreateMpeg1AudioParser(
|
| + int pes_pid) {
|
| + 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);
|
| + return base::MakeUnique<EsParserMpeg1Audio>(on_audio_config_changed,
|
| + on_emit_audio_buffer, media_log_);
|
| +}
|
| +
|
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
|
| +bool Mp2tStreamParser::ShouldForceEncryptedParser() {
|
| + // If we expect to handle encrypted data later in the stream, then force the
|
| + // use of the encrypted parser variant so that the initial configuration
|
| + // reflects the intended encryption scheme (even if the initial segment itself
|
| + // is not encrypted).
|
| + return initial_scheme_.is_encrypted();
|
| +}
|
| +
|
| +std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedH264Parser(
|
| + int pes_pid) {
|
| + 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);
|
| + auto get_decrypt_config =
|
| + base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
|
| + return base::MakeUnique<EsParserH264>(
|
| + on_video_config_changed, on_emit_video_buffer, true, get_decrypt_config);
|
| +}
|
| +
|
| +std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedAacParser(
|
| + int pes_pid) {
|
| + 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);
|
| + auto get_decrypt_config =
|
| + base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
|
| + return base::MakeUnique<EsParserAdts>(
|
| + on_audio_config_changed, on_emit_audio_buffer, get_decrypt_config, true,
|
| + sbr_in_mimetype_);
|
| +}
|
| +#endif
|
| +
|
| +void Mp2tStreamParser::RegisterPes(int pes_pid,
|
| int stream_type,
|
| const Descriptors& descriptors) {
|
| // TODO(damienv): check there is no mismatch if the entry already exists.
|
| @@ -401,61 +466,66 @@ 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 ||
|
| - stream_type == kStreamTypeMpeg2Audio) {
|
| - 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;
|
| +
|
| + switch (stream_type) {
|
| + case kStreamTypeAVC:
|
| #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;
|
| + is_audio = false;
|
| + if (ShouldForceEncryptedParser()) {
|
| + es_parser = CreateEncryptedH264Parser(pes_pid);
|
| + break;
|
| + }
|
| #endif
|
| - } else {
|
| + es_parser = CreateH264Parser(pes_pid);
|
| + break;
|
| +
|
| + case kStreamTypeAAC:
|
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
|
| + if (ShouldForceEncryptedParser()) {
|
| + es_parser = CreateEncryptedAacParser(pes_pid);
|
| + break;
|
| + }
|
| +#endif
|
| + es_parser = CreateAacParser(pes_pid);
|
| + break;
|
| +
|
| + case kStreamTypeMpeg1Audio:
|
| + case kStreamTypeMpeg2Audio:
|
| + es_parser = CreateMpeg1AudioParser(pes_pid);
|
| + break;
|
| +
|
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
|
| + case kStreamTypeAVCWithSampleAES:
|
| + if (descriptors.HasPrivateDataIndicator(
|
| + kSampleAESPrivateDataIndicatorAVC)) {
|
| + is_audio = false;
|
| + es_parser = CreateEncryptedH264Parser(pes_pid);
|
| + } else {
|
| + VLOG(2) << "HLS: stream_type in PMT indicates AVC with Sample-AES, but "
|
| + << "corresponding private data indicator is not present.";
|
| + }
|
| + break;
|
| +
|
| + case kStreamTypeAACWithSampleAES:
|
| + if (descriptors.HasPrivateDataIndicator(
|
| + kSampleAESPrivateDataIndicatorAAC)) {
|
| + es_parser = CreateEncryptedAacParser(pes_pid);
|
| + } else {
|
| + VLOG(2) << "HLS: stream_type in PMT indicates AAC with Sample-AES, but "
|
| + << "corresponding private data indicator is not present.";
|
| + }
|
| + break;
|
| +#endif
|
| +
|
| + default:
|
| + // Unknown stream_type, so can't create a parser. Logged below.
|
| + break;
|
| + }
|
| +
|
| + if (!es_parser) {
|
| + VLOG(1) << "Parser could not be created for stream_type: " << stream_type;
|
| return;
|
| }
|
|
|
| @@ -755,7 +825,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();
|
| @@ -803,6 +875,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()));
|
|
|