// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/formats/mp2t/mp2t_stream_parser.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.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/es_parser.h"
#include "media/formats/mp2t/es_parser_adts.h"
#include "media/formats/mp2t/es_parser_h264.h"
#include "media/formats/mp2t/es_parser_mpeg1audio.h"
#include "media/formats/mp2t/mp2t_common.h"
#include "media/formats/mp2t/ts_packet.h"
#include "media/formats/mp2t/ts_section.h"
#include "media/formats/mp2t/ts_section_pat.h"
#include "media/formats/mp2t/ts_section_pes.h"
#include "media/formats/mp2t/ts_section_pmt.h"

namespace cobalt {
namespace media {
namespace mp2t {

enum StreamType {
  // ISO-13818.1 / ITU H.222 Table 2.34 "Stream type assignments"
  kStreamTypeMpeg1Audio = 0x3,
  kStreamTypeAAC = 0xf,
  kStreamTypeAVC = 0x1b,
};

class PidState {
 public:
  enum PidType {
    kPidPat,
    kPidPmt,
    kPidAudioPes,
    kPidVideoPes,
  };

  PidState(int pid, PidType pid_type,
           std::unique_ptr<TsSection> section_parser);

  // Extract the content of the TS packet and parse it.
  // Return true if successful.
  bool PushTsPacket(const TsPacket& ts_packet);

  // Flush the PID state (possibly emitting some pending frames)
  // and reset its state.
  void Flush();

  // Enable/disable the PID.
  // Disabling a PID will reset its state and ignore any further incoming TS
  // packets.
  void Enable();
  void Disable();
  bool IsEnabled() const;

  PidType pid_type() const { return pid_type_; }

 private:
  void ResetState();

  int pid_;
  PidType pid_type_;
  std::unique_ptr<TsSection> section_parser_;

  bool enable_;

