diff --git a/packager/media/base/audio_stream_info.cc b/packager/media/base/audio_stream_info.cc index 5c5cd294dd5..052d74306a8 100644 --- a/packager/media/base/audio_stream_info.cc +++ b/packager/media/base/audio_stream_info.cc @@ -148,6 +148,8 @@ std::string AudioStreamInfo::GetCodecString(Codec codec, return "dts-"; case kCodecDTSP: return "dts+"; + case kCodecDTSX: + return "dtsx"; case kCodecEAC3: return "ec-3"; case kCodecAC4: diff --git a/packager/media/base/fourccs.h b/packager/media/base/fourccs.h index c721f2c81f5..dc4912ab4e2 100644 --- a/packager/media/base/fourccs.h +++ b/packager/media/base/fourccs.h @@ -57,6 +57,7 @@ enum FourCC : uint32_t { FOURCC_dtsl = 0x6474736c, FOURCC_dtsm = 0x6474732d, // "dts-" FOURCC_dtsp = 0x6474732b, // "dts+" + FOURCC_dtsx = 0x64747378, // "dtsx" FOURCC_dvcC = 0x64766343, FOURCC_dvh1 = 0x64766831, FOURCC_dvhe = 0x64766865, @@ -150,6 +151,7 @@ enum FourCC : uint32_t { FOURCC_trex = 0x74726578, FOURCC_trun = 0x7472756e, FOURCC_udta = 0x75647461, + FOURCC_udts = 0x75647473, // "udts" FOURCC_url = 0x75726c20, // "url " FOURCC_urn = 0x75726e20, // "urn " FOURCC_uuid = 0x75756964, diff --git a/packager/media/base/stream_info.h b/packager/media/base/stream_info.h index 4b711b43531..74da2941696 100644 --- a/packager/media/base/stream_info.h +++ b/packager/media/base/stream_info.h @@ -49,6 +49,7 @@ enum Codec { kCodecDTSL, kCodecDTSM, kCodecDTSP, + kCodecDTSX, kCodecEAC3, kCodecFlac, kCodecOpus, diff --git a/packager/media/codecs/codecs.gyp b/packager/media/codecs/codecs.gyp index 9993dd02f25..3657fbf10ba 100644 --- a/packager/media/codecs/codecs.gyp +++ b/packager/media/codecs/codecs.gyp @@ -27,6 +27,8 @@ 'decoder_configuration_record.h', 'dovi_decoder_configuration_record.cc', 'dovi_decoder_configuration_record.h', + 'dts_audio_specific_config.cc', + 'dts_audio_specific_config.h', 'ec3_audio_util.cc', 'ec3_audio_util.h', 'ac4_audio_util.cc', diff --git a/packager/media/codecs/dts_audio_specific_config.cc b/packager/media/codecs/dts_audio_specific_config.cc new file mode 100644 index 00000000000..a26b03dd340 --- /dev/null +++ b/packager/media/codecs/dts_audio_specific_config.cc @@ -0,0 +1,29 @@ +// Copyright (c) 2023 Xperi Inc. All Rights Reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "packager/media/codecs/dts_audio_specific_config.h" + + +#include "packager/base/logging.h" +#include "packager/media/base/bit_reader.h" +#include "packager/media/base/rcheck.h" + +namespace shaka { +namespace media { + +bool GetDTSXChannelMask(const std::vector &udts, uint32_t &mask) { + // udts is the DTS-UHD Specific Box: ETSI TS 103 491 V1.2.1 Table B-2 + // DecoderProfileCode(6 bits) + // FrameDurationCode(2 bits) + // MaxPayloadCode(3 bits) + // NumPresentationsCode(5 bits) + // ChannelMask (32 bits) + BitReader bit_reader(udts.data(), udts.size()); + RCHECK(bit_reader.SkipBits(16)); + RCHECK(bit_reader.ReadBits(32, &mask)); + return true; +} + +} // namespace media +} // namespace shaka diff --git a/packager/media/codecs/dts_audio_specific_config.h b/packager/media/codecs/dts_audio_specific_config.h new file mode 100644 index 00000000000..f36e10c66f8 --- /dev/null +++ b/packager/media/codecs/dts_audio_specific_config.h @@ -0,0 +1,23 @@ +// Copyright (c) 2023 Xperi Inc. All Rights Reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PACKAGER_MEDIA_CODECS_DTS_AUDIO_SPECIFIC_CONFIG_H_ +#define PACKAGER_MEDIA_CODECS_DTS_AUDIO_SPECIFIC_CONFIG_H_ + +#include +#include + +#include + +namespace shaka { +namespace media { + +class BitReader; + +bool GetDTSXChannelMask(const std::vector &udts, uint32_t &mask); + +} // namespace media +} // namespace shaka + +#endif // PACKAGER_MEDIA_CODECS_DTS_AUDIO_SPECIFIC_CONFIG_H_ diff --git a/packager/media/event/muxer_listener_internal.cc b/packager/media/event/muxer_listener_internal.cc index e71d0ec97c8..ec3681110f1 100644 --- a/packager/media/event/muxer_listener_internal.cc +++ b/packager/media/event/muxer_listener_internal.cc @@ -19,6 +19,7 @@ #include "packager/media/base/video_stream_info.h" #include "packager/media/codecs/ec3_audio_util.h" #include "packager/media/codecs/ac4_audio_util.h" +#include "packager/media/codecs/dts_audio_specific_config.h" #include "packager/mpd/base/media_info.pb.h" using ::google::protobuf::util::MessageDifferencer; @@ -162,6 +163,16 @@ void AddAudioInfo(const AudioStreamInfo* audio_stream_info, codec_data->set_ac4_ims_flag(ac4_ims_flag); codec_data->set_ac4_cbi_flag(ac4_cbi_flag); } + + if (audio_stream_info->codec() == kCodecDTSX) { + auto* codec_data = audio_info->mutable_codec_specific_data(); + uint32_t channel_mask; + if (!GetDTSXChannelMask(codec_config, channel_mask)) { + LOG(ERROR) << "Failed to parse DTSX channel mask."; + return; + } + codec_data->set_channel_mask(channel_mask); + } } void AddTextInfo(const TextStreamInfo& text_stream_info, diff --git a/packager/media/formats/mp4/box_definitions.cc b/packager/media/formats/mp4/box_definitions.cc index da818618001..508394c889d 100644 --- a/packager/media/formats/mp4/box_definitions.cc +++ b/packager/media/formats/mp4/box_definitions.cc @@ -1807,6 +1807,27 @@ size_t DTSSpecific::ComputeSizeInternal() { sizeof(kDdtsExtraData); } +UDTSSpecific::UDTSSpecific() = default; +UDTSSpecific::~UDTSSpecific() = default; + +FourCC UDTSSpecific::BoxType() const { + return FOURCC_udts; +} + +bool UDTSSpecific::ReadWriteInternal(BoxBuffer* buffer) { + RCHECK(ReadWriteHeaderInternal(buffer) && + buffer->ReadWriteVector( + &data, buffer->Reading() ? buffer->BytesLeft() : data.size())); + return true; +} + +size_t UDTSSpecific::ComputeSizeInternal() { + // This box is optional. Skip it if not initialized. + if (data.empty()) + return 0; + return HeaderSize() + data.size(); +} + AC3Specific::AC3Specific() = default; AC3Specific::~AC3Specific() = default; @@ -1979,6 +2000,7 @@ bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) { RCHECK(buffer->TryReadWriteChild(&esds)); RCHECK(buffer->TryReadWriteChild(&ddts)); + RCHECK(buffer->TryReadWriteChild(&udts)); RCHECK(buffer->TryReadWriteChild(&dac3)); RCHECK(buffer->TryReadWriteChild(&dec3)); RCHECK(buffer->TryReadWriteChild(&dac4)); @@ -2010,7 +2032,7 @@ size_t AudioSampleEntry::ComputeSizeInternal() { sizeof(samplesize) + sizeof(samplerate) + sinf.ComputeSize() + esds.ComputeSize() + ddts.ComputeSize() + dac3.ComputeSize() + dec3.ComputeSize() + dops.ComputeSize() + dfla.ComputeSize() + - dac4.ComputeSize() + mhac.ComputeSize() + + dac4.ComputeSize() + mhac.ComputeSize() + udts.ComputeSize() + // Reserved and predefined bytes. 6 + 8 + // 6 + 8 bytes reserved. 4; // 4 bytes predefined. diff --git a/packager/media/formats/mp4/box_definitions.h b/packager/media/formats/mp4/box_definitions.h index ce67bd98d68..c1cc9d3d833 100644 --- a/packager/media/formats/mp4/box_definitions.h +++ b/packager/media/formats/mp4/box_definitions.h @@ -334,6 +334,12 @@ struct DTSSpecific : Box { std::vector extra_data; }; +struct UDTSSpecific : Box { + DECLARE_BOX_METHODS(UDTSSpecific); + + std::vector data; +}; + struct AC3Specific : Box { DECLARE_BOX_METHODS(AC3Specific); @@ -396,6 +402,7 @@ struct AudioSampleEntry : Box { ElementaryStreamDescriptor esds; DTSSpecific ddts; + UDTSSpecific udts; AC3Specific dac3; EC3Specific dec3; AC4Specific dac4; diff --git a/packager/media/formats/mp4/mp4_media_parser.cc b/packager/media/formats/mp4/mp4_media_parser.cc index 16981e234f2..07acecc23cf 100644 --- a/packager/media/formats/mp4/mp4_media_parser.cc +++ b/packager/media/formats/mp4/mp4_media_parser.cc @@ -88,6 +88,8 @@ Codec FourCCToCodec(FourCC fourcc) { return kCodecDTSL; case FOURCC_dtse: return kCodecDTSE; + case FOURCC_dtsx: + return kCodecDTSX; case FOURCC_dtsp: return kCodecDTSP; case FOURCC_dtsm: @@ -489,6 +491,9 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) { max_bitrate = entry.ddts.max_bitrate; avg_bitrate = entry.ddts.avg_bitrate; break; + case FOURCC_dtsx: + codec_config = entry.udts.data; + break; case FOURCC_ac_3: codec_config = entry.dac3.data; num_channels = static_cast(GetAc3NumChannels(codec_config)); diff --git a/packager/media/formats/mp4/mp4_muxer.cc b/packager/media/formats/mp4/mp4_muxer.cc index 31e7c55c73a..e84d0ef3dfb 100644 --- a/packager/media/formats/mp4/mp4_muxer.cc +++ b/packager/media/formats/mp4/mp4_muxer.cc @@ -83,6 +83,8 @@ FourCC CodecToFourCC(Codec codec, H26xStreamFormat h26x_stream_format) { return FOURCC_dtse; case kCodecDTSM: return FOURCC_dtsm; + case kCodecDTSX: + return FOURCC_dtsx; case kCodecEAC3: return FOURCC_ec_3; case kCodecAC4: @@ -493,6 +495,9 @@ bool MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info, audio.ddts.sampling_frequency = audio_info->sampling_frequency(); audio.ddts.pcm_sample_depth = audio_info->sample_bits(); break; + case kCodecDTSX: + audio.udts.data = audio_info->codec_config(); + break; case kCodecAC3: audio.dac3.data = audio_info->codec_config(); break; diff --git a/packager/mpd/base/xml/xml_node.cc b/packager/mpd/base/xml/xml_node.cc index 1a1ef64f94c..cb1e0fd5119 100644 --- a/packager/mpd/base/xml/xml_node.cc +++ b/packager/mpd/base/xml/xml_node.cc @@ -43,6 +43,9 @@ typedef MediaInfo::VideoInfo VideoInfo; namespace { const char kEC3Codec[] = "ec-3"; const char kAC4Codec[] = "ac-4"; +const char kDTSCCodec[] = "dtsc"; +const char kDTSECodec[] = "dtse"; +const char kDTSXCodec[] = "dtsx"; std::string RangeToString(const Range& range) { return base::Uint64ToString(range.begin()) + "-" + @@ -606,6 +609,19 @@ bool RepresentationXmlNode::AddAudioChannelInfo(const AudioInfo& audio_info) { "1"); } return ret; + } else if (audio_info.codec() == kDTSCCodec || + audio_info.codec() == kDTSECodec) { + audio_channel_config_value = base::UintToString(audio_info.num_channels()); + audio_channel_config_scheme = + "tag:dts.com,2014:dash:audio_channel_configuration:2012"; + } else if (audio_info.codec() == kDTSXCodec) { + const auto& codec_data = audio_info.codec_specific_data(); + const uint32_t channel_config = + base::HostToNet32(codec_data.channel_mask()); + audio_channel_config_value = + base::HexEncode(&channel_config, sizeof(channel_config)); + audio_channel_config_scheme = + "tag:dts.com,2018:uhd:audio_channel_configuration"; } else { audio_channel_config_value = base::UintToString(audio_info.num_channels()); audio_channel_config_scheme =