| 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 59029dcc2f66207043fc192691910c215a99af95..615f5c46e19138cdeae0ac382aefc49da2625517 100644
 | 
| --- a/media/formats/mp2t/mp2t_stream_parser.cc
 | 
| +++ b/media/formats/mp2t/mp2t_stream_parser.cc
 | 
| @@ -24,14 +24,39 @@
 | 
|  #include "media/formats/mp2t/ts_section_pes.h"
 | 
|  #include "media/formats/mp2t/ts_section_pmt.h"
 | 
|  
 | 
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
 | 
| +#include "media/formats/mp2t/ts_section_cat.h"
 | 
| +#include "media/formats/mp2t/ts_section_cets_ecm.h"
 | 
| +#include "media/formats/mp2t/ts_section_cets_pssh.h"
 | 
| +#endif
 | 
| +
 | 
|  namespace media {
 | 
|  namespace mp2t {
 | 
|  
 | 
| +namespace {
 | 
| +
 | 
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
 | 
| +const int64_t kSampleAESPrivateDataIndicatorAVC = 0x7a617663;
 | 
| +const int64_t kSampleAESPrivateDataIndicatorAAC = 0x61616364;
 | 
| +// TODO(dougsteed). Consider adding support for the following:
 | 
| +// const int64_t kSampleAESPrivateDataIndicatorAC3 = 0x61633364;
 | 
| +// const int64_t kSampleAESPrivateDataIndicatorEAC3 = 0x65633364;
 | 
| +#endif
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
|  enum StreamType {
 | 
|    // ISO-13818.1 / ITU H.222 Table 2.34 "Stream type assignments"
 | 
|    kStreamTypeMpeg1Audio = 0x3,
 | 
|    kStreamTypeAAC = 0xf,
 | 
|    kStreamTypeAVC = 0x1b,
 | 
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
 | 
| +  kStreamTypeAACWithSampleAES = 0xcf,
 | 
| +  kStreamTypeAVCWithSampleAES = 0xdb,
 | 
| +// TODO(dougsteed). Consider adding support for the following:
 | 
| +//  kStreamTypeAC3WithSampleAES = 0xc1,
 | 
| +//  kStreamTypeEAC3WithSampleAES = 0xc2,
 | 
| +#endif
 | 
|  };
 | 
|  
 | 
|  class PidState {
 | 
| @@ -41,6 +66,11 @@ class PidState {
 | 
|      kPidPmt,
 | 
|      kPidAudioPes,
 | 
|      kPidVideoPes,
 | 
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
 | 
| +    kPidCat,
 | 
| +    kPidCetsEcm,
 | 
| +    kPidCetsPssh,
 | 
| +#endif
 | 
|    };
 | 
|  
 | 
|    PidState(int pid,
 | 
| @@ -293,6 +323,15 @@ bool Mp2tStreamParser::Parse(const uint8_t* buf, int size) {
 | 
|                     std::make_pair(ts_packet->pid(), std::move(pat_pid_state)))
 | 
|                 .first;
 | 
|      }
 | 
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
 | 
| +    // We allow a CAT to appear as the first packet in the TS. This allows us to
 | 
| +    // specify encryption metadata for HLS by injecting it as an extra TS packet
 | 
| +    // at the front of the stream.
 | 
| +    else if (it == pids_.end() && ts_packet->pid() == TsSection::kPidCat) {
 | 
| +      it = pids_.insert(std::make_pair(TsSection::kPidCat, MakeCatPidState()))
 | 
| +               .first;
 | 
| +    }
 | 
| +#endif
 | 
|  
 | 
|      if (it != pids_.end()) {
 | 
|        if (!it->second->PushTsPacket(*ts_packet))
 | 
| @@ -335,11 +374,22 @@ void Mp2tStreamParser::RegisterPmt(int program_number, int pmt_pid) {
 | 
|        new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser)));
 | 
|    pmt_pid_state->Enable();
 | 
|    pids_.insert(std::make_pair(pmt_pid, std::move(pmt_pid_state)));
 | 
| +
 | 
| +#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
 | 
| +  // Take the opportunity to clean up any PIDs that were involved in importing
 | 
| +  // encryption metadata for HLS with SampleAES. This prevents the possibility
 | 
| +  // of interference with actual PIDs that might be declared in the PMT.
 | 
| +  // TODO(dougsteed): if in the future the appropriate PIDs are embedded in the
 | 
| +  // source stream, this will not be necessary.
 | 
| +  UnregisterCat();
 | 
| +  UnregisterCencPids();
 | 
| +#endif
 | 
|  }
 | 
|  
 | 
|  void Mp2tStreamParser::RegisterPes(int pmt_pid,
 | 
|                                     int pes_pid,
 | 
| -                                   int stream_type) {
 | 
| +                                   int stream_type,
 | 
| +                                   const Descriptors& descriptors) {
 | 
|    // TODO(damienv): check there is no mismatch if the entry already exists.
 | 
|    DVLOG(1) << "RegisterPes:"
 | 
|             << " pes_pid=" << pes_pid
 | 
| @@ -379,6 +429,29 @@ void Mp2tStreamParser::RegisterPes(int pmt_pid,
 | 
|                     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 {
 | 
|      return;
 | 
|    }
 | 
| @@ -676,5 +749,68 @@ bool Mp2tStreamParser::EmitRemainingBuffers() {
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| +#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))));
 | 
| +  std::unique_ptr<PidState> cat_pid_state(new PidState(
 | 
| +      TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser)));
 | 
| +  cat_pid_state->Enable();
 | 
| +  return cat_pid_state;
 | 
| +}
 | 
| +
 | 
| +void Mp2tStreamParser::UnregisterCat() {
 | 
| +  for (auto& pid : pids_) {
 | 
| +    if (pid.second->pid_type() == PidState::kPidCat) {
 | 
| +      pids_.erase(pid.first);
 | 
| +      break;
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void Mp2tStreamParser::RegisterCencPids(int ca_pid, int pssh_pid) {
 | 
| +  std::unique_ptr<TsSectionCetsEcm> ecm_parser(new TsSectionCetsEcm(base::Bind(
 | 
| +      &Mp2tStreamParser::RegisterDecryptConfig, base::Unretained(this))));
 | 
| +  std::unique_ptr<PidState> ecm_pid_state(
 | 
| +      new PidState(ca_pid, PidState::kPidCetsEcm, std::move(ecm_parser)));
 | 
| +  ecm_pid_state->Enable();
 | 
| +  pids_.insert(std::make_pair(ca_pid, std::move(ecm_pid_state)));
 | 
| +
 | 
| +  std::unique_ptr<TsSectionCetsPssh> pssh_parser(
 | 
| +      new TsSectionCetsPssh(base::Bind(&Mp2tStreamParser::RegisterPsshBoxes,
 | 
| +                                       base::Unretained(this))));
 | 
| +  std::unique_ptr<PidState> pssh_pid_state(
 | 
| +      new PidState(pssh_pid, PidState::kPidCetsPssh, std::move(pssh_parser)));
 | 
| +  pssh_pid_state->Enable();
 | 
| +  pids_.insert(std::make_pair(pssh_pid, std::move(pssh_pid_state)));
 | 
| +}
 | 
| +
 | 
| +void Mp2tStreamParser::UnregisterCencPids() {
 | 
| +  for (auto& pid : pids_) {
 | 
| +    if (pid.second->pid_type() == PidState::kPidCetsEcm) {
 | 
| +      pids_.erase(pid.first);
 | 
| +      break;
 | 
| +    }
 | 
| +  }
 | 
| +  for (auto& pid : pids_) {
 | 
| +    if (pid.second->pid_type() == PidState::kPidCetsPssh) {
 | 
| +      pids_.erase(pid.first);
 | 
| +      break;
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) {
 | 
| +  decrypt_config_.reset(
 | 
| +      new DecryptConfig(config.key_id(), config.iv(), config.subsamples()));
 | 
| +}
 | 
| +
 | 
| +void Mp2tStreamParser::RegisterPsshBoxes(
 | 
| +    const std::vector<uint8_t>& init_data) {
 | 
| +  encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data);
 | 
| +}
 | 
| +
 | 
| +#endif
 | 
| +
 | 
|  }  // namespace mp2t
 | 
|  }  // namespace media
 | 
| 
 |