  int continuity_counter_;
};

PidState::PidState(int pid, PidType pid_type,
                   std::unique_ptr<TsSection> section_parser)
    : pid_(pid),
      pid_type_(pid_type),
      section_parser_(std::move(section_parser)),
      enable_(false),
      continuity_counter_(-1) {
  DCHECK(section_parser_);
}

bool PidState::PushTsPacket(const TsPacket& ts_packet) {
  DCHECK_EQ(ts_packet.pid(), pid_);

  // The current PID is not part of the PID filter,
  // just discard the incoming TS packet.
  if (!enable_) return true;

  int expected_continuity_counter = (continuity_counter_ + 1) % 16;
  if (continuity_counter_ >= 0 &&
      ts_packet.continuity_counter() != expected_continuity_counter) {
    DVLOG(1) << "TS discontinuity detected for pid: " << pid_;
    return false;
  }

  bool status =
      section_parser_->Parse(ts_packet.payload_unit_start_indicator(),
                             ts_packet.payload(), ts_packet.payload_size());

  // At the minimum, when parsing failed, auto reset the section parser.
  // Components that use the StreamParser can take further action if needed.
  if (!status) {
    DVLOG(1) << "Parsing failed for pid = " << pid_;
    ResetState();
  }

  return status;
}

void PidState::Flush() {
  section_parser_->Flush();
  ResetState();
}

void PidState::Enable() { enable_ = true; }

void PidState::Disable() {
  if (!enable_) return;

  ResetState();
  enable_ = false;
}

bool PidState::IsEnabled() const { return enable_; }

void PidState::ResetState() {
  section_parser_->Reset();
  continuity_counter_ = -1;
}

Mp2tStreamParser::BufferQueueWithConfig::BufferQueueWithConfig(
    bool is_cfg_sent, const AudioDecoderConfig& audio_cfg,
    const VideoDecoderConfig& video_cfg)
    : is_config_sent(is_cfg_sent),
      audio_config(audio_cfg),
      video_config(video_cfg) {}

Mp2tStreamParser::BufferQueueWithConfig::BufferQueueWithConfig(
    const BufferQueueWithConfig& other) = default;

Mp2tStreamParser::BufferQueueWithConfig::~BufferQueueWithConfig() {}

Mp2tStreamParser::Mp2tStreamParser(bool sbr_in_mimetype)
    : sbr_in_mimetype_(sbr_in_mimetype),
      selected_audio_pid_(-1),
      selected_video_pid_(-1),
      is_initialized_(false),
      segment_started_(false) {}

Mp2tStreamParser::~Mp2tStreamParser() {}

void Mp2tStreamParser::Init(
    const InitCB& init_cb, const NewConfigCB& config_cb,
    const NewBuffersCB& new_buffers_cb, bool /* ignore_text_tracks */,
    const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
    const NewMediaSegmentCB& new_segment_cb,
    const EndMediaSegmentCB& end_of_segment_cb,
    const scoped_refptr<MediaLog>& media_log) {
  DCHECK(!is_initialized_);
  DCHECK(init_cb_.is_null());
  DCHECK(!init_cb.is_null());
  DCHECK(!config_cb.is_null());
  DCHECK(!new_buffers_cb.is_null());
  DCHECK(!encrypted_media_init_data_cb.is_null());
  DCHECK(!new_segment_cb.is_null());
  DCHECK(!end_of_segment_cb.is_null());

  init_cb_ = init_cb;
  config_cb_ = config_cb;
  new_buffers_cb_ = new_buffers_cb;
  encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
  new_segment_cb_ = new_segment_cb;
  end_of_segment_cb_ = end_of_segment_cb;
  media_log_ = media_log;
}

void Mp2tStreamParser::Flush() {
  DVLOG(1) << "Mp2tStreamParser::Flush";

  // Flush the buffers and reset the pids.
  for (const auto& pid_pair : pids_) {
    DVLOG(1) << "Flushing PID: " << pid_pair.first;
    pid_pair.second->Flush();
  }
  pids_.clear();

  // Flush is invoked from SourceBuffer.abort/SourceState::ResetParserState, and
  // MSE spec prohibits emitting new configs in ResetParserState algorithm (see
  // https://w3c.github.io/media-source/#sourcebuffer-reset-parser-state,
  // 3.5.2 Reset Parser State states that new frames might be processed only in
  // PARSING_MEDIA_SEGMENT and therefore doesn't allow emitting new configs,
  // since that might need to run "init segment received" algorithm).
  // So before we emit remaining buffers here, we need to trim our buffer queue
  // so that we leave only buffers with configs that were already sent.
  for (auto buffer_queue_iter = buffer_queue_chain_.begin();
       buffer_queue_iter != buffer_queue_chain_.end(); ++buffer_queue_iter) {
    const BufferQueueWithConfig& queue_with_config = *buffer_queue_iter;
    if (!queue_with_config.is_config_sent) {
      DVLOG(LOG_LEVEL_ES) << "Flush: dropping buffers with unsent new configs.";
      buffer_queue_chain_.erase(buffer_queue_iter, buffer_queue_chain_.end());
      break;
    }
  }

  EmitRemainingBuffers();
  buffer_queue_chain_.clear();

  // End of the segment.
  // Note: does not need to invoke |end_of_segment_cb_| since flushing the
  // stream parser already involves the end of the current segment.
  segment_started_ = false;

  // Remove any bytes left in the TS buffer.
  // (i.e. any partial TS packet => less than 188 bytes).
  ts_byte_queue_.Reset();

  // Reset the selected PIDs.
  selected_audio_pid_ = -1;
  selected_video_pid_ = -1;

  // Reset the timestamp unroller.
  timestamp_unroller_.Reset();
}

bool Mp2tStreamParser::Parse(const uint8_t* buf, int size) {
  DVLOG(1) << "Mp2tStreamParser::Parse size=" << size;

  // Add the data to the parser state.
  ts_byte_queue_.Push(buf, size);

  while (true) {
    const uint8_t* ts_buffer;
    int ts_buffer_size;
    ts_byte_queue_.Peek(&ts_buffer, &ts_buffer_size);
    if (ts_buffer_size < TsPacket::kPacketSize) break;

    // Synchronization.
    int skipped_bytes = TsPacket::Sync(ts_buffer, ts_buffer_size);
    if (skipped_bytes > 0) {
      DVLOG(1) << "Packet not aligned on a TS syncword:"
               << " skipped_bytes=" << skipped_bytes;
      ts_byte_queue_.Pop(skipped_bytes);
      continue;
    }

    // Parse the TS header, skipping 1 byte if the header is invalid.
    std::unique_ptr<TsPacket> ts_packet(
        TsPacket::Parse(ts_buffer, ts_buffer_size));
    if (!ts_packet) {
      DVLOG(1) << "Error: invalid TS packet";
      ts_byte_queue_.Pop(1);
      continue;
    }
    DVLOG(LOG_LEVEL_TS) << "Processing PID=" << ts_packet->pid()
                        << " start_unit="
                        << ts_packet->payload_unit_start_indicator();

    // Parse the section.
    auto it = pids_.find(ts_packet->pid());
    if (it == pids_.end() && ts_packet->pid() == TsSection::kPidPat) {
      // Create the PAT state here if needed.
      std::unique_ptr<TsSection> pat_section_parser(new TsSectionPat(
          base::Bind(&Mp2tStreamParser::RegisterPmt, base::Unretained(this))));
      std::unique_ptr<PidState> pat_pid_state(new PidState(
          ts_packet->pid(), PidState::kPidPat, std::move(pat_section_parser)));
      pat_pid_state->Enable();
      it = pids_
               .insert(
                   std::make_pair(ts_packet->pid(), std::move(pat_pid_state)))
               .first;
    }

    if (it != pids_.end()) {
      if (!it->second->PushTsPacket(*ts_packet)) return false;
    } else {
      DVLOG(LOG_LEVEL_TS) << "Ignoring TS packet for pid: " << ts_packet->pid();
    }

    // Go to the next packet.
    ts_byte_queue_.Pop(TsPacket::kPacketSize);
  }

  RCHECK(FinishInitializationIfNeeded());

  // Emit the A/V buffers that kept accumulating during TS parsing.
  return EmitRemainingBuffers();
}

void Mp2tStreamParser::RegisterPmt(int program_number, int pmt_pid) {
  DVLOG(1) << "RegisterPmt:"
           << " program_number=" << program_number << " pmt_pid=" << pmt_pid;

  // Only one TS program is allowed. Ignore the incoming program map table,
  // if there is already one registered.
  for (const auto& pid_pair : pids_) {
    PidState* pid_state = pid_pair.second.get();
    if (pid_state->pid_type() == PidState::kPidPmt) {
      DVLOG_IF(1, pmt_pid != pid_pair.first)
          << "More than one program is defined";
      return;
    }
  }

  // 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<PidState> pmt_pid_state(
      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)));
}

