Skip to content

Commit

Permalink
Add DTS Enumerations and Definitions for DTS Audio Support
Browse files Browse the repository at this point in the history
This CL adds DTS Enumerations and Definitions for supporting playback of media streams that has DTS audio.

Bug: 1270685

Change-Id: I5ca12650e99adb2c1c659ac7446190349a5350f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3271232
Commit-Queue: Mark Foltz <mfoltz@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Yuchen Liu <yucliu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#948239}
  • Loading branch information
cedricxperi authored and Chromium LUCI CQ committed Dec 4, 2021
1 parent 8470674 commit a145d57
Show file tree
Hide file tree
Showing 27 changed files with 976 additions and 4 deletions.
4 changes: 4 additions & 0 deletions AUTHORS
Expand Up @@ -189,6 +189,7 @@ Camille Viot <viot.camille@outlook.com>
Carlos Santa <carlos.santa@intel.com>
Catalin Badea <badea@adobe.com>
Cathie Chen <cathiechen@tencent.com>
Cedric Tio <cedric.tio@xperi.com>
Cem Kocagil <cem.kocagil@gmail.com>
Cezary Kułakowski <cezary.kulakowski@gmail.com>
Chakshu Ahuja <chakshu.a@samsung.com>
Expand Down Expand Up @@ -305,6 +306,7 @@ Dongwoo Joshua Im <dw.im@samsung.com>
Dongyu Lin <l2d4y3@gmail.com>
Donna Wu <donna.wu@intel.com>
Douglas F. Turner <doug.turner@gmail.com>
Douglas Wong <Douglas.wong@xperi.com>
Dustin Doloff <doloffd@amazon.com>
Ebrahim Byagowi <ebrahim@gnu.org>
Ebrahim Byagowi <ebraminio@gmail.com>
Expand Down Expand Up @@ -959,6 +961,7 @@ Rosen Dash <nqk836@motorola.com>
Rosen Dash <rosen.dash@gmail.com>
Ross Kirsling <rkirsling@gmail.com>
Ross Wollman <ross.wollman@gmail.com>
Roy Funderburk <roy.funderburk@xperi.com>
Ruan Beihong <ruanbeihong@gmail.com>
ruben <chromium@hybridsource.org>
Ruben Bridgewater <ruben@bridgewater.de>
Expand Down Expand Up @@ -1348,6 +1351,7 @@ Venture 3 Systems LLC <*@venture3systems.com>
Vewd Software AS <*@vewd.com>
Vivaldi Technologies AS <*@vivaldi.com>
Wacom <*@wacom.com>
Xperi Corporation <*@xperi.com>
Yandex LLC <*@yandex-team.ru>
# Please DO NOT APPEND here. See comments at the top of the file.
# END organizations section.
2 changes: 2 additions & 0 deletions chromecast/media/cma/base/decoder_config_adapter.cc
Expand Up @@ -52,6 +52,8 @@ SampleFormat ToSampleFormat(const ::media::SampleFormat sample_format) {
case ::media::kUnknownSampleFormat:
case ::media::kSampleFormatAc3:
case ::media::kSampleFormatEac3:
case ::media::kSampleFormatDts:
case ::media::kSampleFormatDtsxP2:
case ::media::kSampleFormatMpegHAudio:
return kUnknownSampleFormat;
case ::media::kSampleFormatU8:
Expand Down
1 change: 1 addition & 0 deletions media/BUILD.gn
Expand Up @@ -51,6 +51,7 @@ buildflag_header("media_buildflags") {
"USE_CHROMEOS_PROTECTED_AV1=$use_chromeos_protected_av1",
"USE_CHROMEOS_PROTECTED_MEDIA=$use_chromeos_protected_media",
"USE_PROPRIETARY_CODECS=$proprietary_codecs",
"ENABLE_PLATFORM_DTS_AUDIO=$enable_platform_dts_audio",
]
}

Expand Down
2 changes: 2 additions & 0 deletions media/base/audio_buffer.cc
Expand Up @@ -508,6 +508,8 @@ void AudioBuffer::TrimRange(int start, int end) {
case kSampleFormatAc3:
case kSampleFormatEac3:
case kSampleFormatMpegHAudio:
case kSampleFormatDts:
case kSampleFormatDtsxP2:
NOTREACHED() << "Invalid sample format!";
}
} else {
Expand Down
4 changes: 4 additions & 0 deletions media/base/audio_codecs.cc
Expand Up @@ -47,6 +47,10 @@ std::string GetCodecName(AudioCodec codec) {
return "ac3";
case AudioCodec::kMpegHAudio:
return "mpeg-h-audio";
case AudioCodec::kDTS:
return "dts";
case AudioCodec::kDTSXP2:
return "dtsx-p2";
}
}

Expand Down
4 changes: 3 additions & 1 deletion media/base/audio_codecs.h
Expand Up @@ -33,13 +33,15 @@ enum class AudioCodec {
kALAC = 15,
kAC3 = 16,
kMpegHAudio = 17,
kDTS = 18,
kDTSXP2 = 19,
// DO NOT ADD RANDOM AUDIO CODECS!
//
// The only acceptable time to add a new codec is if there is production code
// that uses said codec in the same CL.

// Must always be equal to the largest entry ever logged.
kMaxValue = kMpegHAudio,
kMaxValue = kDTSXP2,
};

