Skip to content

Commit

Permalink
Added unit tests for DTS audio
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy-Funderburk committed Feb 8, 2024
1 parent bc95591 commit b94f315
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 0 deletions.
7 changes: 7 additions & 0 deletions packager/app/test/packager_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,13 @@ def testAacHe(self):
self._GetFlags(output_dash=True))
self._CheckTestResults('acc-he')

def testDtsx(self):
self.assertPackageSuccess(
self._GetStreams(
['audio'], test_files=['bear-dtsx.mp4']),
self._GetFlags(output_dash=True))
self._CheckTestResults('dtsx-dash')

def testVideoAudioWebVTT(self):
audio_video_streams = self._GetStreams(['audio', 'video'])
text_stream = self._GetStreams(['text'], test_files=['bear-english.vtt'])
Expand Down
Binary file not shown.
15 changes: 15 additions & 0 deletions packager/app/test/testdata/dtsx-dash/output.mpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT3.114666700363159S">
<Period id="0">
<AdaptationSet id="0" contentType="audio" subsegmentAlignment="true">
<Representation id="0" bandwidth="227665" codecs="dtsx" mimeType="audio/mp4" audioSamplingRate="48000">
<AudioChannelConfiguration schemeIdUri="tag:dts.com,2018:uhd:audio_channel_configuration" value="0000003F"/>
<BaseURL>bear-dtsx-audio.mp4</BaseURL>
<SegmentBase indexRange="742-821" timescale="48000">
<Initialization range="0-741"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>
37 changes: 37 additions & 0 deletions packager/media/codecs/dts_audio_specific_config_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2023 Google 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 <gtest/gtest.h>

#include "packager/media/codecs/dts_audio_specific_config.h"

namespace shaka {
namespace media {

TEST(DTSAudioSpecificConfigTest, BasicProfileTest) {
uint8_t buffer[] = {0x01, 0x20, 0x00, 0x00, 0x0, 0x3F, 0x80, 0x00};
std::vector<uint8_t> data(std::begin(buffer), std::end(buffer));
uint32_t mask;
EXPECT_TRUE(GetDTSXChannelMask(data, mask));
EXPECT_EQ(0x3F, mask);
}

TEST(DTSAudioSpecificConfigTest, ChannelMaskBytes) {
uint8_t buffer[] = {0x01, 0x20, 0x12, 0x34, 0x56, 0x78, 0x80, 0x00};
std::vector<uint8_t> data(std::begin(buffer), std::end(buffer));
uint32_t mask;
EXPECT_TRUE(GetDTSXChannelMask(data, mask));
EXPECT_EQ(0x12345678, mask);
}

TEST(DTSAudioSpecificConfigTest, Truncated) {
uint8_t buffer[] = {0x01, 0x20, 0x00, 0x00, 0x00};
std::vector<uint8_t> data(std::begin(buffer), std::end(buffer));
uint32_t mask;
EXPECT_FALSE(GetDTSXChannelMask(data, mask));
}

} // namespace media
} // namespace shaka
18 changes: 18 additions & 0 deletions packager/media/event/muxer_listener_internal_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ TEST_F(MuxerListenerInternalVideoStreamTest, TransferCharacteristics) {
EXPECT_EQ(18u, media_info.video_info().transfer_characteristics());
}

class MuxerListenerInternalAudioStreamTest : public MuxerListenerInternalTest {
};

// AddAudioInfo function should parse the channel mask
TEST_F(MuxerListenerInternalAudioStreamTest, DTSX) {
MediaInfo media_info;
std::shared_ptr<AudioStreamInfo> audio_info = CreateAudioStreamInfo(
GetAudioStreamInfoParams(kCodecDTSX, "dtsx",
{0x01, 0x20, 0x00, 0x00, 0x0, 0x3F, 0x80,
0x00})); // Channel mask = 3F
ASSERT_TRUE(GenerateMediaInfo(MuxerOptions(), *audio_info,
kReferenceTimeScale,
MuxerListener::kContainerMp4, &media_info));
MediaInfo_AudioInfo* info = media_info.mutable_audio_info();
auto* codec_data = info->mutable_codec_specific_data();
EXPECT_EQ(0x3F, codec_data->channel_mask());
}

} // namespace internal
} // namespace media
} // namespace shaka
48 changes: 48 additions & 0 deletions packager/media/event/muxer_listener_test_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,53 @@ std::vector<ProtectionSystemSpecificInfo> GetDefaultKeySystemInfo() {
std::end(kExpectedDefaultPsshBox) - 1}}};
}