void Mp2tStreamParser::RegisterPes(int pmt_pid, int pes_pid, int stream_type) {
  // TODO(damienv): check there is no mismatch if the entry already exists.
  DVLOG(1) << "RegisterPes:"
           << " pes_pid=" << pes_pid << " stream_type=" << std::hex
           << stream_type << std::dec;
  auto it = pids_.find(pes_pid);
  if (it != pids_.end()) return;

  // Create a stream parser corresponding to the stream type.
  bool is_audio = false;
  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;
  } else {
    return;
  }

  // Create the PES state here.
  DVLOG(1) << "Create a new PES state";
  std::unique_ptr<TsSection> pes_section_parser(
      new TsSectionPes(std::move(es_parser), &timestamp_unroller_));
  PidState::PidType pid_type =
      is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes;
  std::unique_ptr<PidState> pes_pid_state(
      new PidState(pes_pid, pid_type, std::move(pes_section_parser)));
  pids_.insert(std::make_pair(pes_pid, std::move(pes_pid_state)));

  // A new PES pid has been added, the PID filter might change.
  UpdatePidFilter();
}

void Mp2tStreamParser::UpdatePidFilter() {
  // Applies the HLS rule to select the default audio/video PIDs:
  // select the audio/video streams with the lowest PID.
  // TODO(damienv): this can be changed when the StreamParser interface
  // supports multiple audio/video streams.
  auto lowest_audio_pid = pids_.end();
  auto lowest_video_pid = pids_.end();
  for (auto it = pids_.begin(); it != pids_.end(); ++it) {
    int pid = it->first;
    PidState* pid_state = it->second.get();
    if (pid_state->pid_type() == PidState::kPidAudioPes &&
        (lowest_audio_pid == pids_.end() || pid < lowest_audio_pid->first))
      lowest_audio_pid = it;
    if (pid_state->pid_type() == PidState::kPidVideoPes &&
        (lowest_video_pid == pids_.end() || pid < lowest_video_pid->first))
      lowest_video_pid = it;
  }

  // Enable both the lowest audio and video PIDs.
  if (lowest_audio_pid != pids_.end()) {
    DVLOG(1) << "Enable audio pid: " << lowest_audio_pid->first;
    lowest_audio_pid->second->Enable();
    selected_audio_pid_ = lowest_audio_pid->first;
  }
  if (lowest_video_pid != pids_.end()) {
    DVLOG(1) << "Enable video pid: " << lowest_video_pid->first;
    lowest_video_pid->second->Enable();
    selected_video_pid_ = lowest_video_pid->first;
  }

  // Disable all the other audio and video PIDs.
  for (auto it = pids_.begin(); it != pids_.end(); ++it) {
    PidState* pid_state = it->second.get();
    if (it != lowest_audio_pid && it != lowest_video_pid &&
        (pid_state->pid_type() == PidState::kPidAudioPes ||
         pid_state->pid_type() == PidState::kPidVideoPes))
      pid_state->Disable();
  }
}

