231 lines
7.4 KiB
C++
231 lines
7.4 KiB
C++
// Copyright 2014 Google LLC. All rights reserved.
|
||
//
|
||
// Use of this source code is governed by a BSD-style
|
||
// license that can be found in the LICENSE file or at
|
||
// https://developers.google.com/open-source/licenses/bsd
|
||
|
||
#include <packager/media/base/audio_stream_info.h>
|
||
|
||
#include <cinttypes>
|
||
|
||
#include <absl/log/log.h>
|
||
#include <absl/strings/str_format.h>
|
||
|
||
#include <packager/macros/compiler.h>
|
||
#include <packager/macros/logging.h>
|
||
#include <packager/media/base/limits.h>
|
||
|
||
namespace shaka {
|
||
namespace media {
|
||
|
||
namespace {
|
||
std::string AudioCodecToString(Codec codec) {
|
||
switch (codec) {
|
||
case kCodecAAC:
|
||
return "AAC";
|
||
case kCodecAC3:
|
||
return "AC3";
|
||
case kCodecALAC:
|
||
return "ALAC";
|
||
case kCodecDTSC:
|
||
return "DTSC";
|
||
case kCodecDTSE:
|
||
return "DTSE";
|
||
case kCodecDTSH:
|
||
return "DTSH";
|
||
case kCodecDTSL:
|
||
return "DTSL";
|
||
case kCodecDTSM:
|
||
return "DTS-";
|
||
case kCodecDTSP:
|
||
return "DTS+";
|
||
case kCodecEAC3:
|
||
return "EAC3";
|
||
case kCodecAC4:
|
||
return "AC4";
|
||
case kCodecFlac:
|
||
return "FLAC";
|
||
case kCodecIAMF:
|
||
return "IAMF";
|
||
case kCodecOpus:
|
||
return "Opus";
|
||
case kCodecVorbis:
|
||
return "Vorbis";
|
||
case kCodecMP3:
|
||
return "MP3";
|
||
default:
|
||
NOTIMPLEMENTED() << "Unknown Audio Codec: " << codec;
|
||
return "UnknownCodec";
|
||
}
|
||
}
|
||
|
||
FourCC CodecToFourCC(Codec codec) {
|
||
switch (codec) {
|
||
case kCodecMha1:
|
||
return FOURCC_mha1;
|
||
case kCodecMhm1:
|
||
return FOURCC_mhm1;
|
||
default:
|
||
return FOURCC_NULL;
|
||
}
|
||
}
|
||
} // namespace
|
||
|
||
AudioStreamInfo::AudioStreamInfo(int track_id,
|
||
int32_t time_scale,
|
||
int64_t duration,
|
||
Codec codec,
|
||
const std::string& codec_string,
|
||
const uint8_t* codec_config,
|
||
size_t codec_config_size,
|
||
uint8_t sample_bits,
|
||
uint8_t num_channels,
|
||
uint32_t sampling_frequency,
|
||
uint64_t seek_preroll_ns,
|
||
uint64_t codec_delay_ns,
|
||
uint32_t max_bitrate,
|
||
uint32_t avg_bitrate,
|
||
const std::string& language,
|
||
bool is_encrypted)
|
||
: StreamInfo(kStreamAudio,
|
||
track_id,
|
||
time_scale,
|
||
duration,
|
||
codec,
|
||
codec_string,
|
||
codec_config,
|
||
codec_config_size,
|
||
language,
|
||
is_encrypted),
|
||
sample_bits_(sample_bits),
|
||
num_channels_(num_channels),
|
||
sampling_frequency_(sampling_frequency),
|
||
seek_preroll_ns_(seek_preroll_ns),
|
||
codec_delay_ns_(codec_delay_ns),
|
||
max_bitrate_(max_bitrate),
|
||
avg_bitrate_(avg_bitrate) {}
|
||
|
||
AudioStreamInfo::~AudioStreamInfo() {}
|
||
|
||
bool AudioStreamInfo::IsValidConfig() const {
|
||
return codec() != kUnknownCodec && num_channels_ != 0 &&
|
||
num_channels_ <= limits::kMaxChannels && sample_bits_ > 0 &&
|
||
sample_bits_ <= limits::kMaxBitsPerSample && sampling_frequency_ > 0 &&
|
||
sampling_frequency_ <= limits::kMaxSampleRate;
|
||
}
|
||
|
||
std::string AudioStreamInfo::ToString() const {
|
||
std::string str = absl::StrFormat(
|
||
"%s codec: %s\n sample_bits: %d\n num_channels: %d\n "
|
||
"sampling_frequency: %d\n language: %s\n",
|
||
StreamInfo::ToString().c_str(), AudioCodecToString(codec()).c_str(),
|
||
sample_bits_, num_channels_, sampling_frequency_, language().c_str());
|
||
if (seek_preroll_ns_ != 0) {
|
||
absl::StrAppendFormat(&str, " seek_preroll_ns: %" PRIu64 "\n",
|
||
seek_preroll_ns_);
|
||
}
|
||
if (codec_delay_ns_ != 0) {
|
||
absl::StrAppendFormat(&str, " codec_delay_ns: %" PRIu64 "\n",
|
||
codec_delay_ns_);
|
||
}
|
||
return str;
|
||
}
|
||
|
||
std::unique_ptr<StreamInfo> AudioStreamInfo::Clone() const {
|
||
return std::unique_ptr<StreamInfo>(new AudioStreamInfo(*this));
|
||
}
|
||
|
||
std::string AudioStreamInfo::GetCodecString(Codec codec,
|
||
uint8_t audio_object_type) {
|
||
switch (codec) {
|
||
case kCodecAAC:
|
||
return "mp4a.40." + absl::StrFormat("%hhu", audio_object_type);
|
||
case kCodecAC3:
|
||
return "ac-3";
|
||
case kCodecALAC:
|
||
return "alac";
|
||
case kCodecDTSC:
|
||
return "dtsc";
|
||
case kCodecDTSE:
|
||
return "dtse";
|
||
case kCodecDTSH:
|
||
return "dtsh";
|
||
case kCodecDTSL:
|
||
return "dtsl";
|
||
case kCodecDTSM:
|
||
return "dts-";
|
||
case kCodecDTSP:
|
||
return "dts+";
|
||
case kCodecDTSX:
|
||
return "dtsx";
|
||
case kCodecEAC3:
|
||
return "ec-3";
|
||
case kCodecAC4:
|
||
// ETSI TS 103 190-2 Digital Audio Compression (AC-4) Standard; Part 2:
|
||
// Immersive and personalized audio E.13. audio_object_type is composed of
|
||
// bitstream_version (3bits), presentation_version (2bits) and
|
||
// mdcompat (3bits).
|
||
return absl::StrFormat(
|
||
"ac-4.%02d.%02d.%02d", (audio_object_type & 0xE0) >> 5,
|
||
(audio_object_type & 0x18) >> 3, audio_object_type & 0x7);
|
||
case kCodecFlac:
|
||
return "flac";
|
||
case kCodecIAMF: {
|
||
// https://aomediacodec.github.io/iamf/#codecsparameter
|
||
// The codecs parameter string is composed as
|
||
//
|
||
// iamf.xxx.yyy.<standalone_codec_string>
|
||
//
|
||
// - xxx is the IAMF primary profile
|
||
// - yyy is the IAMF additional profile
|
||
// - <standalone_codec_string> are the elements of the codecs parameter
|
||
// string if that stream was carried in its own track
|
||
//
|
||
// audio_object_type is composed of primary_profile (2 bits),
|
||
// additional_profile (2 bits) and (IAMF codec - kCodecAudio) (4 bits).
|
||
const int iamf_codec = (audio_object_type & 0xF) + kCodecAudio;
|
||
|
||
const std::string iamf_codec_string =
|
||
absl::StrFormat("iamf.%03d.%03d", (audio_object_type & 0xC0) >> 6,
|
||
(audio_object_type & 0x30) >> 4);
|
||
|
||
switch (iamf_codec) {
|
||
case kCodecOpus:
|
||
return absl::StrFormat("%s.%s", iamf_codec_string, "Opus");
|
||
case kCodecAAC:
|
||
return absl::StrFormat("%s.%s", iamf_codec_string, "mp4a.40.2");
|
||
case kCodecFlac:
|
||
return absl::StrFormat("%s.%s", iamf_codec_string, "fLaC");
|
||
case kCodecPcm:
|
||
return absl::StrFormat("%s.%s", iamf_codec_string, "ipcm");
|
||
default:
|
||
LOG(WARNING) << "Unknown IAMF codec: " << iamf_codec;
|
||
return "unknown";
|
||
}
|
||
}
|
||
case kCodecOpus:
|
||
return "opus";
|
||
case kCodecMP3:
|
||
return "mp3";
|
||
case kCodecVorbis:
|
||
return "vorbis";
|
||
case kCodecMha1:
|
||
case kCodecMhm1:
|
||
// The signalling of the codecs parameters is according to RFC6381 [11]
|
||
// and ISO/IEC 23008-3 clause 21 [7].
|
||
// The value consists of the following two parts separated by a dot:
|
||
// - the sample entry 4CC code ('mha1', 'mha2', 'mhm1', 'mhm2')
|
||
// - ‘0x’ followed by the hex value of the profile-levelid, as defined
|
||
// in in ISO/IEC 23008-3 [7]
|
||
return absl::StrFormat("%s.0x%02x",
|
||
FourCCToString(CodecToFourCC(codec)).c_str(),
|
||
audio_object_type);
|
||
default:
|
||
NOTIMPLEMENTED() << "Codec: " << codec;
|
||
return "unknown";
|
||
}
|
||
}
|
||
|
||
} // namespace media
|
||
} // namespace shaka
|