AudioStreamInfoParameters::AudioStreamInfoParameters() {}
AudioStreamInfoParameters::~AudioStreamInfoParameters() {}

std::shared_ptr<AudioStreamInfo> CreateAudioStreamInfo(
const AudioStreamInfoParameters& param) {
return std::make_shared<AudioStreamInfo>(
param.track_id, param.time_scale, param.duration, param.codec,
param.codec_string, param.codec_config.data(), param.codec_config.size(),
param.sample_bits, param.num_channels, param.sampling_frequency,
param.seek_preroll_ns, param.codec_delay_ns, param.max_bitrate,
param.avg_bitrate, param.language, param.is_encrypted);
}

AudioStreamInfoParameters GetAudioStreamInfoParams(
Codec codec,
const char* codec_string,
const std::vector<uint8_t>& codec_config) {
const int kTrackId = 0;
const int32_t kTimeScale = 10;
const int64_t kAudioStreamDuration = 200;
const char* kLanuageUndefined = "und";
const uint8_t kSampleBits = 16;
const uint8_t kNumChannels = 6;
const uint32_t kSamplingFrequency = 48000;
const uint64_t kSeekPrerollNs = 0;
const uint64_t kCodecDelayNs = 0;
const uint32_t kMaxBitrate = 0;
const uint32_t kAvgBitrate = 0;
const bool kEncryptedFlag = false;
AudioStreamInfoParameters params;
params.track_id = kTrackId;
params.time_scale = kTimeScale;
params.duration = kAudioStreamDuration;
params.codec = codec;
params.codec_string = codec_string;
params.language = kLanuageUndefined;
params.sample_bits = kSampleBits;
params.num_channels = kNumChannels;
params.sampling_frequency = kSamplingFrequency;
params.seek_preroll_ns = kSeekPrerollNs;
params.codec_delay_ns = kCodecDelayNs;
params.max_bitrate = kMaxBitrate;
params.avg_bitrate = kAvgBitrate;
params.codec_config = codec_config;
params.is_encrypted = kEncryptedFlag;
return params;
}

} // namespace media
} // namespace shaka
34 changes: 34 additions & 0 deletions packager/media/event/muxer_listener_test_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <cstdint>
#include <vector>

#include "packager/media/base/audio_stream_info.h"
#include <packager/media/base/key_source.h>
#include <packager/media/base/muxer_options.h>
#include <packager/media/base/stream_info.h>
Expand Down Expand Up @@ -93,6 +94,29 @@ struct VideoStreamInfoParameters {
bool is_encrypted;
};

// Struct that gets passed for to CreateAudioStreamInfo() to create a
// StreamInfo instance. Useful for generating multiple AudioStreamInfo with
// slightly different parameters.
struct AudioStreamInfoParameters {
AudioStreamInfoParameters();
~AudioStreamInfoParameters();
int track_id;
int32_t time_scale;
int64_t duration;
Codec codec;
std::string codec_string;
std::vector<uint8_t> codec_config;
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;
std::string language;
bool is_encrypted;
};

