Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add DTS:X audio support for DASH and HLS-fMP4 #1302

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packager/media/base/audio_stream_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions packager/media/base/fourccs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions packager/media/base/stream_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ enum Codec {
kCodecDTSL,
kCodecDTSM,
kCodecDTSP,
kCodecDTSX,
kCodecEAC3,
kCodecFlac,
kCodecOpus,
Expand Down
2 changes: 2 additions & 0 deletions packager/media/codecs/codecs.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
29 changes: 29 additions & 0 deletions packager/media/codecs/dts_audio_specific_config.cc
Original file line number Diff line number Diff line change
@@ -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<uint8_t> &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
23 changes: 23 additions & 0 deletions packager/media/codecs/dts_audio_specific_config.h
Original file line number Diff line number Diff line change
@@ -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 <stddef.h>
#include <stdint.h>

#include <vector>

namespace shaka {
namespace media {

class BitReader;

bool GetDTSXChannelMask(const std::vector<uint8_t> &udts, uint32_t &mask);

} // namespace media
} // namespace shaka

#endif // PACKAGER_MEDIA_CODECS_DTS_AUDIO_SPECIFIC_CONFIG_H_
11 changes: 11 additions & 0 deletions packager/media/event/muxer_listener_internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
24 changes: 23 additions & 1 deletion packager/media/formats/mp4/box_definitions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions packager/media/formats/mp4/box_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,12 @@ struct DTSSpecific : Box {
std::vector<uint8_t> extra_data;
};

struct UDTSSpecific : Box {
DECLARE_BOX_METHODS(UDTSSpecific);

std::vector<uint8_t> data;
};

struct AC3Specific : Box {
DECLARE_BOX_METHODS(AC3Specific);

Expand Down Expand Up @@ -396,6 +402,7 @@ struct AudioSampleEntry : Box {

ElementaryStreamDescriptor esds;
DTSSpecific ddts;
UDTSSpecific udts;
AC3Specific dac3;
EC3Specific dec3;
AC4Specific dac4;
Expand Down
5 changes: 5 additions & 0 deletions packager/media/formats/mp4/mp4_media_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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<uint8_t>(GetAc3NumChannels(codec_config));
Expand Down
5 changes: 5 additions & 0 deletions packager/media/formats/mp4/mp4_muxer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions packager/mpd/base/xml/xml_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()) + "-" +
Expand Down Expand Up @@ -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 =
Expand Down