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:
parent
b6718a37c5
commit
f3e19fc002
|
@ -74,15 +74,8 @@ bool DashIopMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
|||
return false;
|
||||
|
||||
base::AutoLock auto_lock(lock_);
|
||||
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();
|
||||
}
|
||||
|
||||
AdaptationSet* adaptation_set =
|
||||
GetAdaptationSetForMediaInfo(media_info, content_type, lang);
|
||||
const std::string key = GetAdaptationSetKey(media_info);
|
||||
AdaptationSet* adaptation_set = GetAdaptationSetForMediaInfo(key, media_info);
|
||||
DCHECK(adaptation_set);
|
||||
if (media_info.has_text_info()) {
|
||||
// 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;
|
||||
|
||||
SetGroupId(content_type, lang, adaptation_set);
|
||||
SetGroupId(key, adaptation_set);
|
||||
|
||||
*container_id = representation->id();
|
||||
DCHECK(!ContainsKey(representation_map_, representation->id()));
|
||||
|
@ -169,13 +162,11 @@ bool DashIopMpdNotifier::Flush() {
|
|||
}
|
||||
|
||||
AdaptationSet* DashIopMpdNotifier::GetAdaptationSetForMediaInfo(
|
||||
const MediaInfo& media_info,
|
||||
ContentType content_type,
|
||||
const std::string& language) {
|
||||
std::list<AdaptationSet*>& adaptation_sets =
|
||||
adaptation_set_list_map_[content_type][language];
|
||||
const std::string& key,
|
||||
const MediaInfo& media_info) {
|
||||
std::list<AdaptationSet*>& adaptation_sets = adaptation_set_list_map_[key];
|
||||
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();
|
||||
|
||||
|
@ -204,13 +195,12 @@ AdaptationSet* DashIopMpdNotifier::GetAdaptationSetForMediaInfo(
|
|||
|
||||
// None of the adaptation sets match with the new content protection.
|
||||
// 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
|
||||
// same UUIDs then those should be groupable.
|
||||
void DashIopMpdNotifier::SetGroupId(ContentType type,
|
||||
const std::string& language,
|
||||
void DashIopMpdNotifier::SetGroupId(const std::string& key,
|
||||
AdaptationSet* adaptation_set) {
|
||||
if (adaptation_set->Group() >= 0) // @group already assigned.
|
||||
return;
|
||||
|
@ -230,7 +220,7 @@ void DashIopMpdNotifier::SetGroupId(ContentType type,
|
|||
GetUUIDs(protected_content_it->second);
|
||||
|
||||
std::list<AdaptationSet*>& same_type_adapatation_sets =
|
||||
adaptation_set_list_map_[type][language];
|
||||
adaptation_set_list_map_[key];
|
||||
DCHECK(!same_type_adapatation_sets.empty())
|
||||
<< "same_type_adapatation_sets should not be null, it should at least "
|
||||
"contain adaptation_set";
|
||||
|
@ -270,8 +260,8 @@ void DashIopMpdNotifier::SetGroupId(ContentType type,
|
|||
|
||||
AdaptationSet* DashIopMpdNotifier::NewAdaptationSet(
|
||||
const MediaInfo& media_info,
|
||||
const std::string& language,
|
||||
std::list<AdaptationSet*>* adaptation_sets) {
|
||||
std::string language = GetLanguage(media_info);
|
||||
AdaptationSet* new_adaptation_set = mpd_builder_->AddAdaptationSet(language);
|
||||
if (media_info.has_protected_content()) {
|
||||
DCHECK(!ContainsKey(protected_content_map_, new_adaptation_set->id()));
|
||||
|
|
|
@ -70,22 +70,17 @@ class DashIopMpdNotifier : public MpdNotifier {
|
|||
// This does not necessarily return a new AdaptationSet. If
|
||||
// media_info.protected_content completely matches with an existing
|
||||
// AdaptationSet, then it will return the pointer.
|
||||
AdaptationSet* GetAdaptationSetForMediaInfo(const MediaInfo& media_info,
|
||||
ContentType type,
|
||||
const std::string& language);
|
||||
AdaptationSet* GetAdaptationSetForMediaInfo(const std::string& key,
|
||||
const MediaInfo& media_info);
|
||||
|
||||
// Sets a group id for |adaptation_set| if applicable.
|
||||
// If a group ID is already assigned, then this returns immediately.
|
||||
// |type| and |language| are the type and language of |adaptation_set|.
|
||||
void SetGroupId(ContentType type,
|
||||
const std::string& language,
|
||||
AdaptationSet* adaptation_set);
|
||||
void SetGroupId(const std::string& key, AdaptationSet* adaptation_set);
|
||||
|
||||
// Helper function to get a new AdaptationSet; registers the values
|
||||
// to the fields (maps) of the instance.
|
||||
// If the media is encrypted, registers data to protected_content_map_.
|
||||
AdaptationSet* NewAdaptationSet(const MediaInfo& media_info,
|
||||
const std::string& language,
|
||||
std::list<AdaptationSet*>* adaptation_sets);
|
||||
|
||||
// Testing only method. Returns a pointer to MpdBuilder.
|
||||
|
@ -98,10 +93,7 @@ class DashIopMpdNotifier : public MpdNotifier {
|
|||
mpd_builder_ = mpd_builder.Pass();
|
||||
}
|
||||
|
||||
// [type][lang] = list<AdaptationSet>
|
||||
// Note: lang can be empty, e.g. for video.
|
||||
std::map<ContentType, std::map<std::string, std::list<AdaptationSet*> > >
|
||||
adaptation_set_list_map_;
|
||||
std::map<std::string, std::list<AdaptationSet*>> adaptation_set_list_map_;
|
||||
RepresentationMap representation_map_;
|
||||
|
||||
// Used to check whether a Representation should be added to an AdaptationSet.
|
||||
|
|
|
@ -776,6 +776,102 @@ TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
|||
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(¬ifier, 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,
|
||||
DashIopMpdNotifierTest,
|
||||
::testing::Values(MpdBuilder::kStatic,
|
||||
|
|
|
@ -57,6 +57,16 @@ void RemoveDuplicateAttributes(
|
|||
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) {
|
||||
CHECK(OnlyOneTrue(media_info.has_video_info(), media_info.has_audio_info(),
|
||||
media_info.has_text_info()));
|
||||
|
@ -86,6 +96,47 @@ std::string GetCodecs(const MediaInfo& media_info) {
|
|||
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) {
|
||||
return "PT" + base::DoubleToString(seconds) + "S";
|
||||
}
|
||||
|
|
|
@ -40,10 +40,20 @@ bool HasLiveOnlyFields(const MediaInfo& media_info);
|
|||
void RemoveDuplicateAttributes(
|
||||
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
|
||||
// comma.
|
||||
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);
|
||||
|
||||
// Tries to get "duration" attribute from |node|. On success |duration| is set.
|
||||
|
|
|
@ -44,15 +44,12 @@ bool SimpleMpdNotifier::NotifyNewContainer(const MediaInfo& media_info,
|
|||
return false;
|
||||
|
||||
base::AutoLock auto_lock(lock_);
|
||||
|
||||
// TODO(kqyang): Consider adding a new method MpdBuilder::AddRepresentation.
|
||||
// Most of the codes here can be moved inside.
|
||||
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();
|
||||
}
|
||||
AdaptationSet** adaptation_set = &adaptation_set_map_[content_type][lang];
|
||||
std::string key = GetAdaptationSetKey(media_info);
|
||||
std::string lang = GetLanguage(media_info);
|
||||
AdaptationSet** adaptation_set = &adaptation_set_map_[key];
|
||||
if (*adaptation_set == NULL)
|
||||
*adaptation_set = mpd_builder_->AddAdaptationSet(lang);
|
||||
|
||||
|
|
|
@ -74,9 +74,7 @@ class SimpleMpdNotifier : public MpdNotifier {
|
|||
scoped_ptr<MpdBuilder> mpd_builder_;
|
||||
base::Lock lock_;
|
||||
|
||||
// [type][lang] = AdaptationSet
|
||||
typedef std::map<ContentType, std::map<std::string, AdaptationSet*> >
|
||||
AdaptationSetMap;
|
||||
typedef std::map<std::string, AdaptationSet*> AdaptationSetMap;
|
||||
AdaptationSetMap adaptation_set_map_;
|
||||
|
||||
typedef std::map<uint32_t, Representation*> RepresentationMap;
|
||||
|
|
|
@ -308,6 +308,101 @@ TEST_P(SimpleMpdNotifierTest, UpdateEncryption) {
|
|||
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(¬ifier, 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,
|
||||
SimpleMpdNotifierTest,
|
||||
::testing::Values(MpdBuilder::kStatic,
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -23,14 +23,6 @@ const char kFileNameVideoMediaInfo1[] = "video_media_info1.txt";
|
|||
const char kFileNameVideoMediaInfo2[] = "video_media_info2.txt";
|
||||
const char kFileNameAudioMediaInfo1[] = "audio_media_info1.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.
|
||||
const char kFileNameExpectedMpdOutputVideo1[] =
|
||||
|
@ -50,9 +42,6 @@ const char kFileNameExpectedMpdOutputEncryptedAudio[] =
|
|||
|
||||
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
|
||||
// path to the test files.
|
||||
base::FilePath GetTestDataFilePath(const std::string& file_name);
|
||||
|
|
Loading…
Reference in New Issue