chromium/media/formats/mp4/box_definitions.cc

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "media/formats/mp4/box_definitions.h"

#include <bitset>
#include <memory>
#include <utility>

#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/containers/span_writer.h"
#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "media/base/media_switches.h"
#include "media/base/media_util.h"
#include "media/base/video_types.h"
#include "media/base/video_util.h"
#include "media/formats/common/opus_constants.h"
#include "media/formats/mp4/es_descriptor.h"
#include "media/formats/mp4/rcheck.h"
#include "media/media_buildflags.h"

#if BUILDFLAG(USE_PROPRIETARY_CODECS)
#include <optional>

#include "media/formats/mp4/avc.h"
#include "media/formats/mp4/dolby_vision.h"
#include "media/parsers/h264_parser.h"

#if BUILDFLAG(ENABLE_PLATFORM_HEVC)
#include "media/formats/mp4/hevc.h"
#endif  // BUILDFLAG(ENABLE_PLATFORM_HEVC)
#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)

namespace media {
namespace mp4 {

namespace {

const size_t kKeyIdSize =;
const size_t kFlacMetadataBlockStreaminfoSize =;

#if BUILDFLAG(USE_PROPRIETARY_CODECS)
// Try to parse dvcC or dvvC box if exists, return `video_info` and an optional
// `dv_info` based on the configuration.
std::tuple<CodecProfileLevel, std::optional<CodecProfileLevel>> MaybeParseDOVI(
    BoxReader* reader,
    CodecProfileLevel video_info) {
  std::optional<DOVIDecoderConfigurationRecord> dovi_config;

  {
    DolbyVisionConfiguration dvcc;
    if (reader->HasChild(&dvcc) && reader->ReadChild(&dvcc)) {
      DVLOG(2) << __func__ << " reading DolbyVisionConfiguration (dvcC)";
      DCHECK_LE(dvcc.dovi_config.dv_profile, 7);
      dovi_config = dvcc.dovi_config;
    }
  }

  {
    DolbyVisionConfiguration8 dvvc;
    if (reader->HasChild(&dvvc) && reader->ReadChild(&dvvc)) {
      DVLOG(2) << __func__ << " reading DolbyVisionConfiguration (dvvC)";
      DCHECK_GT(dvvc.dovi_config.dv_profile, 7);
      dovi_config = dvvc.dovi_config;
    }
  }

  if (!dovi_config.has_value()) {
    return {video_info, std::nullopt};
  }

  constexpr int kHDR10CompatibilityId = 1;
  constexpr int kSDRCompatibilityId = 2;
  constexpr int kHLGCompatibilityId = 4;
  CodecProfileLevel dv_info = {VideoCodec::kDolbyVision,
                               dovi_config->codec_profile,
                               dovi_config->dv_level};
  if (dovi_config->dv_bl_signal_compatibility_id == kHDR10CompatibilityId ||
      dovi_config->dv_bl_signal_compatibility_id == kSDRCompatibilityId ||
      dovi_config->dv_bl_signal_compatibility_id == kHLGCompatibilityId) {
    return {video_info, dv_info};
  }
  // If the buffer is not backward compatible, always treat it as Dolby Vision.
  return {dv_info, std::nullopt};
}
#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)

// Read color coordinate value as defined in the MasteringDisplayColorVolume
// ('mdcv') box.  Each coordinate is a float encoded in uint16_t, with upper
// bound set to 50000.
bool ReadMdcvColorCoordinate(BoxReader* reader,
                             float* normalized_value_in_float) {}

// Read "fixed point" value as defined in the
// SMPTE2086MasteringDisplayMetadataBox ('SmDm') box. See
// https://www.webmproject.org/vp9/mp4/#data-types-and-fields
bool ReadFixedPoint16(float fixed_point_divisor,
                      BoxReader* reader,
                      float* normalized_value_in_float) {}

bool ReadFixedPoint32(float fixed_point_divisor,
                      BoxReader* reader,
                      float* normalized_value_in_float) {}

gfx::HdrMetadataSmpteSt2086 ConvertMdcvToColorVolumeMetadata(
    const MasteringDisplayColorVolume& mdcv) {}

}  // namespace

FileType::FileType() = default;
FileType::FileType(const FileType& other) = default;
FileType::~FileType() = default;
FourCC FileType::BoxType() const {}

bool FileType::Parse(BoxReader* reader) {}

ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader() = default;
ProtectionSystemSpecificHeader::ProtectionSystemSpecificHeader(
    const ProtectionSystemSpecificHeader& other) = default;
ProtectionSystemSpecificHeader::~ProtectionSystemSpecificHeader() = default;
FourCC ProtectionSystemSpecificHeader::BoxType() const {}

bool ProtectionSystemSpecificHeader::Parse(BoxReader* reader) {}

FullProtectionSystemSpecificHeader::FullProtectionSystemSpecificHeader() =
    default;
FullProtectionSystemSpecificHeader::FullProtectionSystemSpecificHeader(
    const FullProtectionSystemSpecificHeader& other) = default;
FullProtectionSystemSpecificHeader::~FullProtectionSystemSpecificHeader() =
    default;
FourCC FullProtectionSystemSpecificHeader::BoxType() const {}

// The format of a 'pssh' box is as follows:
//   unsigned int(32) size;
//   unsigned int(32) type = "pssh";
//   if (size==1) {
//     unsigned int(64) largesize;
//   } else if (size==0) {
//     -- box extends to end of file
//   }
//   unsigned int(8) version;
//   bit(24) flags;
//   unsigned int(8)[16] SystemID;
//   if (version > 0)
//   {
//     unsigned int(32) KID_count;
//     {
//       unsigned int(8)[16] KID;
//     } [KID_count]
//   }
//   unsigned int(32) DataSize;
//   unsigned int(8)[DataSize] Data;

bool FullProtectionSystemSpecificHeader::Parse(mp4::BoxReader* reader) {}

SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset() = default;
SampleAuxiliaryInformationOffset::SampleAuxiliaryInformationOffset(
    const SampleAuxiliaryInformationOffset& other) = default;
SampleAuxiliaryInformationOffset::~SampleAuxiliaryInformationOffset() = default;
FourCC SampleAuxiliaryInformationOffset::BoxType() const {}

bool SampleAuxiliaryInformationOffset::Parse(BoxReader* reader) {}

SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize()
  :{}
SampleAuxiliaryInformationSize::SampleAuxiliaryInformationSize(
    const SampleAuxiliaryInformationSize& other) = default;
SampleAuxiliaryInformationSize::~SampleAuxiliaryInformationSize() = default;
FourCC SampleAuxiliaryInformationSize::BoxType() const {}

bool SampleAuxiliaryInformationSize::Parse(BoxReader* reader) {}

SampleEncryptionEntry::SampleEncryptionEntry() = default;
SampleEncryptionEntry::SampleEncryptionEntry(
    const SampleEncryptionEntry& other) = default;
SampleEncryptionEntry::~SampleEncryptionEntry() = default;

bool SampleEncryptionEntry::Parse(BufferReader* reader,
                                  uint8_t iv_size,
                                  bool has_subsamples) {}

bool SampleEncryptionEntry::GetTotalSizeOfSubsamples(size_t* total_size) const {}

SampleEncryption::SampleEncryption() :{}
SampleEncryption::SampleEncryption(const SampleEncryption& other) = default;
SampleEncryption::~SampleEncryption() = default;
FourCC SampleEncryption::BoxType() const {}

bool SampleEncryption::Parse(BoxReader* reader) {}

OriginalFormat::OriginalFormat() :{}
OriginalFormat::OriginalFormat(const OriginalFormat& other) = default;
OriginalFormat::~OriginalFormat() = default;
FourCC OriginalFormat::BoxType() const {}

bool OriginalFormat::Parse(BoxReader* reader) {}

SchemeType::SchemeType() :{}
SchemeType::SchemeType(const SchemeType& other) = default;
SchemeType::~SchemeType() = default;
FourCC SchemeType::BoxType() const {}

bool SchemeType::Parse(BoxReader* reader) {}

TrackEncryption::TrackEncryption()
    :{}
TrackEncryption::TrackEncryption(const TrackEncryption& other) = default;
TrackEncryption::~TrackEncryption() = default;
FourCC TrackEncryption::BoxType() const {}

bool TrackEncryption::Parse(BoxReader* reader) {}

SchemeInfo::SchemeInfo() = default;
SchemeInfo::SchemeInfo(const SchemeInfo& other) = default;
SchemeInfo::~SchemeInfo() = default;
FourCC SchemeInfo::BoxType() const {}

bool SchemeInfo::Parse(BoxReader* reader) {}

ProtectionSchemeInfo::ProtectionSchemeInfo() = default;
ProtectionSchemeInfo::ProtectionSchemeInfo(const ProtectionSchemeInfo& other) =
    default;
ProtectionSchemeInfo::~ProtectionSchemeInfo() = default;
FourCC ProtectionSchemeInfo::BoxType() const {}

bool ProtectionSchemeInfo::Parse(BoxReader* reader) {}

bool ProtectionSchemeInfo::HasSupportedScheme() const {}

bool ProtectionSchemeInfo::IsCbcsEncryptionScheme() const {}

MovieHeader::MovieHeader()
    :{}
MovieHeader::MovieHeader(const MovieHeader& other) = default;
MovieHeader::~MovieHeader() = default;
FourCC MovieHeader::BoxType() const {}

bool MovieHeader::Parse(BoxReader* reader) {}

TrackHeader::TrackHeader()
    :{}
TrackHeader::TrackHeader(const TrackHeader& other) = default;
TrackHeader::~TrackHeader() = default;
FourCC TrackHeader::BoxType() const {}

bool TrackHeader::Parse(BoxReader* reader) {}

SampleDescription::SampleDescription() :{}
SampleDescription::SampleDescription(const SampleDescription& other) = default;
SampleDescription::~SampleDescription() = default;
FourCC SampleDescription::BoxType() const {}

bool SampleDescription::Parse(BoxReader* reader) {}

SampleTable::SampleTable() = default;
SampleTable::SampleTable(const SampleTable& other) = default;

SampleTable::~SampleTable() = default;
FourCC SampleTable::BoxType() const {}

bool SampleTable::Parse(BoxReader* reader) {}

EditList::EditList() = default;
EditList::EditList(const EditList& other) = default;
EditList::~EditList() = default;
FourCC EditList::BoxType() const {}

bool EditList::Parse(BoxReader* reader) {}

Edit::Edit() = default;
Edit::Edit(const Edit& other) = default;
Edit::~Edit() = default;
FourCC Edit::BoxType() const {}

bool Edit::Parse(BoxReader* reader) {}

HandlerReference::HandlerReference() :{}
HandlerReference::HandlerReference(const HandlerReference& other) = default;
HandlerReference::~HandlerReference() = default;
FourCC HandlerReference::BoxType() const {}

bool HandlerReference::Parse(BoxReader* reader) {}

#if BUILDFLAG(USE_PROPRIETARY_CODECS)
AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord()
    : version(0),
      profile_indication(0),
      profile_compatibility(0),
      avc_level(0),
      length_size(0) {}
AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord(
    const AVCDecoderConfigurationRecord& other) = default;
AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() = default;
FourCC AVCDecoderConfigurationRecord::BoxType() const { return FOURCC_AVCC; }

bool AVCDecoderConfigurationRecord::Parse(BoxReader* reader) {
  return ParseInternal(reader, reader->media_log());
}

bool AVCDecoderConfigurationRecord::Parse(const uint8_t* data, int data_size) {
  BufferReader reader(data, data_size);
  NullMediaLog media_log;
  return ParseInternal(&reader, &media_log);
}

bool AVCDecoderConfigurationRecord::ParseInternal(BufferReader* reader,
                                                  MediaLog* media_log) {
  RCHECK(reader->Read1(&version) && version == 1 &&
         reader->Read1(&profile_indication) &&
         reader->Read1(&profile_compatibility) &&
         reader->Read1(&avc_level));

  uint8_t length_size_minus_one;
  RCHECK(reader->Read1(&length_size_minus_one));
  length_size = (length_size_minus_one & 0x3) + 1;

  RCHECK(length_size != 3); // Only values of 1, 2, and 4 are valid.

  uint8_t num_sps;
  RCHECK(reader->Read1(&num_sps));
  num_sps &= 0x1f;

  sps_list.resize(num_sps);
  for (int i = 0; i < num_sps; i++) {
    uint16_t sps_length;
    RCHECK(reader->Read2(&sps_length) &&
           reader->ReadVec(&sps_list[i], sps_length));
    RCHECK(sps_list[i].size() > 4);
  }

  uint8_t num_pps;
  RCHECK(reader->Read1(&num_pps));

  pps_list.resize(num_pps);
  for (int i = 0; i < num_pps; i++) {
    uint16_t pps_length;
    RCHECK(reader->Read2(&pps_length) &&
           reader->ReadVec(&pps_list[i], pps_length));
  }

  if (profile_indication == 100 || profile_indication == 110 ||
      profile_indication == 122 || profile_indication == 144) {
    if (!ParseREXT(reader, media_log)) {
      DVLOG(2) << __func__ << ": avcC REXT is missing or invalid";
      chroma_format = 0;
      bit_depth_luma_minus8 = 0;
      bit_depth_chroma_minus8 = 0;
      sps_ext_list.resize(0);
    }
  }

  return true;
}

bool AVCDecoderConfigurationRecord::ParseREXT(BufferReader* reader,
                                              MediaLog* media_log) {
  RCHECK(reader->Read1(&chroma_format));
  chroma_format &= 0x3;

  RCHECK(reader->Read1(&bit_depth_luma_minus8));
  bit_depth_luma_minus8 &= 0x7;
  RCHECK(bit_depth_luma_minus8 <= 4);

  RCHECK(reader->Read1(&bit_depth_chroma_minus8));
  bit_depth_chroma_minus8 &= 0x7;
  RCHECK(bit_depth_chroma_minus8 <= 4);

  uint8_t num_sps_ext;
  RCHECK(reader->Read1(&num_sps_ext));

  sps_ext_list.resize(num_sps_ext);
  for (int i = 0; i < num_sps_ext; i++) {
    uint16_t sps_ext_length;
    RCHECK(reader->Read2(&sps_ext_length) &&
           reader->ReadVec(&sps_ext_list[i], sps_ext_length));
  }

  return true;
}

bool AVCDecoderConfigurationRecord::Serialize(
    std::vector<uint8_t>& output) const {
  if (sps_list.size() > 0x1f) {
    return false;
  }

  if (pps_list.size() > 0xff) {
    return false;
  }

  if (length_size != 1 && length_size != 2 && length_size != 4) {
    return false;
  }

  size_t expected_size =
      1 +  // configurationVersion
      1 +  // AVCProfileIndication
      1 +  // profile_compatibility
      1 +  // AVCLevelIndication
      1 +  // lengthSizeMinusOne
      1 +  // numOfSequenceParameterSets, i.e. length of sps_list
      1;   // numOfPictureParameterSets, i.e. length of pps_list

  for (auto& sps : sps_list) {
    expected_size += 2;  // sequenceParameterSetLength
    if (sps.size() > 0xffff) {
      return false;
    }
    expected_size += sps.size();
  }

  for (auto& pps : pps_list) {
    expected_size += 2;  // pictureParameterSetLength
    if (pps.size() > 0xffff) {
      return false;
    }
    expected_size += pps.size();
  }

  if (profile_indication == 100 || profile_indication == 110 ||
      profile_indication == 122 || profile_indication == 144) {
    if (chroma_format > 0x3) {
      return false;
    }

    if (bit_depth_luma_minus8 > 4) {
      return false;
    }

    if (bit_depth_chroma_minus8 > 4) {
      return false;
    }

    if (sps_ext_list.size() > 0xff) {
      return false;
    }

    expected_size += 1 +  // chroma_format
                     1 +  // bit_depth_luma_minus8
                     1 +  // bit_depth_chroma_minus8
                     1;   // numOfSequenceParameterSetExt

    for (auto& sps_ext : sps_ext_list) {
      expected_size += 2;  // sequenceParameterSetExtLength
      if (sps_ext.size() > 0xffff) {
        return false;
      }
      expected_size += sps_ext.size();
    }
  }

  output.clear();
  output.resize(expected_size);
  auto writer = base::SpanWriter(base::span(output));
  bool result = true;

  // configurationVersion
  result &= writer.WriteU8BigEndian(version);
  // AVCProfileIndication
  result &= writer.WriteU8BigEndian(profile_indication);
  // profile_compatibility
  result &= writer.WriteU8BigEndian(profile_compatibility);
  // AVCLevelIndication
  result &= writer.WriteU8BigEndian(avc_level);
  // lengthSizeMinusOne
  uint8_t length_size_minus_one = (length_size - 1) | 0xfc;
  result &= writer.WriteU8BigEndian(length_size_minus_one);
  // numOfSequenceParameterSets
  uint8_t sps_size = sps_list.size() | 0xe0;
  result &= writer.WriteU8BigEndian(sps_size);
  // sequenceParameterSetNALUnits
  for (auto& sps : sps_list) {
    result &= writer.WriteU16BigEndian(sps.size());
    result &= writer.Write(sps);
  }
  // numOfPictureParameterSets
  uint8_t pps_size = pps_list.size();
  result &= writer.WriteU8BigEndian(pps_size);
  // pictureParameterSetNALUnit
  for (auto& pps : pps_list) {
    result &= writer.WriteU16BigEndian(pps.size());
    result &= writer.Write(pps);
  }

  if (profile_indication == 100 || profile_indication == 110 ||
      profile_indication == 122 || profile_indication == 144) {
    // chroma_format
    result &= writer.WriteU8BigEndian(chroma_format | 0xfc);
    // bit_depth_luma_minus8
    result &= writer.WriteU8BigEndian(bit_depth_luma_minus8 | 0xf8);
    // bit_depth_chroma_minus8
    result &= writer.WriteU8BigEndian(bit_depth_chroma_minus8 | 0xf8);
    // numOfSequenceParameterSetExt
    uint8_t sps_ext_size = sps_ext_list.size();
    result &= writer.WriteU8BigEndian(sps_ext_size);
    // sequenceParameterSetExtNALUnit
    for (auto& sps_ext : sps_ext_list) {
      result &= writer.WriteU16BigEndian(sps_ext.size());
      result &= writer.Write(sps_ext);
    }
  }

  return result;
}

#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)

VPCodecConfigurationRecord::VPCodecConfigurationRecord()
    :{}

VPCodecConfigurationRecord::VPCodecConfigurationRecord(
    const VPCodecConfigurationRecord& other) = default;

VPCodecConfigurationRecord::~VPCodecConfigurationRecord() = default;

FourCC VPCodecConfigurationRecord::BoxType() const {}

bool VPCodecConfigurationRecord::Parse(BoxReader* reader) {}

#if BUILDFLAG(ENABLE_AV1_DECODER)
AV1CodecConfigurationRecord::AV1CodecConfigurationRecord() = default;

AV1CodecConfigurationRecord::AV1CodecConfigurationRecord(
    const AV1CodecConfigurationRecord& other) = default;

AV1CodecConfigurationRecord::~AV1CodecConfigurationRecord() = default;

FourCC AV1CodecConfigurationRecord::BoxType() const {}

bool AV1CodecConfigurationRecord::Parse(BoxReader* reader) {}

bool AV1CodecConfigurationRecord::Parse(const uint8_t* data, int data_size) {}

// Parse the AV1CodecConfigurationRecord, which has the following format:
// unsigned int (1) marker = 1;
// unsigned int (7) version = 1;
// unsigned int (3) seq_profile;
// unsigned int (5) seq_level_idx_0;
// unsigned int (1) seq_tier_0;
// unsigned int (1) high_bitdepth;
// unsigned int (1) twelve_bit;
// unsigned int (1) monochrome;
// unsigned int (1) chroma_subsampling_x;
// unsigned int (1) chroma_subsampling_y;
// unsigned int (2) chroma_sample_position;
// unsigned int (3) reserved = 0;
//
// unsigned int (1) initial_presentation_delay_present;
// if (initial_presentation_delay_present) {
//   unsigned int (4) initial_presentation_delay_minus_one;
// } else {
//   unsigned int (4) reserved = 0;
// }
//
// unsigned int (8)[] configOBUs;
bool AV1CodecConfigurationRecord::ParseInternal(BufferReader* reader,
                                                MediaLog* media_log) {}
#endif  // BUILDFLAG(ENABLE_AV1_DECODER)

PixelAspectRatioBox::PixelAspectRatioBox() :{}
PixelAspectRatioBox::PixelAspectRatioBox(const PixelAspectRatioBox& other) =
    default;
PixelAspectRatioBox::~PixelAspectRatioBox() = default;
FourCC PixelAspectRatioBox::BoxType() const {}

bool PixelAspectRatioBox::Parse(BoxReader* reader) {}

ColorParameterInformation::ColorParameterInformation() = default;
ColorParameterInformation::ColorParameterInformation(
    const ColorParameterInformation& other) = default;
ColorParameterInformation::~ColorParameterInformation() = default;
FourCC ColorParameterInformation::BoxType() const {}

bool ColorParameterInformation::Parse(BoxReader* reader) {}

MasteringDisplayColorVolume::MasteringDisplayColorVolume() = default;
MasteringDisplayColorVolume::MasteringDisplayColorVolume(
    const MasteringDisplayColorVolume& other) = default;
MasteringDisplayColorVolume::~MasteringDisplayColorVolume() = default;

FourCC MasteringDisplayColorVolume::BoxType() const {}

bool MasteringDisplayColorVolume::Parse(BoxReader* reader) {}

FourCC SMPTE2086MasteringDisplayMetadataBox::BoxType() const {}

bool SMPTE2086MasteringDisplayMetadataBox::Parse(BoxReader* reader) {}

ContentLightLevelInformation::ContentLightLevelInformation() = default;
ContentLightLevelInformation::ContentLightLevelInformation(
    const ContentLightLevelInformation& other) = default;
ContentLightLevelInformation::~ContentLightLevelInformation() = default;
FourCC ContentLightLevelInformation::BoxType() const {}

bool ContentLightLevelInformation::Parse(BoxReader* reader) {}

bool ContentLightLevel::Parse(BoxReader* reader) {}

FourCC ContentLightLevel::BoxType() const {}

VideoSampleEntry::VideoSampleEntry()
    :{}

VideoSampleEntry::VideoSampleEntry(const VideoSampleEntry& other) = default;

VideoSampleEntry::~VideoSampleEntry() = default;
FourCC VideoSampleEntry::BoxType() const {}

// static
VideoColorSpace VideoSampleEntry::ConvertColorParameterInformationToColorSpace(
    const ColorParameterInformation& info) {}

bool VideoSampleEntry::Parse(BoxReader* reader) {}

bool VideoSampleEntry::IsFormatValid() const {}

ElementaryStreamDescriptor::ElementaryStreamDescriptor()
    :{}

ElementaryStreamDescriptor::ElementaryStreamDescriptor(
    const ElementaryStreamDescriptor& other) = default;

ElementaryStreamDescriptor::~ElementaryStreamDescriptor() = default;

FourCC ElementaryStreamDescriptor::BoxType() const {}

bool ElementaryStreamDescriptor::Parse(BoxReader* reader) {}

FlacSpecificBox::FlacSpecificBox()
    :{}

FlacSpecificBox::FlacSpecificBox(const FlacSpecificBox& other) = default;

FlacSpecificBox::~FlacSpecificBox() = default;

FourCC FlacSpecificBox::BoxType() const {}

bool FlacSpecificBox::Parse(BoxReader* reader) {}

OpusSpecificBox::OpusSpecificBox()
    :{}

OpusSpecificBox::OpusSpecificBox(const OpusSpecificBox& other) = default;

OpusSpecificBox::~OpusSpecificBox() = default;

FourCC OpusSpecificBox::BoxType() const {}

bool OpusSpecificBox::Parse(BoxReader* reader) {}

#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
DtsSpecificBox::DtsSpecificBox() {}

DtsSpecificBox::DtsSpecificBox(const DtsSpecificBox& other) = default;

DtsSpecificBox::~DtsSpecificBox() = default;

FourCC DtsSpecificBox::BoxType() const {
  return FOURCC_DDTS;
}

bool DtsSpecificBox::Parse(BoxReader* reader) {
  // Read ddts into buffer.
  std::vector<uint8_t> dts_data;

  RCHECK(reader->ReadVec(&dts_data, reader->box_size() - reader->pos()));
  RCHECK(dts.Parse(dts_data, reader->media_log()));

  return true;
}

DtsUhdSpecificBox::DtsUhdSpecificBox() {}

DtsUhdSpecificBox::DtsUhdSpecificBox(const DtsUhdSpecificBox& other) = default;

DtsUhdSpecificBox::~DtsUhdSpecificBox() = default;

FourCC DtsUhdSpecificBox::BoxType() const {
  return FOURCC_UDTS;
}

bool DtsUhdSpecificBox::Parse(BoxReader* reader) {
  // Read udts into buffer.
  std::vector<uint8_t> dtsx_data;

  RCHECK(reader->ReadVec(&dtsx_data, reader->box_size() - reader->pos()));
  RCHECK(dtsx.Parse(dtsx_data, reader->media_log()));

  return true;
}
#endif  // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)

#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)
EC3SpecificBox::EC3SpecificBox() {}

EC3SpecificBox::EC3SpecificBox(const EC3SpecificBox& other) = default;

EC3SpecificBox::~EC3SpecificBox() = default;

FourCC EC3SpecificBox::BoxType() const {
  return FOURCC_DEC3;
}

bool EC3SpecificBox::Parse(BoxReader* reader) {
  // Read dec3 into buffer.
  std::vector<uint8_t> eac3_data;

  RCHECK(reader->ReadVec(&eac3_data, reader->box_size() - reader->pos()));
  RCHECK(dec3.Parse(eac3_data, reader->media_log()));

  return true;
}

AC3SpecificBox::AC3SpecificBox() {}

AC3SpecificBox::AC3SpecificBox(const AC3SpecificBox& other) = default;

AC3SpecificBox::~AC3SpecificBox() = default;

FourCC AC3SpecificBox::BoxType() const {
  return FOURCC_DAC3;
}

bool AC3SpecificBox::Parse(BoxReader* reader) {
  // Read dac3 into buffer.
  std::vector<uint8_t> ac3_data;

  RCHECK(reader->ReadVec(&ac3_data, reader->box_size() - reader->pos()));
  RCHECK(dac3.Parse(ac3_data, reader->media_log()));

  return true;
}
#endif  // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO)

#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
AC4SpecificBox::AC4SpecificBox() {}

AC4SpecificBox::AC4SpecificBox(const AC4SpecificBox& other) = default;

AC4SpecificBox::~AC4SpecificBox() = default;

FourCC AC4SpecificBox::BoxType() const {
  return FOURCC_DAC4;
}

bool AC4SpecificBox::Parse(BoxReader* reader) {
  // Read dac4 into buffer.
  std::vector<uint8_t> ac4_data;

  RCHECK(reader->ReadVec(&ac4_data, reader->box_size() - reader->pos()));
  RCHECK(dac4.Parse(ac4_data, reader->media_log()));

  return true;
}
#endif  // BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)

#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
enum IamfConfigObuType {
  // The following enum values are mapped to their respective Config OBU
  // values in the IAMF specification.
  // https://aomediacodec.github.io/iamf/v1.0.0.html#obu-header-syntax.
  kIamfConfigObuTypeCodecConfig = 0,
  kIamfConfigObuTypeAudioElement = 1,
  kIamfConfigObuTypeMixPresentation = 2,
  kIamfConfigObuTypeSequenceHeader = 31,
};

IamfSpecificBox::IamfSpecificBox() = default;

IamfSpecificBox::IamfSpecificBox(const IamfSpecificBox& other) = default;

IamfSpecificBox::~IamfSpecificBox() = default;

FourCC IamfSpecificBox::BoxType() const {
  return FOURCC_IACB;
}

bool IamfSpecificBox::Parse(BoxReader* reader) {
  uint8_t configuration_version;
  RCHECK(reader->Read1(&configuration_version));
  RCHECK(configuration_version == 0x01);

  uint32_t config_obus_size;
  RCHECK(ReadLeb128Value(reader, &config_obus_size));

  base::span<const uint8_t> buffer =
      reader->buffer().subspan(reader->pos(), config_obus_size);
  ia_descriptors.assign(buffer.begin(), buffer.end());

  RCHECK(reader->SkipBytes(config_obus_size));

  BufferReader config_reader(ia_descriptors.data(), ia_descriptors.size());

  while (config_reader.pos() < config_reader.buffer().size()) {
    RCHECK(ReadOBU(&config_reader));
  }

  return true;
}

bool IamfSpecificBox::ReadOBU(BufferReader* reader) {
  uint8_t obu_type;
  uint32_t obu_size;
  RCHECK(ReadOBUHeader(reader, &obu_type, &obu_size));
  const size_t read_stop_pos = reader->pos() + obu_size;

  switch (static_cast<int>(obu_type)) {
    case kIamfConfigObuTypeCodecConfig:
    case kIamfConfigObuTypeAudioElement:
    case kIamfConfigObuTypeMixPresentation:
      break;
    case kIamfConfigObuTypeSequenceHeader:
      uint32_t ia_code;
      RCHECK(reader->Read4(&ia_code));
      RCHECK(ia_code == FOURCC_IAMF);

      RCHECK(reader->Read1(&profile));
      RCHECK(profile <= 1);

      break;
    default:
      DVLOG(1) << "Unhandled IAMF OBU type " << static_cast<int>(obu_type);
      return false;
  }

  const size_t remaining_size = read_stop_pos - reader->pos();
  RCHECK(reader->SkipBytes(remaining_size));
  return true;
}

bool IamfSpecificBox::ReadOBUHeader(BufferReader* reader,
                                    uint8_t* obu_type,
                                    uint32_t* obu_size) {
  uint8_t header_flags;
  RCHECK(reader->Read1(&header_flags));
  *obu_type = (header_flags >> 3) & 0x1f;

  const bool obu_redundant_copy = (header_flags >> 2) & 1;
  const bool obu_trimming_status_flag = (header_flags >> 1) & 1;
  const bool obu_extension_flag = header_flags & 1;

  redundant_copy |= obu_redundant_copy;

  RCHECK(ReadLeb128Value(reader, obu_size));
  RCHECK(reader->HasBytes(*obu_size));

  RCHECK(!obu_trimming_status_flag);
  if (obu_extension_flag) {
    uint32_t extension_header_size;
    const int last_reader_pos = reader->pos();
    RCHECK(ReadLeb128Value(reader, &extension_header_size));
    const int num_leb128_bytes_read = reader->pos() - last_reader_pos;
    RCHECK(reader->SkipBytes(extension_header_size));
    obu_size -= (num_leb128_bytes_read + extension_header_size);
  }
  return true;
}

bool IamfSpecificBox::ReadLeb128Value(BufferReader* reader,
                                      uint32_t* value) const {
  DCHECK(reader);
  DCHECK(value);
  *value = 0;
  bool error = true;
  for (size_t i = 0; i < sizeof(uint32_t); ++i) {
    uint8_t byte;
    RCHECK(reader->Read1(&byte));
    *value |= ((byte & 0x7f) << (i * 7));
    if (!(byte & 0x80)) {
      error = false;
      break;
    }
  }

  return !error;
}
#endif  // BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)

AudioSampleEntry::AudioSampleEntry()
    :{}

AudioSampleEntry::AudioSampleEntry(const AudioSampleEntry& other) = default;

AudioSampleEntry::~AudioSampleEntry() = default;

FourCC AudioSampleEntry::BoxType() const {}

bool AudioSampleEntry::Parse(BoxReader* reader) {}

MediaHeader::MediaHeader()
    :{}
MediaHeader::MediaHeader(const MediaHeader& other) = default;
MediaHeader::~MediaHeader() = default;
FourCC MediaHeader::BoxType() const {}

bool MediaHeader::Parse(BoxReader* reader) {}

std::string MediaHeader::language() const {}

MediaInformation::MediaInformation() = default;
MediaInformation::MediaInformation(const MediaInformation& other) = default;
MediaInformation::~MediaInformation() = default;
FourCC MediaInformation::BoxType() const {}

bool MediaInformation::Parse(BoxReader* reader) {}

Media::Media() = default;
Media::Media(const Media& other) = default;
Media::~Media() = default;
FourCC Media::BoxType() const {}

bool Media::Parse(BoxReader* reader) {}

Track::Track() = default;
Track::Track(const Track& other) = default;
Track::~Track() = default;
FourCC Track::BoxType() const {}

bool Track::Parse(BoxReader* reader) {}

MovieExtendsHeader::MovieExtendsHeader() :{}
MovieExtendsHeader::MovieExtendsHeader(const MovieExtendsHeader& other) =
    default;
MovieExtendsHeader::~MovieExtendsHeader() = default;
FourCC MovieExtendsHeader::BoxType() const {}

bool MovieExtendsHeader::Parse(BoxReader* reader) {}

TrackExtends::TrackExtends()
    :{}
TrackExtends::TrackExtends(const TrackExtends& other) = default;
TrackExtends::~TrackExtends() = default;
FourCC TrackExtends::BoxType() const {}

bool TrackExtends::Parse(BoxReader* reader) {}

MovieExtends::MovieExtends() = default;
MovieExtends::MovieExtends(const MovieExtends& other) = default;
MovieExtends::~MovieExtends() = default;
FourCC MovieExtends::BoxType() const {}

bool MovieExtends::Parse(BoxReader* reader) {}

Movie::Movie() :{}
Movie::Movie(const Movie& other) = default;
Movie::~Movie() = default;
FourCC Movie::BoxType() const {}

bool Movie::Parse(BoxReader* reader) {}

TrackFragmentDecodeTime::TrackFragmentDecodeTime() :{}
TrackFragmentDecodeTime::TrackFragmentDecodeTime(
    const TrackFragmentDecodeTime& other) = default;
TrackFragmentDecodeTime::~TrackFragmentDecodeTime() = default;
FourCC TrackFragmentDecodeTime::BoxType() const {}

bool TrackFragmentDecodeTime::Parse(BoxReader* reader) {}

MovieFragmentHeader::MovieFragmentHeader() :{}
MovieFragmentHeader::MovieFragmentHeader(const MovieFragmentHeader& other) =
    default;
MovieFragmentHeader::~MovieFragmentHeader() = default;
FourCC MovieFragmentHeader::BoxType() const {}

bool MovieFragmentHeader::Parse(BoxReader* reader) {}

TrackFragmentHeader::TrackFragmentHeader()
    :{}

TrackFragmentHeader::TrackFragmentHeader(const TrackFragmentHeader& other) =
    default;
TrackFragmentHeader::~TrackFragmentHeader() = default;
FourCC TrackFragmentHeader::BoxType() const {}

bool TrackFragmentHeader::Parse(BoxReader* reader) {}

TrackFragmentRun::TrackFragmentRun()
    :{}
TrackFragmentRun::TrackFragmentRun(const TrackFragmentRun& other) = default;
TrackFragmentRun::~TrackFragmentRun() = default;
FourCC TrackFragmentRun::BoxType() const {}

bool TrackFragmentRun::Parse(BoxReader* reader) {}

SampleToGroup::SampleToGroup() :{}
SampleToGroup::SampleToGroup(const SampleToGroup& other) = default;
SampleToGroup::~SampleToGroup() = default;
FourCC SampleToGroup::BoxType() const {}

bool SampleToGroup::Parse(BoxReader* reader) {}

CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry()
    :{}
CencSampleEncryptionInfoEntry::CencSampleEncryptionInfoEntry(
    const CencSampleEncryptionInfoEntry& other) = default;
CencSampleEncryptionInfoEntry::~CencSampleEncryptionInfoEntry() = default;

bool CencSampleEncryptionInfoEntry::Parse(BoxReader* reader) {}

SampleGroupDescription::SampleGroupDescription() :{}
SampleGroupDescription::SampleGroupDescription(
    const SampleGroupDescription& other) = default;
SampleGroupDescription::~SampleGroupDescription() = default;
FourCC SampleGroupDescription::BoxType() const {}

bool SampleGroupDescription::Parse(BoxReader* reader) {}

TrackFragment::TrackFragment() = default;
TrackFragment::TrackFragment(const TrackFragment& other) = default;
TrackFragment::~TrackFragment() = default;
FourCC TrackFragment::BoxType() const {}

bool TrackFragment::Parse(BoxReader* reader) {}

MovieFragment::MovieFragment() = default;
MovieFragment::MovieFragment(const MovieFragment& other) = default;
MovieFragment::~MovieFragment() = default;
FourCC MovieFragment::BoxType() const {}

bool MovieFragment::Parse(BoxReader* reader) {}

IndependentAndDisposableSamples::IndependentAndDisposableSamples() = default;
IndependentAndDisposableSamples::IndependentAndDisposableSamples(
    const IndependentAndDisposableSamples& other) = default;
IndependentAndDisposableSamples::~IndependentAndDisposableSamples() = default;
FourCC IndependentAndDisposableSamples::BoxType() const {}

bool IndependentAndDisposableSamples::Parse(BoxReader* reader) {}

SampleDependsOn IndependentAndDisposableSamples::sample_depends_on(
    size_t i) const {}

}  // namespace mp4
}  // namespace media