void Mp2tStreamParser::OnVideoConfigChanged(
    int pes_pid, const VideoDecoderConfig& video_decoder_config) {
  DVLOG(1) << "OnVideoConfigChanged for pid=" << pes_pid;
  DCHECK_EQ(pes_pid, selected_video_pid_);
  DCHECK(video_decoder_config.IsValidConfig());

  if (!buffer_queue_chain_.empty() &&
      !buffer_queue_chain_.back().video_config.IsValidConfig()) {
    // No video has been received so far, can reuse the existing video queue.
    DCHECK(buffer_queue_chain_.back().video_queue.empty());
    buffer_queue_chain_.back().video_config = video_decoder_config;
  } else {
    // Create a new entry in |buffer_queue_chain_| with the updated configs.
    BufferQueueWithConfig buffer_queue_with_config(
        false,
        buffer_queue_chain_.empty() ? AudioDecoderConfig()
                                    : buffer_queue_chain_.back().audio_config,
        video_decoder_config);
    buffer_queue_chain_.push_back(buffer_queue_with_config);
  }

  // Replace any non valid config with the 1st valid entry.
  // This might happen if there was no available config before.
  for (std::list<BufferQueueWithConfig>::iterator it =
           buffer_queue_chain_.begin();
       it != buffer_queue_chain_.end(); ++it) {
    if (it->video_config.IsValidConfig()) break;
    it->video_config = video_decoder_config;
  }
}

void Mp2tStreamParser::OnAudioConfigChanged(
    int pes_pid, const AudioDecoderConfig& audio_decoder_config) {
  DVLOG(1) << "OnAudioConfigChanged for pid=" << pes_pid;
  DCHECK_EQ(pes_pid, selected_audio_pid_);
  DCHECK(audio_decoder_config.IsValidConfig());

  if (!buffer_queue_chain_.empty() &&
      !buffer_queue_chain_.back().audio_config.IsValidConfig()) {
    // No audio has been received so far, can reuse the existing audio queue.
    DCHECK(buffer_queue_chain_.back().audio_queue.empty());
    buffer_queue_chain_.back().audio_config = audio_decoder_config;
  } else {
    // Create a new entry in |buffer_queue_chain_| with the updated configs.
    BufferQueueWithConfig buffer_queue_with_config(
        false, audio_decoder_config,
        buffer_queue_chain_.empty() ? VideoDecoderConfig()
                                    : buffer_queue_chain_.back().video_config);
    buffer_queue_chain_.push_back(buffer_queue_with_config);
  }

  // Replace any non valid config with the 1st valid entry.
  // This might happen if there was no available config before.
  for (std::list<BufferQueueWithConfig>::iterator it =
           buffer_queue_chain_.begin();
       it != buffer_queue_chain_.end(); ++it) {
    if (it->audio_config.IsValidConfig()) break;
    it->audio_config = audio_decoder_config;
  }
}

std::unique_ptr<MediaTracks> GenerateMediaTrackInfo(
    const AudioDecoderConfig& audio_config,
    const VideoDecoderConfig& video_config) {
  std::unique_ptr<MediaTracks> media_tracks(new MediaTracks());
  // TODO(servolk): Implement proper sourcing of media track info as described
  // in crbug.com/590085
  if (audio_config.IsValidConfig()) {
    media_tracks->AddAudioTrack(audio_config, kMp2tAudioTrackId, "main", "",
                                "");
  }
  if (video_config.IsValidConfig()) {
    media_tracks->AddVideoTrack(video_config, kMp2tVideoTrackId, "main", "",
                                "");
  }
  return media_tracks;
}

bool Mp2tStreamParser::FinishInitializationIfNeeded() {
  // Nothing to be done if already initialized.
  if (is_initialized_) return true;

  // Wait for more data to come to finish initialization.
  if (buffer_queue_chain_.empty()) return true;

  // Wait for more data to come if one of the config is not available.
  BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
  if (selected_audio_pid_ > 0 &&
      !queue_with_config.audio_config.IsValidConfig())
    return true;
  if (selected_video_pid_ > 0 &&
      !queue_with_config.video_config.IsValidConfig())
    return true;

  // Pass the config before invoking the initialization callback.
  std::unique_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
      queue_with_config.audio_config, queue_with_config.video_config);
  RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()));
  queue_with_config.is_config_sent = true;

  // For Mpeg2 TS, the duration is not known.
  DVLOG(1) << "Mpeg2TS stream parser initialization done";

  // TODO(wolenetz): If possible, detect and report track counts by type more
  // accurately here. Currently, capped at max 1 each for audio and video, with
  // assumption of 0 text tracks.
  InitParameters params(kInfiniteDuration);
  params.detected_audio_track_count =
      queue_with_config.audio_config.IsValidConfig() ? 1 : 0;
  params.detected_video_track_count =
      queue_with_config.video_config.IsValidConfig() ? 1 : 0;
  base::ResetAndReturn(&init_cb_).Run(params);
  is_initialized_ = true;

  return true;
}

