Added support for multiple audio & video configurations in WVM parser.

BUG=24614172

Change-Id: I197a0ebdfa6df90abc27358762cae041e4f8fd45
This commit is contained in:
Thomas Inskip 2015-10-09 15:09:09 -07:00 committed by KongQun Yang
parent 9ba1c1ebfd
commit da235ab724
4 changed files with 163 additions and 66 deletions

View File

@ -20,6 +20,7 @@
'../../base/media_base.gyp:base', '../../base/media_base.gyp:base',
'../../filters/filters.gyp:filters', '../../filters/filters.gyp:filters',
'../../formats/mp2t/mp2t.gyp:mp2t', '../../formats/mp2t/mp2t.gyp:mp2t',
'../../formats/mp4/mp4.gyp:mp4',
'../mpeg/mpeg.gyp:mpeg', '../mpeg/mpeg.gyp:mpeg',
], ],
}, },

View File

@ -8,6 +8,7 @@
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#include "packager/base/stl_util.h"
#include "packager/base/strings/string_number_conversions.h" #include "packager/base/strings/string_number_conversions.h"
#include "packager/media/base/aes_encryptor.h" #include "packager/media/base/aes_encryptor.h"
#include "packager/media/base/audio_stream_info.h" #include "packager/media/base/audio_stream_info.h"
@ -17,6 +18,8 @@
#include "packager/media/base/video_stream_info.h" #include "packager/media/base/video_stream_info.h"
#include "packager/media/filters/h264_parser.h" #include "packager/media/filters/h264_parser.h"
#include "packager/media/formats/mp2t/adts_header.h" #include "packager/media/formats/mp2t/adts_header.h"
#include "packager/media/formats/mp4/aac_audio_specific_config.h"
#include "packager/media/formats/mp4/es_descriptor.h"
#define HAS_HEADER_EXTENSION(x) ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) \ #define HAS_HEADER_EXTENSION(x) ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) \
&& (x != 0xF0) && (x != 0xF2) && (x != 0xF8) \ && (x != 0xF0) && (x != 0xF2) && (x != 0xF8) \
@ -543,22 +546,22 @@ bool WvmMediaParser::ParseIndexEntry() {
return false; return false;
} }
const uint8_t* read_ptr_index = &index_data_[0]; const uint8_t* read_ptr = vector_as_array(&index_data_);
if (ntohlFromBuffer(read_ptr_index) != kIndexMagic) { if (ntohlFromBuffer(read_ptr) != kIndexMagic) {
index_data_.clear(); index_data_.clear();
return false; return false;
} }
read_ptr_index += 4; read_ptr += 4;
uint32_t version = ntohlFromBuffer(read_ptr_index); uint32_t version = ntohlFromBuffer(read_ptr);
read_ptr_index += 4; read_ptr += 4;
if (version == kVersion4) { if (version == kVersion4) {
index_size = kIndexVersion4HeaderSize + ntohlFromBuffer(read_ptr_index); index_size = kIndexVersion4HeaderSize + ntohlFromBuffer(read_ptr);
if (index_data_.size() < index_size) { if (index_data_.size() < index_size) {
// We do not yet have the full index. Keep accumulating index data. // We do not yet have the full index. Keep accumulating index data.
return true; return true;
} }
read_ptr_index += sizeof(uint32_t); read_ptr += sizeof(uint32_t);
// Index metadata // Index metadata
uint32_t index_metadata_max_size = index_size - kIndexVersion4HeaderSize; uint32_t index_metadata_max_size = index_size - kIndexVersion4HeaderSize;
@ -581,90 +584,89 @@ bool WvmMediaParser::ParseIndexEntry() {
int video_pes_stream_id = 0; int video_pes_stream_id = 0;
bool has_video = false; bool has_video = false;
bool has_audio = false; bool has_audio = false;
std::vector<uint8_t> decoder_config_record; std::vector<uint8_t> audio_codec_config;
std::string video_codec_string; std::vector<uint8_t> video_codec_config;
std::string audio_codec_string; uint8_t num_index_entries = *read_ptr;
uint8_t num_index_entries = *read_ptr_index; ++read_ptr;
++read_ptr_index;
--index_metadata_max_size; --index_metadata_max_size;
for (uint8_t idx = 0; idx < num_index_entries; ++idx) { for (uint8_t idx = 0; idx < num_index_entries; ++idx) {
if (index_metadata_max_size < (2 * sizeof(uint8_t)) + sizeof(uint32_t)) { if (index_metadata_max_size < (2 * sizeof(uint8_t)) + sizeof(uint32_t)) {
return false; return false;
} }
uint8_t tag = *read_ptr_index; uint8_t tag = *read_ptr;
++read_ptr_index; ++read_ptr;
uint8_t type = *read_ptr_index; uint8_t type = *read_ptr;
++read_ptr_index; ++read_ptr;
uint32_t length = ntohlFromBuffer(read_ptr_index); uint32_t length = ntohlFromBuffer(read_ptr);
read_ptr_index += sizeof(uint32_t); read_ptr += sizeof(uint32_t);
index_metadata_max_size -= (2 * sizeof(uint8_t)) + sizeof(uint32_t); index_metadata_max_size -= (2 * sizeof(uint8_t)) + sizeof(uint32_t);
if (index_metadata_max_size < length) { if (index_metadata_max_size < length) {
return false; return false;
} }
int64_t value = 0; int64_t value = 0;
Tag tagtype = Unset; Tag tagtype = Unset;
std::vector<uint8_t> binary_data(length); std::vector<uint8_t> binary_data;
switch (Type(type)) { switch (Type(type)) {
case Type_uint8: case Type_uint8:
if (length == sizeof(uint8_t)) { if (length == sizeof(uint8_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_int8: case Type_int8:
if (length == sizeof(int8_t)) { if (length == sizeof(int8_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_uint16: case Type_uint16:
if (length == sizeof(uint16_t)) { if (length == sizeof(uint16_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_int16: case Type_int16:
if (length == sizeof(int16_t)) { if (length == sizeof(int16_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_uint32: case Type_uint32:
if (length == sizeof(uint32_t)) { if (length == sizeof(uint32_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_int32: case Type_int32:
if (length == sizeof(int32_t)) { if (length == sizeof(int32_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_uint64: case Type_uint64:
if (length == sizeof(uint64_t)) { if (length == sizeof(uint64_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_int64: case Type_int64:
if (length == sizeof(int64_t)) { if (length == sizeof(int64_t)) {
tagtype = GetTag(tag, length, read_ptr_index, &value); tagtype = GetTag(tag, length, read_ptr, &value);
} else { } else {
return false; return false;
} }
break; break;
case Type_string: case Type_string:
case Type_BinaryData: case Type_BinaryData:
memcpy(&binary_data[0], read_ptr_index, length); binary_data.assign(read_ptr, read_ptr + length);
tagtype = Tag(tag); tagtype = Tag(tag);
break; break;
default: default:
@ -705,24 +707,41 @@ bool WvmMediaParser::ParseIndexEntry() {
case VideoPixelHeight: case VideoPixelHeight:
pixel_height = static_cast<uint32_t>(value); pixel_height = static_cast<uint32_t>(value);
break; break;
case Audio_EsDescriptor: {
mp4::ESDescriptor descriptor;
if (!descriptor.Parse(binary_data)) {
LOG(ERROR) <<
"Could not extract AudioSpecificConfig from ES_Descriptor";
return false;
}
audio_codec_config = descriptor.decoder_specific_info();
break;
}
case Audio_EC3SpecificData:
case Audio_DtsSpecificData:
case Audio_AC3SpecificData:
LOG(ERROR) << "Audio type not supported.";
return false;
case AVCDecoderConfigurationRecord:
video_codec_config = binary_data;
break;
default: default:
break; break;
} }
read_ptr_index += length; read_ptr += length;
index_metadata_max_size -= length; index_metadata_max_size -= length;
} }
// End Index metadata // End Index metadata
index_size = read_ptr_index - &index_data_[0]; index_size = read_ptr - vector_as_array(&index_data_);
// Extra data for both audio and video streams not set here, but in
// Output().
if (has_video) { if (has_video) {
VideoCodec video_codec = kCodecH264; VideoCodec video_codec = kCodecH264;
stream_infos_.push_back(new VideoStreamInfo( stream_infos_.push_back(new VideoStreamInfo(
stream_id_count_, time_scale, track_duration, video_codec, stream_id_count_, time_scale, track_duration, video_codec,
video_codec_string, std::string(), video_width, video_height, std::string(), std::string(), video_width, video_height,
pixel_width, pixel_height, trick_play_rate, nalu_length_size, NULL, 0, pixel_width, pixel_height, trick_play_rate, nalu_length_size,
vector_as_array(&video_codec_config), video_codec_config.size(),
true)); true));
program_demux_stream_map_[base::UintToString(index_program_id_) + ":" + program_demux_stream_map_[base::UintToString(index_program_id_) + ":" +
base::UintToString(video_pes_stream_id ? base::UintToString(video_pes_stream_id ?
@ -734,8 +753,9 @@ bool WvmMediaParser::ParseIndexEntry() {
AudioCodec audio_codec = kCodecAAC; AudioCodec audio_codec = kCodecAAC;
stream_infos_.push_back(new AudioStreamInfo( stream_infos_.push_back(new AudioStreamInfo(
stream_id_count_, time_scale, track_duration, audio_codec, stream_id_count_, time_scale, track_duration, audio_codec,
audio_codec_string, std::string(), kAacSampleSizeBits, num_channels, std::string(), std::string(), kAacSampleSizeBits, num_channels,
sampling_frequency, NULL, 0, true)); sampling_frequency, vector_as_array(&audio_codec_config),
audio_codec_config.size(), true));
program_demux_stream_map_[base::UintToString(index_program_id_) + ":" + program_demux_stream_map_[base::UintToString(index_program_id_) + ":" +
base::UintToString(audio_pes_stream_id ? base::UintToString(audio_pes_stream_id ?
audio_pes_stream_id : audio_pes_stream_id :
@ -788,14 +808,16 @@ void WvmMediaParser::StartMediaSampleDemux() {
bool WvmMediaParser::Output(bool output_encrypted_sample) { bool WvmMediaParser::Output(bool output_encrypted_sample) {
if (output_encrypted_sample) { if (output_encrypted_sample) {
media_sample_->set_data(&sample_data_[0], sample_data_.size()); media_sample_->set_data(vector_as_array(&sample_data_),
sample_data_.size());
media_sample_->set_is_encrypted(true); media_sample_->set_is_encrypted(true);
} else { } else {
if ((prev_pes_stream_id_ & kPesStreamIdVideoMask) == kPesStreamIdVideo) { if ((prev_pes_stream_id_ & kPesStreamIdVideoMask) == kPesStreamIdVideo) {
// Set data on the video stream from the NalUnitStream. // Convert video stream to unit stream and get config.
std::vector<uint8_t> nal_unit_stream; std::vector<uint8_t> nal_unit_stream;
if (!byte_to_unit_stream_converter_.ConvertByteStreamToNalUnitStream( if (!byte_to_unit_stream_converter_.ConvertByteStreamToNalUnitStream(
&sample_data_[0], sample_data_.size(), &nal_unit_stream)) { vector_as_array(&sample_data_), sample_data_.size(),
&nal_unit_stream)) {
LOG(ERROR) << "Could not convert h.264 byte stream sample"; LOG(ERROR) << "Could not convert h.264 byte stream sample";
return false; return false;
} }
@ -808,11 +830,21 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) {
&decoder_config_record); &decoder_config_record);
for (uint32_t i = 0; i < stream_infos_.size(); i++) { for (uint32_t i = 0; i < stream_infos_.size(); i++) {
if (stream_infos_[i]->stream_type() == media::kStreamVideo && if (stream_infos_[i]->stream_type() == media::kStreamVideo &&
stream_infos_[i]->extra_data().empty()) { stream_infos_[i]->codec_string().empty()) {
stream_infos_[i]->set_extra_data(decoder_config_record); const std::vector<uint8_t>* stream_config;
if (stream_infos_[i]->extra_data().empty()) {
// Decoder config record not available for stream. Use the one
// computed from the first video stream.
stream_infos_[i]->set_extra_data(decoder_config_record);
stream_config = &decoder_config_record;
} else {
// Use stream-specific config record.
stream_config = &stream_infos_[i]->extra_data();
}
DCHECK(stream_config);
stream_infos_[i]->set_codec_string(VideoStreamInfo::GetCodecString( stream_infos_[i]->set_codec_string(VideoStreamInfo::GetCodecString(
kCodecH264, decoder_config_record[1], decoder_config_record[2], kCodecH264, (*stream_config)[1], (*stream_config)[2],
decoder_config_record[3])); (*stream_config)[3]));
VideoStreamInfo* video_stream_info = VideoStreamInfo* video_stream_info =
reinterpret_cast<VideoStreamInfo*>(stream_infos_[i].get()); reinterpret_cast<VideoStreamInfo*>(stream_infos_[i].get());
@ -821,7 +853,7 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) {
uint32_t pixel_width = 0; uint32_t pixel_width = 0;
uint32_t pixel_height = 0; uint32_t pixel_height = 0;
if (!ExtractResolutionFromDecoderConfig( if (!ExtractResolutionFromDecoderConfig(
&decoder_config_record[0], decoder_config_record.size(), vector_as_array(stream_config), stream_config->size(),
&coded_width, &coded_height, &pixel_width, &pixel_height)) { &coded_width, &coded_height, &pixel_width, &pixel_height)) {
LOG(ERROR) << "Failed to parse AVCDecoderConfigurationRecord."; LOG(ERROR) << "Failed to parse AVCDecoderConfigurationRecord.";
return false; return false;
@ -857,14 +889,12 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) {
} }
} else if ((prev_pes_stream_id_ & kPesStreamIdAudioMask) == } else if ((prev_pes_stream_id_ & kPesStreamIdAudioMask) ==
kPesStreamIdAudio) { kPesStreamIdAudio) {
// Set data on the audio stream from AdtsHeader. // Set data on the audio stream.
int frame_size = media::mp2t::AdtsHeader::GetAdtsFrameSize( int frame_size = media::mp2t::AdtsHeader::GetAdtsFrameSize(
&sample_data_[0], kAdtsHeaderMinSize); vector_as_array(&sample_data_), kAdtsHeaderMinSize);
media::mp2t::AdtsHeader adts_header; media::mp2t::AdtsHeader adts_header;
const uint8_t* frame_ptr = &sample_data_[0]; const uint8_t* frame_ptr = vector_as_array(&sample_data_);
std::vector<uint8_t> extra_data; if (!adts_header.Parse(frame_ptr, frame_size)) {
if (!adts_header.Parse(frame_ptr, frame_size) ||
!adts_header.GetAudioSpecificConfig(&extra_data)) {
LOG(ERROR) << "Could not parse ADTS header"; LOG(ERROR) << "Could not parse ADTS header";
return false; return false;
} }
@ -875,18 +905,36 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) {
if (!is_initialized_) { if (!is_initialized_) {
for (uint32_t i = 0; i < stream_infos_.size(); i++) { for (uint32_t i = 0; i < stream_infos_.size(); i++) {
if (stream_infos_[i]->stream_type() == media::kStreamAudio && if (stream_infos_[i]->stream_type() == media::kStreamAudio &&
stream_infos_[i]->extra_data().empty()) { stream_infos_[i]->codec_string().empty()) {
// Set AudioStreamInfo fields using information from the ADTS
// header.
AudioStreamInfo* audio_stream_info = AudioStreamInfo* audio_stream_info =
reinterpret_cast<AudioStreamInfo*>( reinterpret_cast<AudioStreamInfo*>(stream_infos_[i].get());
stream_infos_[i].get()); if (audio_stream_info->extra_data().empty()) {
audio_stream_info->set_sampling_frequency( // Set AudioStreamInfo fields using information from the ADTS
adts_header.GetSamplingFrequency()); // header.
audio_stream_info->set_extra_data(extra_data); audio_stream_info->set_sampling_frequency(
audio_stream_info->set_codec_string( adts_header.GetSamplingFrequency());
AudioStreamInfo::GetCodecString( std::vector<uint8_t> audio_specific_config;
kCodecAAC, adts_header.GetObjectType())); if (!adts_header.GetAudioSpecificConfig(&audio_specific_config)) {
LOG(ERROR) << "Could not compute AACaudiospecificconfig";
return false;
}
audio_stream_info->set_extra_data(audio_specific_config);
audio_stream_info->set_codec_string(
AudioStreamInfo::GetCodecString(
kCodecAAC, adts_header.GetObjectType()));
} else {
// Set AudioStreamInfo fields using information from the
// AACAudioSpecificConfig record.
mp4::AACAudioSpecificConfig aac_config;
if (!aac_config.Parse(stream_infos_[i]->extra_data())) {
LOG(ERROR) << "Could not parse AACAudioSpecificconfig";
return false;
}
audio_stream_info->set_sampling_frequency(aac_config.frequency());
audio_stream_info->set_codec_string(
AudioStreamInfo::GetCodecString(
kCodecAAC, aac_config.audio_object_type()));
}
} }
} }
} }
@ -894,15 +942,15 @@ bool WvmMediaParser::Output(bool output_encrypted_sample) {
} }
if (!is_initialized_) { if (!is_initialized_) {
bool is_extra_data_in_stream_infos = true; bool all_streams_have_config = true;
// Check if all collected stream infos have extra_data set. // Check if all collected stream infos have extra_data set.
for (uint32_t i = 0; i < stream_infos_.size(); i++) { for (uint32_t i = 0; i < stream_infos_.size(); i++) {
if (stream_infos_[i]->extra_data().empty()) { if (stream_infos_[i]->codec_string().empty()) {
is_extra_data_in_stream_infos = false; all_streams_have_config = false;
break; break;
} }
} }
if (is_extra_data_in_stream_infos) { if (all_streams_have_config) {
init_cb_.Run(stream_infos_); init_cb_.Run(stream_infos_);
is_initialized_ = true; is_initialized_ = true;
} }
@ -1074,7 +1122,7 @@ bool WvmMediaParser::ProcessEcm() {
kEcmPaddingSizeBytes; // flags + contentKey + padding. kEcmPaddingSizeBytes; // flags + contentKey + padding.
std::vector<uint8_t> content_key_buffer(content_key_buffer_size); std::vector<uint8_t> content_key_buffer(content_key_buffer_size);
asset_decryptor.Decrypt( asset_decryptor.Decrypt(
ecm_data, content_key_buffer_size, &content_key_buffer[0]); ecm_data, content_key_buffer_size, vector_as_array(&content_key_buffer));
std::vector<uint8_t> decrypted_content_key_vec( std::vector<uint8_t> decrypted_content_key_vec(
content_key_buffer.begin() + 4, content_key_buffer.begin() + 4,

View File

@ -12,6 +12,7 @@
#include "packager/base/bind_helpers.h" #include "packager/base/bind_helpers.h"
#include "packager/base/logging.h" #include "packager/base/logging.h"
#include "packager/base/memory/ref_counted.h" #include "packager/base/memory/ref_counted.h"
#include "packager/media/base/audio_stream_info.h"
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
#include "packager/media/base/request_signer.h" #include "packager/media/base/request_signer.h"
#include "packager/media/base/stream_info.h" #include "packager/media/base/stream_info.h"
@ -37,6 +38,7 @@ const uint8_t k64ByteAssetKey[] =
"\x06\x81\x7f\x48\x6b\xf2\x7f\x3e\xc7\x39\xa8\x3f\x12\x0a\xd2\xfc" "\x06\x81\x7f\x48\x6b\xf2\x7f\x3e\xc7\x39\xa8\x3f\x12\x0a\xd2\xfc"
"\x06\x81\x7f\x48\x6b\xf2\x7f\x3e\xc7\x39\xa8\x3f\x12\x0a\xd2\xfc"; "\x06\x81\x7f\x48\x6b\xf2\x7f\x3e\xc7\x39\xa8\x3f\x12\x0a\xd2\xfc";
const size_t kInitDataSize = 0x4000; const size_t kInitDataSize = 0x4000;
const char kMultiConfigWvmFile[] = "bear-multi-configs.wvm";
} // namespace } // namespace
using ::testing::_; using ::testing::_;
@ -209,6 +211,52 @@ TEST_F(WvmMediaParserTest, ParseWvmWith64ByteAssetKey) {
EXPECT_EQ(kExpectedAudioFrameCount, audio_frame_count_); EXPECT_EQ(kExpectedAudioFrameCount, audio_frame_count_);
} }
TEST_F(WvmMediaParserTest, ParseMultiConfigWvm) {
EXPECT_CALL(*key_source_, FetchKeys(_)).WillOnce(Return(Status::OK));
EXPECT_CALL(*key_source_, GetKey(_, _))
.WillOnce(DoAll(SetArgPointee<1>(encryption_key_), Return(Status::OK)));
Parse(kMultiConfigWvmFile);
EXPECT_EQ(6u, stream_map_.size());
ASSERT_EQ(kStreamVideo, stream_map_[0]->stream_type());
VideoStreamInfo* video_info = reinterpret_cast<VideoStreamInfo*>(
stream_map_[0].get());
EXPECT_EQ("avc1.64000d", video_info->codec_string());
EXPECT_EQ(320u, video_info->width());
EXPECT_EQ(180u, video_info->height());
ASSERT_EQ(kStreamAudio, stream_map_[1]->stream_type());
AudioStreamInfo* audio_info = reinterpret_cast<AudioStreamInfo*>(
stream_map_[1].get());
EXPECT_EQ("mp4a.40.2", audio_info->codec_string());
EXPECT_EQ(2u, audio_info->num_channels());
EXPECT_EQ(44100u, audio_info->sampling_frequency());
ASSERT_EQ(kStreamVideo, stream_map_[2]->stream_type());
video_info = reinterpret_cast<VideoStreamInfo*>(stream_map_[2].get());
EXPECT_EQ("avc1.64001e", video_info->codec_string());
EXPECT_EQ(640u, video_info->width());
EXPECT_EQ(360u, video_info->height());
ASSERT_EQ(kStreamAudio, stream_map_[3]->stream_type());
audio_info = reinterpret_cast<AudioStreamInfo*>(stream_map_[3].get());
EXPECT_EQ("mp4a.40.2", audio_info->codec_string());
EXPECT_EQ(2u, audio_info->num_channels());
EXPECT_EQ(44100u, audio_info->sampling_frequency());
ASSERT_EQ(kStreamVideo, stream_map_[4]->stream_type());
video_info = reinterpret_cast<VideoStreamInfo*>(stream_map_[4].get());
EXPECT_EQ("avc1.64001f", video_info->codec_string());
EXPECT_EQ(1280u, video_info->width());
EXPECT_EQ(720u, video_info->height());
ASSERT_EQ(kStreamAudio, stream_map_[5]->stream_type());
audio_info = reinterpret_cast<AudioStreamInfo*>(stream_map_[5].get());
EXPECT_EQ("mp4a.40.2", audio_info->codec_string());
EXPECT_EQ(2u, audio_info->num_channels());
EXPECT_EQ(48000u, audio_info->sampling_frequency());
}
} // namespace wvm } // namespace wvm
} // namespace media } // namespace media
} // namespace edash_packager } // namespace edash_packager

Binary file not shown.