chromium/media/formats/mp4/dtsx.cc

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

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

#include "base/logging.h"
#include "media/base/bit_reader.h"
#include "media/formats/mp4/rcheck.h"

namespace media {

namespace mp4 {

DTSX::DTSX() = default;

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

DTSX::~DTSX() = default;

bool DTSX::Parse(const std::vector<uint8_t>& data, MediaLog* media_log) {
  if (data.empty())
    return false;

  if (data.size() < (2 + 3 + 5 + 32 + 1 + 2 + 8) / 8)
    return false;
  DVLOG(3) << "dtsx data.size " << data.size();
  // Parse udts box using reader.
  BitReader reader(&data[0], data.size());

  // Read DecoderProfileCode
  RCHECK(reader.ReadBits(6, &decoder_profile_code_));

  // Read FrameDurationCode
  uint8_t frame_duration_code = 0;
  RCHECK(reader.ReadBits(2, &frame_duration_code));
  switch (frame_duration_code) {
    case 0:
      frame_duration_ = 512;
      break;
    case 1:
      frame_duration_ = 1024;
      break;
    case 2:
      frame_duration_ = 2048;
      break;
    case 3:
      frame_duration_ = 4096;
      break;
    default:
      frame_duration_ = 0;
      break;
  }

  // Read MaxPayloadCode
  uint8_t max_payload_code = 0;
  RCHECK(reader.ReadBits(3, &max_payload_code));
  switch (max_payload_code) {
    case 0:
      max_payload_ = 2048;
      break;
    case 1:
      max_payload_ = 4096;
      break;
    case 2:
      max_payload_ = 8192;
      break;
    case 3:
      max_payload_ = 16384;
      break;
    case 4:
      max_payload_ = 32768;
      break;
    case 5:
      max_payload_ = 65536;
      break;
    case 6:
      max_payload_ = 131072;
      break;
    case 7:
    default:
      max_payload_ = 0;
      break;
  }

  // Read NumPresentationsCode
  RCHECK(reader.ReadBits(5, &num_presentations_));

  // Read ChannelMask
  RCHECK(reader.ReadBits(32, &channel_mask_));

  // Read BaseSamplingFrequencyCode
  int base_sampling_frequency = 0;
  uint8_t base_sampling_frequency_code = 0;
  RCHECK(reader.ReadBits(1, &base_sampling_frequency_code));
  if (base_sampling_frequency_code == 1)
    base_sampling_frequency = 48000;
  else
    base_sampling_frequency = 44100;

  // Read SampleRateMod
  int sample_rate_mod = 0;
  uint8_t sample_rate_mod_code;
  RCHECK(reader.ReadBits(2, &sample_rate_mod_code));
  switch (sample_rate_mod) {
    case 0:
      sample_rate_mod = 1;
      break;
    case 1:
      sample_rate_mod = 2;
      break;
    case 2:
      sample_rate_mod = 4;
      break;
    case 3:
      sample_rate_mod = 8;
      break;
    default:
      // error, should not hit default case.
      DLOG(ERROR) << "SampleRateMod invalid value";
      return false;
  }

  // Calculate the Sampling Frequency
  sampling_frequency_ = base_sampling_frequency * sample_rate_mod;

  LogDtsxParameters();
  return true;
}

uint8_t DTSX::GetDecoderProfileCode() const {
  return decoder_profile_code_;
}

int DTSX::GetFrameDuration() const {
  return frame_duration_;
}

int DTSX::GetMaxPayload() const {
  return max_payload_;
}

int DTSX::GetNumPresentations() const {
  return num_presentations_;
}

uint32_t DTSX::GetChannelMask() const {
  return channel_mask_;
}

int DTSX::GetSamplingFrequency() const {
  return sampling_frequency_;
}

void DTSX::LogDtsxParameters() {
  DVLOG(3) << "DecoderProfileCode " << static_cast<int>(decoder_profile_code_)
           << "Frame Duration " << frame_duration_ << "Max Payload "
           << max_payload_ << "Num Presentations " << num_presentations_
           << "Channel Mask " << channel_mask_ << "Sampling Frequency "
           << sampling_frequency_;
}

}  // namespace mp4
}  // namespace media