void Mp2tStreamParser::OnEmitAudioBuffer(
    int pes_pid, scoped_refptr<StreamParserBuffer> stream_parser_buffer) {
  DCHECK_EQ(pes_pid, selected_audio_pid_);

  DVLOG(LOG_LEVEL_ES)
      << "OnEmitAudioBuffer: "
      << " size=" << stream_parser_buffer->data_size()
      << " dts=" << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds()
      << " pts=" << stream_parser_buffer->timestamp().InMilliseconds()
      << " dur=" << stream_parser_buffer->duration().InMilliseconds();

  // Ignore the incoming buffer if it is not associated with any config.
  if (buffer_queue_chain_.empty()) {
    LOG(ERROR) << "Cannot provide buffers before configs";
    return;
  }

  buffer_queue_chain_.back().audio_queue.push_back(stream_parser_buffer);
}

void Mp2tStreamParser::OnEmitVideoBuffer(
    int pes_pid, scoped_refptr<StreamParserBuffer> stream_parser_buffer) {
  DCHECK_EQ(pes_pid, selected_video_pid_);

  DVLOG(LOG_LEVEL_ES)
      << "OnEmitVideoBuffer"
      << " size=" << stream_parser_buffer->data_size()
      << " dts=" << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds()
      << " pts=" << stream_parser_buffer->timestamp().InMilliseconds()
      << " dur=" << stream_parser_buffer->duration().InMilliseconds()
      << " is_key_frame=" << stream_parser_buffer->is_key_frame();

  // Ignore the incoming buffer if it is not associated with any config.
  if (buffer_queue_chain_.empty()) {
    NOTREACHED() << "Cannot provide buffers before configs";
    return;
  }

  buffer_queue_chain_.back().video_queue.push_back(stream_parser_buffer);
}

bool Mp2tStreamParser::EmitRemainingBuffers() {
  DVLOG(LOG_LEVEL_ES) << "Mp2tStreamParser::EmitRemainingBuffers";

  // No buffer should be sent until fully initialized.
  if (!is_initialized_) return true;

  if (buffer_queue_chain_.empty()) return true;

  // Keep track of the last audio and video config sent.
  AudioDecoderConfig last_audio_config =
      buffer_queue_chain_.back().audio_config;
  VideoDecoderConfig last_video_config =
      buffer_queue_chain_.back().video_config;

  // Do not have all the configs, need more data.
  if (selected_audio_pid_ >= 0 && !last_audio_config.IsValidConfig())
    return true;
  if (selected_video_pid_ >= 0 && !last_video_config.IsValidConfig())
    return true;

  // Buffer emission.
  while (!buffer_queue_chain_.empty()) {
    // Start a segment if needed.
    if (!segment_started_) {
      DVLOG(1) << "Starting a new segment";
      segment_started_ = true;
      new_segment_cb_.Run();
    }

    // Update the audio and video config if needed.
    BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
    if (!queue_with_config.is_config_sent) {
      std::unique_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
          queue_with_config.audio_config, queue_with_config.video_config);
      if (!config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()))
        return false;
      queue_with_config.is_config_sent = true;
    }

    // Add buffers.
    BufferQueueMap buffer_queue_map;
    if (!queue_with_config.audio_queue.empty())
      buffer_queue_map.insert(
          std::make_pair(kMp2tAudioTrackId, queue_with_config.audio_queue));
    if (!queue_with_config.video_queue.empty())
      buffer_queue_map.insert(
          std::make_pair(kMp2tVideoTrackId, queue_with_config.video_queue));

    if (!buffer_queue_map.empty() && !new_buffers_cb_.Run(buffer_queue_map))
      return false;

    buffer_queue_chain_.pop_front();
  }

  // Push an empty queue with the last audio/video config
  // so that buffers with the same config can be added later on.
  BufferQueueWithConfig queue_with_config(true, last_audio_config,
                                          last_video_config);
  buffer_queue_chain_.push_back(queue_with_config);

  return true;
}

}  // namespace mp2t
}  // namespace media
}  // namespace cobalt
