Split AdaptationSets by content type, container, codec, and language

This adds a new function to key AdaptationSets based on the
characteristics that require separate sets.

With this, we are now able to package multi-codec assets at once
(AVC1/MP4 and VP9/WebM in the same manifest, but in different
AdaptationSets).

Fixes b/27534371

Change-Id: Ie82fd096d2ef99fd23e323d60fd0849b1e8d7500
This commit is contained in:
Joey Parrish 2016-03-08 11:19:12 -08:00
parent b6718a37c5
commit f3e19fc002
14 changed files with 272 additions and 174 deletions

View File

@ -74,15 +74,8 @@ bool DashIopMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
return false; return false;
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
std::string lang; const std::string key = GetAdaptationSetKey(media_info);
if (media_info.has_audio_info()) { AdaptationSet* adaptation_set = GetAdaptationSetForMediaInfo(key, media_info);
lang = media_info.audio_info().language();
} else if (media_info.has_text_info()) {
lang = media_info.text_info().language();
}
AdaptationSet* adaptation_set =
GetAdaptationSetForMediaInfo(media_info, content_type, lang);
DCHECK(adaptation_set); DCHECK(adaptation_set);
if (media_info.has_text_info()) { if (media_info.has_text_info()) {
// IOP requires all AdaptationSets to have (sub)segmentAlignment set to // IOP requires all AdaptationSets to have (sub)segmentAlignment set to
@ -100,7 +93,7 @@ bool DashIopMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
representation_id_to_adaptation_set_[representation->id()] = adaptation_set; representation_id_to_adaptation_set_[representation->id()] = adaptation_set;
SetGroupId(content_type, lang, adaptation_set); SetGroupId(key, adaptation_set);
*container_id = representation->id(); *container_id = representation->id();
DCHECK(!ContainsKey(representation_map_, representation->id())); DCHECK(!ContainsKey(representation_map_, representation->id()));
@ -169,13 +162,11 @@ bool DashIopMpdNotifier::Flush() {
} }
AdaptationSet* DashIopMpdNotifier::GetAdaptationSetForMediaInfo( AdaptationSet* DashIopMpdNotifier::GetAdaptationSetForMediaInfo(
const MediaInfo& media_info, const std::string& key,
ContentType content_type, const MediaInfo& media_info) {
const std::string& language) { std::list<AdaptationSet*>& adaptation_sets = adaptation_set_list_map_[key];
std::list<AdaptationSet*>& adaptation_sets =
adaptation_set_list_map_[content_type][language];
if (adaptation_sets.empty()) if (adaptation_sets.empty())
return NewAdaptationSet(media_info, language, &adaptation_sets); return NewAdaptationSet(media_info, &adaptation_sets);
const bool has_protected_content = media_info.has_protected_content(); const bool has_protected_content = media_info.has_protected_content();
@ -204,13 +195,12 @@ AdaptationSet* DashIopMpdNotifier::GetAdaptationSetForMediaInfo(
// None of the adaptation sets match with the new content protection. // None of the adaptation sets match with the new content protection.
// Need a new one. // Need a new one.
return NewAdaptationSet(media_info, language, &adaptation_sets); return NewAdaptationSet(media_info, &adaptation_sets);
} }
// Get all the UUIDs of the AdaptationSet. If another AdaptationSet has the // Get all the UUIDs of the AdaptationSet. If another AdaptationSet has the
// same UUIDs then those should be groupable. // same UUIDs then those should be groupable.
void DashIopMpdNotifier::SetGroupId(ContentType type, void DashIopMpdNotifier::SetGroupId(const std::string& key,
const std::string& language,
AdaptationSet* adaptation_set) { AdaptationSet* adaptation_set) {
if (adaptation_set->Group() >= 0) // @group already assigned. if (adaptation_set->Group() >= 0) // @group already assigned.
return; return;
@ -230,7 +220,7 @@ void DashIopMpdNotifier::SetGroupId(ContentType type,
GetUUIDs(protected_content_it->second); GetUUIDs(protected_content_it->second);
std::list<AdaptationSet*>& same_type_adapatation_sets = std::list<AdaptationSet*>& same_type_adapatation_sets =
adaptation_set_list_map_[type][language]; adaptation_set_list_map_[key];
DCHECK(!same_type_adapatation_sets.empty()) DCHECK(!same_type_adapatation_sets.empty())
<< "same_type_adapatation_sets should not be null, it should at least " << "same_type_adapatation_sets should not be null, it should at least "
"contain adaptation_set"; "contain adaptation_set";
@ -270,8 +260,8 @@ void DashIopMpdNotifier::SetGroupId(ContentType type,
AdaptationSet* DashIopMpdNotifier::NewAdaptationSet( AdaptationSet* DashIopMpdNotifier::NewAdaptationSet(
const MediaInfo& media_info, const MediaInfo& media_info,
const std::string& language,
std::list<AdaptationSet*>* adaptation_sets) { std::list<AdaptationSet*>* adaptation_sets) {
std::string language = GetLanguage(media_info);
AdaptationSet* new_adaptation_set = mpd_builder_->AddAdaptationSet(language); AdaptationSet* new_adaptation_set = mpd_builder_->AddAdaptationSet(language);
if (media_info.has_protected_content()) { if (media_info.has_protected_content()) {
DCHECK(!ContainsKey(protected_content_map_, new_adaptation_set->id())); DCHECK(!ContainsKey(protected_content_map_, new_adaptation_set->id()));

View File

@ -70,22 +70,17 @@ class DashIopMpdNotifier : public MpdNotifier {
// This does not necessarily return a new AdaptationSet. If // This does not necessarily return a new AdaptationSet. If
// media_info.protected_content completely matches with an existing // media_info.protected_content completely matches with an existing
// AdaptationSet, then it will return the pointer. // AdaptationSet, then it will return the pointer.
AdaptationSet* GetAdaptationSetForMediaInfo(const MediaInfo& media_info, AdaptationSet* GetAdaptationSetForMediaInfo(const std::string& key,
ContentType type, const MediaInfo& media_info);
const std::string& language);
// Sets a group id for |adaptation_set| if applicable. // Sets a group id for |adaptation_set| if applicable.
// If a group ID is already assigned, then this returns immediately. // If a group ID is already assigned, then this returns immediately.
// |type| and |language| are the type and language of |adaptation_set|. void SetGroupId(const std::string& key, AdaptationSet* adaptation_set);
void SetGroupId(ContentType type,
const std::string& language,
AdaptationSet* adaptation_set);
// Helper function to get a new AdaptationSet; registers the values // Helper function to get a new AdaptationSet; registers the values
// to the fields (maps) of the instance. // to the fields (maps) of the instance.
// If the media is encrypted, registers data to protected_content_map_. // If the media is encrypted, registers data to protected_content_map_.
AdaptationSet* NewAdaptationSet(const MediaInfo& media_info, AdaptationSet* NewAdaptationSet(const MediaInfo& media_info,
const std::string& language,
std::list<AdaptationSet*>* adaptation_sets); std::list<AdaptationSet*>* adaptation_sets);
// Testing only method. Returns a pointer to MpdBuilder. // Testing only method. Returns a pointer to MpdBuilder.
@ -98,10 +93,7 @@ class DashIopMpdNotifier : public MpdNotifier {
mpd_builder_ = mpd_builder.Pass(); mpd_builder_ = mpd_builder.Pass();
} }
// [type][lang] = list<AdaptationSet> std::map<std::string, std::list<AdaptationSet*>> adaptation_set_list_map_;
// Note: lang can be empty, e.g. for video.
std::map<ContentType, std::map<std::string, std::list<AdaptationSet*> > >
adaptation_set_list_map_;
RepresentationMap representation_map_; RepresentationMap representation_map_;
// Used to check whether a Representation should be added to an AdaptationSet. // Used to check whether a Representation should be added to an AdaptationSet.

View File

@ -776,6 +776,102 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
EXPECT_TRUE(notifier.Flush()); EXPECT_TRUE(notifier.Flush());
} }
// Don't put different audio languages or codecs in the same AdaptationSet.
TEST_P(DashIopMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
// MP4, English
const char kAudioContent1[] =
"audio_info {\n"
" codec: 'mp4a.40.2'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'eng'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_MP4\n"
"media_duration_seconds: 10.5\n";
// MP4, German
const char kAudioContent2[] =
"audio_info {\n"
" codec: 'mp4a.40.2'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'ger'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_MP4\n"
"media_duration_seconds: 10.5\n";
// WebM, German
const char kAudioContent3[] =
"audio_info {\n"
" codec: 'vorbis'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'ger'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_WEBM\n"
"media_duration_seconds: 10.5\n";
// WebM, German again
const char kAudioContent4[] =
"audio_info {\n"
" codec: 'vorbis'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'ger'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_WEBM\n"
"media_duration_seconds: 10.5\n";
DashIopMpdNotifier notifier(dash_profile(), empty_mpd_option_,
empty_base_urls_, output_path_);
scoped_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder(mpd_type()));
scoped_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
scoped_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
scoped_ptr<MockAdaptationSet> adaptation_set3(new MockAdaptationSet(3));
scoped_ptr<MockRepresentation> representation1(new MockRepresentation(1));
scoped_ptr<MockRepresentation> representation2(new MockRepresentation(2));
scoped_ptr<MockRepresentation> representation3(new MockRepresentation(3));
scoped_ptr<MockRepresentation> representation4(new MockRepresentation(4));
// We expect three AdaptationSets.
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
.WillOnce(Return(adaptation_set1.get()))
.WillOnce(Return(adaptation_set2.get()))
.WillOnce(Return(adaptation_set3.get()));
// The first AdaptationSet should have Eng MP4, one Representation.
EXPECT_CALL(*adaptation_set1, AddRepresentation(_))
.WillOnce(Return(representation1.get()));
// The second AdaptationSet should have Ger MP4, one Representation.
EXPECT_CALL(*adaptation_set2, AddRepresentation(_))
.WillOnce(Return(representation2.get()));
// The third AdaptationSet should have Ger WebM, two Representations.
EXPECT_CALL(*adaptation_set3, AddRepresentation(_))
.WillOnce(Return(representation3.get()))
.WillOnce(Return(representation4.get()));
uint32_t unused_container_id;
SetMpdBuilder(&notifier, mock_mpd_builder.Pass());
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent1), &unused_container_id));
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent2), &unused_container_id));
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent3), &unused_container_id));
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent4), &unused_container_id));
}
INSTANTIATE_TEST_CASE_P(StaticAndDynamic, INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
DashIopMpdNotifierTest, DashIopMpdNotifierTest,
::testing::Values(MpdBuilder::kStatic, ::testing::Values(MpdBuilder::kStatic,

View File

@ -57,6 +57,16 @@ void RemoveDuplicateAttributes(
attributes.erase("schemeIdUri"); attributes.erase("schemeIdUri");
} }
std::string GetLanguage(const MediaInfo& media_info) {
std::string lang;
if (media_info.has_audio_info()) {
lang = media_info.audio_info().language();
} else if (media_info.has_text_info()) {
lang = media_info.text_info().language();
}
return lang;
}
std::string GetCodecs(const MediaInfo& media_info) { std::string GetCodecs(const MediaInfo& media_info) {
CHECK(OnlyOneTrue(media_info.has_video_info(), media_info.has_audio_info(), CHECK(OnlyOneTrue(media_info.has_video_info(), media_info.has_audio_info(),
media_info.has_text_info())); media_info.has_text_info()));
@ -86,6 +96,47 @@ std::string GetCodecs(const MediaInfo& media_info) {
return ""; return "";
} }
std::string GetBaseCodec(const MediaInfo& media_info) {
std::string codec;
if (media_info.has_video_info()) {
codec = media_info.video_info().codec();
} else if (media_info.has_audio_info()) {
codec = media_info.audio_info().codec();
} else if (media_info.has_text_info()) {
codec = media_info.text_info().format();
}
// Convert, for example, "mp4a.40.2" to simply "mp4a".
// "mp4a.40.2" and "mp4a.40.5" can exist in the same AdaptationSet.
size_t dot = codec.find('.');
if (dot != std::string::npos) {
codec.erase(dot);
}
return codec;
}
std::string GetAdaptationSetKey(const MediaInfo& media_info) {
std::string key;
if (media_info.has_video_info()) {
key.append("video:");
} else if (media_info.has_audio_info()) {
key.append("audio:");
} else if (media_info.has_text_info()) {
key.append(MediaInfo_TextInfo_TextType_Name(media_info.text_info().type()));
key.append(":");
} else {
key.append("unknown:");
}
key.append(MediaInfo_ContainerType_Name(media_info.container_type()));
key.append(":");
key.append(GetBaseCodec(media_info));
key.append(":");
key.append(GetLanguage(media_info));
return key;
}
std::string SecondsToXmlDuration(double seconds) { std::string SecondsToXmlDuration(double seconds) {
return "PT" + base::DoubleToString(seconds) + "S"; return "PT" + base::DoubleToString(seconds) + "S";
} }

View File

@ -40,10 +40,20 @@ bool HasLiveOnlyFields(const MediaInfo& media_info);
void RemoveDuplicateAttributes( void RemoveDuplicateAttributes(
ContentProtectionElement* content_protection_element); ContentProtectionElement* content_protection_element);
// Returns a language tag. May be blank for video.
std::string GetLanguage(const MediaInfo& media_info);
// Returns a 'codecs' string that has all the video and audio codecs joined with // Returns a 'codecs' string that has all the video and audio codecs joined with
// comma. // comma.
std::string GetCodecs(const MediaInfo& media_info); std::string GetCodecs(const MediaInfo& media_info);
// Returns a codec string without variants. For example, "mp4a" instead of
// "mp4a.40.2". May return a format for text streams.
std::string GetBaseCodec(const MediaInfo& media_info);
// Returns a key made from the characteristics that separate AdaptationSets.
std::string GetAdaptationSetKey(const MediaInfo& media_info);
std::string SecondsToXmlDuration(double seconds); std::string SecondsToXmlDuration(double seconds);
// Tries to get "duration" attribute from |node|. On success |duration| is set. // Tries to get "duration" attribute from |node|. On success |duration| is set.

View File

@ -44,15 +44,12 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
return false; return false;
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
// TODO(kqyang): Consider adding a new method MpdBuilder::AddRepresentation. // TODO(kqyang): Consider adding a new method MpdBuilder::AddRepresentation.
// Most of the codes here can be moved inside. // Most of the codes here can be moved inside.
std::string lang; std::string key = GetAdaptationSetKey(media_info);
if (media_info.has_audio_info()) { std::string lang = GetLanguage(media_info);
lang = media_info.audio_info().language(); AdaptationSet** adaptation_set = &adaptation_set_map_[key];
} else if (media_info.has_text_info()) {
lang = media_info.text_info().language();
}
AdaptationSet** adaptation_set = &adaptation_set_map_[content_type][lang];
if (*adaptation_set == NULL) if (*adaptation_set == NULL)
*adaptation_set = mpd_builder_->AddAdaptationSet(lang); *adaptation_set = mpd_builder_->AddAdaptationSet(lang);

View File

@ -74,9 +74,7 @@ class SimpleMpdNotifier : public MpdNotifier {
scoped_ptr<MpdBuilder> mpd_builder_; scoped_ptr<MpdBuilder> mpd_builder_;
base::Lock lock_; base::Lock lock_;
// [type][lang] = AdaptationSet typedef std::map<std::string, AdaptationSet*> AdaptationSetMap;
typedef std::map<ContentType, std::map<std::string, AdaptationSet*> >
AdaptationSetMap;
AdaptationSetMap adaptation_set_map_; AdaptationSetMap adaptation_set_map_;
typedef std::map<uint32_t, Representation*> RepresentationMap; typedef std::map<uint32_t, Representation*> RepresentationMap;

View File

@ -308,6 +308,101 @@ TEST_P(SimpleMpdNotifierTest, UpdateEncryption) {
container_id, "myuuid", std::vector<uint8_t>(), kBogusNewPsshVector)); container_id, "myuuid", std::vector<uint8_t>(), kBogusNewPsshVector));
} }
// Don't put different audio languages or codecs in the same AdaptationSet.
TEST_P(SimpleMpdNotifierTest, SplitAdaptationSetsByLanguageAndCodec) {
// MP4, English
const char kAudioContent1[] =
"audio_info {\n"
" codec: 'mp4a.40.2'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'eng'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_MP4\n"
"media_duration_seconds: 10.5\n";
// MP4, German
const char kAudioContent2[] =
"audio_info {\n"
" codec: 'mp4a.40.2'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'ger'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_MP4\n"
"media_duration_seconds: 10.5\n";
// WebM, German
const char kAudioContent3[] =
"audio_info {\n"
" codec: 'vorbis'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'ger'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_WEBM\n"
"media_duration_seconds: 10.5\n";
// WebM, German again
const char kAudioContent4[] =
"audio_info {\n"
" codec: 'vorbis'\n"
" sampling_frequency: 44100\n"
" time_scale: 1200\n"
" num_channels: 2\n"
" language: 'ger'\n"
"}\n"
"reference_time_scale: 50\n"
"container_type: CONTAINER_WEBM\n"
"media_duration_seconds: 10.5\n";
SimpleMpdNotifier notifier(kOnDemandProfile, empty_mpd_option_,
empty_base_urls_, output_path_);
scoped_ptr<MockMpdBuilder> mock_mpd_builder(StaticMpdBuilderMock());
scoped_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
scoped_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
scoped_ptr<MockAdaptationSet> adaptation_set3(new MockAdaptationSet(3));
scoped_ptr<MockRepresentation> representation1(new MockRepresentation(1));
scoped_ptr<MockRepresentation> representation2(new MockRepresentation(2));
scoped_ptr<MockRepresentation> representation3(new MockRepresentation(3));
scoped_ptr<MockRepresentation> representation4(new MockRepresentation(4));
// We expect three AdaptationSets.
EXPECT_CALL(*mock_mpd_builder, AddAdaptationSet(_))
.WillOnce(Return(adaptation_set1.get()))
.WillOnce(Return(adaptation_set2.get()))
.WillOnce(Return(adaptation_set3.get()));
// The first AdaptationSet should have Eng MP4, one Representation.
EXPECT_CALL(*adaptation_set1, AddRepresentation(_))
.WillOnce(Return(representation1.get()));
// The second AdaptationSet should have Ger MP4, one Representation.
EXPECT_CALL(*adaptation_set2, AddRepresentation(_))
.WillOnce(Return(representation2.get()));
// The third AdaptationSet should have Ger WebM, two Representations.
EXPECT_CALL(*adaptation_set3, AddRepresentation(_))
.WillOnce(Return(representation3.get()))
.WillOnce(Return(representation4.get()));
uint32_t unused_container_id;
SetMpdBuilder(&notifier, mock_mpd_builder.Pass());
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent1), &unused_container_id));
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent2), &unused_container_id));
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent3), &unused_container_id));
EXPECT_TRUE(notifier.NotifyNewContainer(
ConvertToMediaInfo(kAudioContent4), &unused_container_id));
}
INSTANTIATE_TEST_CASE_P(StaticAndDynamic, INSTANTIATE_TEST_CASE_P(StaticAndDynamic,
SimpleMpdNotifierTest, SimpleMpdNotifierTest,
::testing::Values(MpdBuilder::kStatic, ::testing::Values(MpdBuilder::kStatic,

View File

@ -1,20 +0,0 @@
bandwidth: 400
audio_info {
codec: "mp4a.40.2"
sampling_frequency: 44100
time_scale: 1200
num_channels: 2
language: "eng"
}
init_range {
begin: 0
end: 120
}
index_range {
begin: 121
end: 221
}
reference_time_scale: 50
container_type: 1
media_file_name: "test_output_file_name_audio_eng1.mp4"
media_duration_seconds: 10.5

View File

@ -1,20 +0,0 @@
bandwidth: 800
audio_info {
codec: "mp4a.40.2"
sampling_frequency: 44100
time_scale: 1200
num_channels: 2
language: "eng"
}
init_range {
begin: 0
end: 120
}
index_range {
begin: 121
end: 221
}
reference_time_scale: 50
container_type: 1
media_file_name: "test_output_file_name_audio_eng2.mp4"
media_duration_seconds: 10.5

View File

@ -1,20 +0,0 @@
bandwidth: 400
audio_info {
codec: "mp4a.40.2"
sampling_frequency: 44100
time_scale: 1200
num_channels: 2
language: "ger"
}
init_range {
begin: 0
end: 120
}
index_range {
begin: 121
end: 221
}
reference_time_scale: 50
container_type: 1
media_file_name: "test_output_file_name_audio_ger1.mp4"
media_duration_seconds: 10.5

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT10.5S">
<Period>
<AdaptationSet id="0" width="720" height="480" frameRate="10/1" contentType="video" par="3:2">
<Representation id="3" bandwidth="7620" codecs="avc1.010101" mimeType="video/mp4" sar="1:1">
<BaseURL>test_output_file_name1.mp4</BaseURL>
<SegmentBase indexRange="121-221" timescale="1000">
<Initialization range="0-120"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" lang="en" contentType="audio">
<Representation id="0" bandwidth="400" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>test_output_file_name_audio_eng1.mp4</BaseURL>
<SegmentBase indexRange="121-221" timescale="50">
<Initialization range="0-120"/>
</SegmentBase>
</Representation>
<Representation id="1" bandwidth="800" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>test_output_file_name_audio_eng2.mp4</BaseURL>
<SegmentBase indexRange="121-221" timescale="50">
<Initialization range="0-120"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="2" lang="de" contentType="audio">
<Representation id="2" bandwidth="400" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>test_output_file_name_audio_ger1.mp4</BaseURL>
<SegmentBase indexRange="121-221" timescale="50">
<Initialization range="0-120"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>

View File

@ -1,22 +0,0 @@
bandwidth: 7620
video_info {
codec: "avc1.010101"
width: 720
height: 480
time_scale: 10
frame_duration: 1
pixel_width: 1
pixel_height: 1
}
init_range {
begin: 0
end: 120
}
index_range {
begin: 121
end: 221
}
reference_time_scale: 1000
container_type: 1
media_file_name: "test_output_file_name1.mp4"
media_duration_seconds: 10.5

View File

@ -23,14 +23,6 @@ const char kFileNameVideoMediaInfo1[] = "video_media_info1.txt";
const char kFileNameVideoMediaInfo2[] = "video_media_info2.txt"; const char kFileNameVideoMediaInfo2[] = "video_media_info2.txt";
const char kFileNameAudioMediaInfo1[] = "audio_media_info1.txt"; const char kFileNameAudioMediaInfo1[] = "audio_media_info1.txt";
const char kFileNameEncytpedAudioMediaInfo[] = "encrypted_audio_media_info.txt"; const char kFileNameEncytpedAudioMediaInfo[] = "encrypted_audio_media_info.txt";
const char kFileNameLanguageAudioMediaInfo1[] =
"language_audio_media_info1.txt";
const char kFileNameLanguageAudioMediaInfo2[] =
"language_audio_media_info2.txt";
const char kFileNameLanguageAudioMediaInfo3[] =
"language_audio_media_info3.txt";
const char kFileNameLanguageVideoMediaInfo1[] =
"language_video_media_info1.txt";
// These are the expected output files. // These are the expected output files.
const char kFileNameExpectedMpdOutputVideo1[] = const char kFileNameExpectedMpdOutputVideo1[] =
@ -50,9 +42,6 @@ const char kFileNameExpectedMpdOutputEncryptedAudio[] =
const char kFileNameExpectedMpdOutputDynamicNormal[] = "dynamic_normal_mpd.txt"; const char kFileNameExpectedMpdOutputDynamicNormal[] = "dynamic_normal_mpd.txt";
const char kFileNameExpectedMpdOutputLanguageAudio[] =
"language_audio_media_info_expected_output.txt";
// Returns the path to test data with |file_name|. Use constants above to get // Returns the path to test data with |file_name|. Use constants above to get
// path to the test files. // path to the test files.
base::FilePath GetTestDataFilePath(const std::string& file_name); base::FilePath GetTestDataFilePath(const std::string& file_name);