// 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 #include #include #include #include #include #include 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 AudioStreamInfo::Clone() const { return std::unique_ptr(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. // // - xxx is the IAMF primary profile // - yyy is the IAMF additional profile // - 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