struct OnNewSegmentParameters {
std::string file_name;
int64_t start_time;
Expand All @@ -113,6 +137,16 @@ std::shared_ptr<VideoStreamInfo> CreateVideoStreamInfo(
// Returns the "default" VideoStreamInfoParameters for testing.
VideoStreamInfoParameters GetDefaultVideoStreamInfoParams();

// Creates StreamInfo instance from AudioStreamInfoParameters.
std::shared_ptr<AudioStreamInfo> CreateAudioStreamInfo(
const AudioStreamInfoParameters& param);

// Returns the "default" configuration for testing given codec and parameters.
AudioStreamInfoParameters GetAudioStreamInfoParams(
Codec codec,
const char* codec_string,
const std::vector<uint8_t>& codec_config);

// Returns the "default" values for OnMediaEnd().
OnMediaEndParameters GetDefaultOnMediaEndParams();

Expand Down
24 changes: 24 additions & 0 deletions packager/media/formats/mp4/box_definitions_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,16 @@ class BoxDefinitionsTestGeneral : public testing::Test {
ddts->pcm_sample_depth = 24;
}

void Fill(UDTSSpecific* udts) {
const uint8_t kUdtsData[] = {0x01, 0x20, 0x00, 0x00, 0x0, 0x3F, 0x80, 0x00};
udts->data.assign(kUdtsData, kUdtsData + arraysize(kUdtsData));
}

void Modify(UDTSSpecific* udts) {
const uint8_t kUdtsData[] = {0x01, 0x20, 0x01, 0x80, 0xA, 0x3F, 0x80, 0x00};
udts->data.assign(kUdtsData, kUdtsData + arraysize(kUdtsData));
}

void Fill(AC3Specific* dac3) {
const uint8_t kAc3Data[] = {0x50, 0x11, 0x60};
dac3->data.assign(kAc3Data, kAc3Data + std::size(kAc3Data));
Expand Down Expand Up @@ -1217,6 +1227,20 @@ TEST_F(BoxDefinitionsTest, DTSSampleEntry) {
ASSERT_EQ(entry, entry_readback);
}

TEST_F(BoxDefinitionsTest, UDTSSampleEntry) {
AudioSampleEntry entry;
entry.format = FOURCC_dtsx;
entry.data_reference_index = 2;
entry.channelcount = 6;
entry.samplesize = 16;
entry.samplerate = 48000;
Fill(&entry.udts);
entry.Write(this->buffer_.get());
AudioSampleEntry entry_readback;
ASSERT_TRUE(ReadBack(&entry_readback));
ASSERT_EQ(entry, entry_readback);
}

TEST_F(BoxDefinitionsTest, AC3SampleEntry) {
AudioSampleEntry entry;
entry.format = FOURCC_ac_3;
Expand Down
Binary file added packager/media/test/data/bear-dtsx.mp4
Binary file not shown.
56 changes: 56 additions & 0 deletions packager/mpd/base/xml/xml_node_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -766,5 +766,61 @@ TEST_F(LowLatencySegmentTest, LowLatencySegmentTemplate) {
"</Representation>"));
}

TEST(XmlNodeTest, AddDTSCAudioInfo) {
MediaInfo::AudioInfo audio_info;
audio_info.set_codec("dtsc");
audio_info.set_sampling_frequency(48000);
audio_info.set_num_channels(6);

RepresentationXmlNode representation;
ASSERT_TRUE(representation.AddAudioInfo(audio_info));
EXPECT_THAT(
representation,
XmlNodeEqual(
"<Representation audioSamplingRate=\"48000\">\n"
" <AudioChannelConfiguration\n"
" schemeIdUri=\n"
" \"tag:dts.com,2014:dash:audio_channel_configuration:2012\"\n"
" value=\"6\"/>\n"
"</Representation>\n"));
}

TEST(XmlNodeTest, AddDTSEAudioInfo) {
MediaInfo::AudioInfo audio_info;
audio_info.set_codec("dtse");
audio_info.set_sampling_frequency(48000);
audio_info.set_num_channels(6);

RepresentationXmlNode representation;
ASSERT_TRUE(representation.AddAudioInfo(audio_info));
EXPECT_THAT(
representation,
XmlNodeEqual(
"<Representation audioSamplingRate=\"48000\">\n"
" <AudioChannelConfiguration\n"
" schemeIdUri=\n"
" \"tag:dts.com,2014:dash:audio_channel_configuration:2012\"\n"
" value=\"6\"/>\n"
"</Representation>\n"));
}

TEST(XmlNodeTest, AddDTSXAudioInfo) {
MediaInfo::AudioInfo audio_info;
audio_info.set_codec("dtsx");
audio_info.set_sampling_frequency(48000);
audio_info.mutable_codec_specific_data()->set_channel_mask(0x3F);

RepresentationXmlNode representation;
ASSERT_TRUE(representation.AddAudioInfo(audio_info));
EXPECT_THAT(
representation,
XmlNodeEqual("<Representation audioSamplingRate=\"48000\">\n"
" <AudioChannelConfiguration\n"
" schemeIdUri=\n"
" \"tag:dts.com,2018:uhd:audio_channel_configuration\"\n"
" value=\"0000003F\"/>\n"
"</Representation>\n"));
}

} // namespace xml
} // namespace shaka

0 comments on commit b94f315

Please sign in to comment.