enum class AudioCodecProfile {
Expand Down
16 changes: 16 additions & 0 deletions media/base/sample_format.cc
Expand Up @@ -19,6 +19,8 @@ int SampleFormatToBytesPerChannel(SampleFormat sample_format) {
case kSampleFormatAc3:
case kSampleFormatEac3:
case kSampleFormatMpegHAudio:
case kSampleFormatDts:
case kSampleFormatDtsxP2:
return 1;
case kSampleFormatS16:
case kSampleFormatPlanarS16:
Expand Down Expand Up @@ -67,6 +69,10 @@ const char* SampleFormatToString(SampleFormat sample_format) {
return "Compressed E-AC3 bitstream";
case kSampleFormatMpegHAudio:
return "Compressed MPEG-H audio bitstream";
case kSampleFormatDts:
return "Compressed DTS bitstream";
case kSampleFormatDtsxP2:
return "Compressed DTSXP2 bitstream";
}
NOTREACHED() << "Invalid sample format provided: " << sample_format;
return "";
Expand All @@ -88,6 +94,8 @@ bool IsPlanar(SampleFormat sample_format) {
case kSampleFormatAc3:
case kSampleFormatEac3:
case kSampleFormatMpegHAudio:
case kSampleFormatDts:
case kSampleFormatDtsxP2:
return false;
}

Expand All @@ -105,6 +113,8 @@ bool IsInterleaved(SampleFormat sample_format) {
case kSampleFormatAc3:
case kSampleFormatEac3:
case kSampleFormatMpegHAudio:
case kSampleFormatDts:
case kSampleFormatDtsxP2:
return true;
case kUnknownSampleFormat:
case kSampleFormatPlanarU8:
Expand All @@ -123,6 +133,12 @@ bool IsBitstream(SampleFormat sample_format) {
case kSampleFormatAc3:
case kSampleFormatEac3:
case kSampleFormatMpegHAudio:
case kSampleFormatDts:
case kSampleFormatDtsxP2:
// If on-device decoding is required, the sample format will be
// kSampleFormatS16, so it will return false. If bit-stream passthrough
// is required, the sample format would already be
// kSampleFormatDts/DtsxP2. In this case, it should return true as below.
return true;
case kUnknownSampleFormat:
case kSampleFormatU8:
Expand Down
4 changes: 3 additions & 1 deletion media/base/sample_format.h
Expand Up @@ -27,9 +27,11 @@ enum SampleFormat {
kSampleFormatEac3, // Compressed E-AC3 bitstream.
kSampleFormatMpegHAudio, // Compressed MPEG-H audio bitstream.
kSampleFormatPlanarU8, // Unsigned 8-bit w/ bias of 128 planar.
kSampleFormatDts, // Compressed DTS audio bitstream.
kSampleFormatDtsxP2, // Compressed DTSX audio bitstream.

// Must always be equal to largest value ever logged.
kSampleFormatMax = kSampleFormatMpegHAudio,
kSampleFormatMax = kSampleFormatDtsxP2,
};

// Returns the number of bytes used per channel for the specified
Expand Down
4 changes: 4 additions & 0 deletions media/base/supported_types.cc
Expand Up @@ -214,6 +214,8 @@ bool IsAudioCodecProprietary(AudioCodec codec) {
case AudioCodec::kGSM_MS:
case AudioCodec::kALAC:
case AudioCodec::kMpegHAudio:
case AudioCodec::kDTS:
case AudioCodec::kDTSXP2:
return true;

case AudioCodec::kFLAC:
Expand Down Expand Up @@ -277,6 +279,8 @@ bool IsDefaultSupportedAudioType(const AudioType& type) {
case AudioCodec::kALAC:
case AudioCodec::kAC3:
case AudioCodec::kMpegHAudio:
case AudioCodec::kDTS:
case AudioCodec::kDTSXP2:
case AudioCodec::kUnknown:
return false;
}
Expand Down
5 changes: 3 additions & 2 deletions media/filters/stream_parser_factory.cc
Expand Up @@ -65,8 +65,9 @@ struct CodecInfo {
HISTOGRAM_FLAC,
HISTOGRAM_AV1,
HISTOGRAM_MPEG_H_AUDIO,
HISTOGRAM_MAX =
HISTOGRAM_MPEG_H_AUDIO // Must be equal to largest logged entry.
HISTOGRAM_DTS,
HISTOGRAM_DTSXP2,
HISTOGRAM_MAX = HISTOGRAM_DTSXP2 // Must be equal to largest logged entry.
};

const char* pattern;
Expand Down
21 changes: 21 additions & 0 deletions media/formats/BUILD.gn
Expand Up @@ -123,6 +123,19 @@ source_set("formats") {
]
}

if (proprietary_codecs && enable_platform_dts_audio) {
sources += [
"dts/dts_stream_parser.cc",
"dts/dts_stream_parser.h",
"dts/dts_util.cc",
"dts/dts_util.h",
"mp4/dts.cc",
"mp4/dts.h",
"mp4/dtsx.cc",
"mp4/dtsx.h",
]
}

if (proprietary_codecs && enable_mse_mpeg2ts_stream_parser) {
deps += [ "//ui/gfx/geometry" ]
sources += [
Expand Down Expand Up @@ -256,6 +269,14 @@ source_set("unit_tests") {

deps += [ "//crypto" ]

if (enable_platform_dts_audio) {
sources += [
"dts/dts_util_unittest.cc",
"mp4/dts_unittest.cc",
"mp4/dtsx_unittest.cc",
]
}

if (enable_mse_mpeg2ts_stream_parser) {
sources += [
"mp2t/es_adapter_video_unittest.cc",
Expand Down
95 changes: 95 additions & 0 deletions media/formats/dts/dts_stream_parser.cc
@@ -0,0 +1,95 @@
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/formats/dts/dts_stream_parser.h"

#include <stddef.h>

#include "build/build_config.h"
#include "media/base/media_log.h"

namespace media {

DTSStreamParser::DTSStreamParser()
: MPEGAudioStreamParserBase(kDTSCoreSyncWord, AudioCodec::kDTS, 0) {}

DTSStreamParser::~DTSStreamParser() = default;

int DTSStreamParser::ParseFrameHeader(const uint8_t* data,
int size,
int* frame_size,
int* sample_rate,
ChannelLayout* channel_layout,
int* sample_count,
bool* metadata_frame,
std::vector<uint8_t>* extra_data) {
if (data == nullptr || size < kDTSCoreHeaderSizeInBytes)
return 0;

BitReader reader(data, size);

// Read and validate Sync word.
uint32_t sync_word = 0;
reader.ReadBits(32, &sync_word);
if (sync_word != kDTSCoreSyncWord)
return 0;

int fsize = 0, ext_audio = 0, ext_audio_id = 0, nblks = 0, sfreq = 0;

// Skip ftype(1-bit) + DeficitSample Count(5-bits) + CRC Present Flag(1-bit)
reader.SkipBits(7);
reader.ReadBits(7, &nblks);
reader.ReadBits(14, &fsize);
reader.SkipBits(6); // Skip AMODE
reader.ReadBits(4, &sfreq);
reader.SkipBits(10); // Skip: RATE, FixedBit, DNYF, TIMEF, AUSX, HDCD
reader.ReadBits(3, &ext_audio_id);
reader.ReadBits(1, &ext_audio);

constexpr int kSampleRateCore[16] = {0, 8000, 16000, 32000, 0, 0,
11025, 22050, 44100, 0, 0, 12000,
24000, 48000, 0, 0};

if (fsize < 95) // Invalid values of FSIZE is 0-94.
return 0;

if (nblks < 5 || nblks > 127) // Valid values of nblks is 5-127.
return 0;

if (kSampleRateCore[sfreq] == 0) // Table value of 0 indicates invalid
return 0;

// extended audio may modify sample count and rate
bool is_core_x96 = ext_audio && ext_audio_id == 2;

if (channel_layout)
*channel_layout = media::CHANNEL_LAYOUT_5_1;

if (extra_data)
extra_data->clear();

if (frame_size)
*frame_size = fsize + 1; // Framesize is FSIZE + 1.

if (metadata_frame)
*metadata_frame = false;

// Use nblks to compute frame duration, a.k.a number of PCM samples per
// channel in the current DTS frames in the buffer.
if (sample_count) {
*sample_count = (nblks + 1) * 32; // Num of PCM samples in current frame
if (is_core_x96)
*sample_count <<= 1;
}

if (sample_rate) {
*sample_rate = kSampleRateCore[sfreq]; // sfreq is table lookup
if (is_core_x96)
*sample_rate <<= 1;
}

return reader.bits_read() / 8;
}

} // namespace media
39 changes: 39 additions & 0 deletions media/formats/dts/dts_stream_parser.h
@@ -0,0 +1,39 @@
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_FORMATS_DTS_DTS_STREAM_PARSER_H_
#define MEDIA_FORMATS_DTS_DTS_STREAM_PARSER_H_

#include <stdint.h>
#include <vector>

#include "media/base/media_export.h"
#include "media/formats/mpeg/mpeg_audio_stream_parser_base.h"

namespace media {

class MEDIA_EXPORT DTSStreamParser : public MPEGAudioStreamParserBase {
public:
DTSStreamParser();
~DTSStreamParser() override;

enum {
kDTSCoreHeaderSizeInBytes = 15,
kDTSCoreSyncWord = 0x7ffe8001,
};

// MPEGAudioStreamParserBase overrides.
int ParseFrameHeader(const uint8_t* data,
int size,
int* frame_size,
int* sample_rate,
ChannelLayout* channel_layout,
int* sample_count,
bool* metadata_frame,
std::vector<uint8_t>* extra_data) override;
};

} // namespace media

#endif // MEDIA_FORMATS_DTS_DTS_STREAM_PARSER_H_

0 comments on commit a145d57

Please sign in to comment.