diff --git a/packager/app/test/testdata/bear-640x360-v-cenc-golden.mp4 b/packager/app/test/testdata/bear-640x360-v-cenc-golden.mp4 index 4d892d7d49..2ef624da3c 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-cenc-golden.mp4 and b/packager/app/test/testdata/bear-640x360-v-cenc-golden.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-golden.mp4 b/packager/app/test/testdata/bear-640x360-v-golden.mp4 index eacdb0ffe8..0a4e7b3deb 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-golden.mp4 and b/packager/app/test/testdata/bear-640x360-v-golden.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 index 7a78de8935..2cbd292e84 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-v-live-cenc-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 index 9a25e2bd98..735a1f464c 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-v-live-cenc-rotation-golden-init.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 b/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 index 33bae3b6cd..80fadab713 100644 Binary files a/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 and b/packager/app/test/testdata/bear-640x360-v-live-golden-init.mp4 differ diff --git a/packager/media/base/demuxer.cc b/packager/media/base/demuxer.cc index 104bab3799..00a2ff7dff 100644 --- a/packager/media/base/demuxer.cc +++ b/packager/media/base/demuxer.cc @@ -17,6 +17,7 @@ #include "packager/media/file/file.h" #include "packager/media/formats/mp2t/mp2t_media_parser.h" #include "packager/media/formats/mp4/mp4_media_parser.h" +#include "packager/media/formats/webm/webm_media_parser.h" #include "packager/media/formats/wvm/wvm_media_parser.h" namespace { @@ -83,6 +84,9 @@ Status Demuxer::Initialize() { case CONTAINER_MPEG2PS: parser_.reset(new wvm::WvmMediaParser()); break; + case CONTAINER_WEBM: + parser_.reset(new WebMMediaParser()); + break; default: NOTIMPLEMENTED(); return Status(error::UNIMPLEMENTED, "Container not supported."); diff --git a/packager/media/base/video_stream_info.cc b/packager/media/base/video_stream_info.cc index 25c1ccde73..fad76d10c4 100644 --- a/packager/media/base/video_stream_info.cc +++ b/packager/media/base/video_stream_info.cc @@ -33,6 +33,8 @@ std::string VideoCodecToString(VideoCodec video_codec) { return "VP8"; case kCodecVP9: return "VP9"; + case kCodecVP10: + return "VP10"; default: NOTIMPLEMENTED() << "Unknown Video Codec: " << video_codec; return "UnknownVideoCodec"; diff --git a/packager/media/base/video_stream_info.h b/packager/media/base/video_stream_info.h index 948354d5ae..2992e65b59 100644 --- a/packager/media/base/video_stream_info.h +++ b/packager/media/base/video_stream_info.h @@ -21,6 +21,7 @@ enum VideoCodec { kCodecTheora, kCodecVP8, kCodecVP9, + kCodecVP10, kNumVideoCodec }; diff --git a/packager/media/filters/filters.gyp b/packager/media/filters/filters.gyp index 75127466dc..f836dec71f 100644 --- a/packager/media/filters/filters.gyp +++ b/packager/media/filters/filters.gyp @@ -21,6 +21,8 @@ 'h264_byte_to_unit_stream_converter.h', 'h264_parser.cc', 'h264_parser.h', + 'vp_codec_configuration.cc', + 'vp_codec_configuration.h', ], 'dependencies': [ '../../base/base.gyp:base', @@ -34,6 +36,7 @@ 'h264_bit_reader_unittest.cc', 'h264_byte_to_unit_stream_converter_unittest.cc', 'h264_parser_unittest.cc', + 'vp_codec_configuration_unittest.cc', ], 'dependencies': [ '../../media/base/media_base.gyp:base', diff --git a/packager/media/filters/vp_codec_configuration.cc b/packager/media/filters/vp_codec_configuration.cc new file mode 100644 index 0000000000..49595d31f4 --- /dev/null +++ b/packager/media/filters/vp_codec_configuration.cc @@ -0,0 +1,121 @@ +// Copyright 2015 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 or at +// https://developers.google.com/open-source/licenses/bsd + +#include "packager/media/filters/vp_codec_configuration.h" + +#include "packager/base/strings/string_number_conversions.h" +#include "packager/base/strings/string_util.h" +#include "packager/media/base/bit_reader.h" +#include "packager/media/base/buffer_writer.h" +#include "packager/base/strings/stringprintf.h" +#include "packager/media/formats/mp4/rcheck.h" + +namespace edash_packager { +namespace media { +namespace { + +std::string VPCodecAsString(VideoCodec codec) { + switch (codec) { + case kCodecVP8: + return "vp08"; + case kCodecVP9: + return "vp09"; + case kCodecVP10: + return "vp10"; + default: + LOG(WARNING) << "Unknown VP codec: " << codec; + return std::string(); + } +} + +} // namespace + +VPCodecConfiguration::VPCodecConfiguration() + : profile_(0), + level_(0), + bit_depth_(0), + color_space_(0), + chroma_subsampling_(0), + transfer_function_(0), + video_full_range_flag_(false) {} + +VPCodecConfiguration::VPCodecConfiguration( + uint8_t profile, + uint8_t level, + uint8_t bit_depth, + uint8_t color_space, + uint8_t chroma_subsampling, + uint8_t transfer_function, + bool video_full_range_flag, + const std::vector& codec_initialization_data) + : profile_(profile), + level_(level), + bit_depth_(bit_depth), + color_space_(color_space), + chroma_subsampling_(chroma_subsampling), + transfer_function_(transfer_function), + video_full_range_flag_(video_full_range_flag), + codec_initialization_data_(codec_initialization_data) {} + +VPCodecConfiguration::~VPCodecConfiguration(){}; + +bool VPCodecConfiguration::Parse(const std::vector& data) { + BitReader reader(vector_as_array(&data), data.size()); + RCHECK(reader.ReadBits(8, &profile_)); + RCHECK(reader.ReadBits(8, &level_)); + RCHECK(reader.ReadBits(4, &bit_depth_)); + RCHECK(reader.ReadBits(4, &color_space_)); + RCHECK(reader.ReadBits(4, &chroma_subsampling_)); + RCHECK(reader.ReadBits(3, &transfer_function_)); + RCHECK(reader.ReadBits(1, &video_full_range_flag_)); + uint16_t codec_initialization_data_size = 0; + RCHECK(reader.ReadBits(16, &codec_initialization_data_size)); + RCHECK(reader.bits_available() >= codec_initialization_data_size * 8); + const size_t kHeaderSize = 6u; // Size of bytes read so far. + codec_initialization_data_.assign( + data.begin() + kHeaderSize, + data.begin() + kHeaderSize + codec_initialization_data_size); + return true; +} + +void VPCodecConfiguration::Write(std::vector* data) const { + BufferWriter writer; + writer.AppendInt(profile_); + writer.AppendInt(level_); + uint8_t bit_depth_color_space = (bit_depth_ << 4) | color_space_; + writer.AppendInt(bit_depth_color_space); + uint8_t chroma = (chroma_subsampling_ << 4) | (transfer_function_ << 1) | + (video_full_range_flag_ ? 1 : 0); + writer.AppendInt(chroma); + uint16_t codec_initialization_data_size = codec_initialization_data_.size(); + writer.AppendInt(codec_initialization_data_size); + writer.AppendVector(codec_initialization_data_); + writer.SwapBuffer(data); +} + +std::string VPCodecConfiguration::GetCodecString(VideoCodec codec) const { + const std::string fields[] = { + base::IntToString(profile_), + base::IntToString(level_), + base::IntToString(bit_depth_), + base::IntToString(color_space_), + base::IntToString(chroma_subsampling_), + base::IntToString(transfer_function_), + (video_full_range_flag_ ? "01" : "00"), + }; + + std::string codec_string = VPCodecAsString(codec); + for (const std::string& field : fields) { + // Make sure every field is at least 2-chars wide. The space will be + // replaced with '0' afterwards. + base::StringAppendF(&codec_string, ".%2s", field.c_str()); + } + base::ReplaceChars(codec_string, " ", "0", &codec_string); + return codec_string; +} + +} // namespace media +} // namespace edash_packager diff --git a/packager/media/filters/vp_codec_configuration.h b/packager/media/filters/vp_codec_configuration.h new file mode 100644 index 0000000000..14481cdc24 --- /dev/null +++ b/packager/media/filters/vp_codec_configuration.h @@ -0,0 +1,69 @@ +// Copyright 2015 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 or at +// https://developers.google.com/open-source/licenses/bsd + +#ifndef MEDIA_FILTERS_VP_CODEC_CONFIGURATION_H_ +#define MEDIA_FILTERS_VP_CODEC_CONFIGURATION_H_ + +#include +#include +#include + +#include "packager/base/macros.h" +#include "packager/media/base/video_stream_info.h" + +namespace edash_packager { +namespace media { + +/// Class for parsing or writing VP codec configuration data. +class VPCodecConfiguration { + public: + VPCodecConfiguration(); + VPCodecConfiguration(uint8_t profile, + uint8_t level, + uint8_t bit_depth, + uint8_t color_space, + uint8_t chroma_subsampling, + uint8_t transfer_function, + bool video_full_range_flag, + const std::vector& codec_initialization_data); + ~VPCodecConfiguration(); + + /// Parses input to extract VP codec configuration data. + /// @return false if there is parsing errors. + bool Parse(const std::vector& data); + + /// @param data should not be null. + /// Writes VP codec configuration data to buffer. + void Write(std::vector* data) const; + + /// @return The codec string. + std::string GetCodecString(VideoCodec codec) const; + + uint8_t profile() const { return profile_; } + uint8_t level() const { return level_; } + uint8_t bit_depth() const { return bit_depth_; } + uint8_t color_space() const { return color_space_; } + uint8_t chroma_subsampling() const { return chroma_subsampling_; } + uint8_t transfer_function() const { return transfer_function_; } + bool video_full_range_flag() const { return video_full_range_flag_; } + + private: + uint8_t profile_; + uint8_t level_; + uint8_t bit_depth_; + uint8_t color_space_; + uint8_t chroma_subsampling_; + uint8_t transfer_function_; + bool video_full_range_flag_; + std::vector codec_initialization_data_; + + DISALLOW_COPY_AND_ASSIGN(VPCodecConfiguration); +}; + +} // namespace media +} // namespace edash_packager + +#endif // MEDIA_FILTERS_VP_CODEC_CONFIGURATION_H_ diff --git a/packager/media/filters/vp_codec_configuration_unittest.cc b/packager/media/filters/vp_codec_configuration_unittest.cc new file mode 100644 index 0000000000..6c8a29ed4e --- /dev/null +++ b/packager/media/filters/vp_codec_configuration_unittest.cc @@ -0,0 +1,63 @@ +// Copyright 2015 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 or at +// https://developers.google.com/open-source/licenses/bsd + +#include "packager/media/filters/vp_codec_configuration.h" + +#include + +namespace edash_packager { +namespace media { + +TEST(VPCodecConfigurationTest, Parse) { + const uint8_t kVpCodecConfigurationData[] = { + 0x01, 0x00, 0xA2, 0x14, 0x00, 0x01, 0x00, + }; + + VPCodecConfiguration vp_config; + ASSERT_TRUE(vp_config.Parse(std::vector( + kVpCodecConfigurationData, + kVpCodecConfigurationData + arraysize(kVpCodecConfigurationData)))); + + EXPECT_EQ(1u, vp_config.profile()); + EXPECT_EQ(0u, vp_config.level()); + EXPECT_EQ(10u, vp_config.bit_depth()); + EXPECT_EQ(2u, vp_config.color_space()); + EXPECT_EQ(1u, vp_config.chroma_subsampling()); + EXPECT_EQ(2u, vp_config.transfer_function()); + EXPECT_FALSE(vp_config.video_full_range_flag()); + + EXPECT_EQ("vp09.01.00.10.02.01.02.00", vp_config.GetCodecString(kCodecVP9)); +} + +TEST(VPCodecConfigurationTest, ParseWithInsufficientData) { + const uint8_t kVpCodecConfigurationData[] = { + 0x01, 0x00, 0xA2, 0x14, + }; + + VPCodecConfiguration vp_config; + ASSERT_FALSE(vp_config.Parse(std::vector( + kVpCodecConfigurationData, + kVpCodecConfigurationData + arraysize(kVpCodecConfigurationData)))); +} + +TEST(VPCodecConfigurationTest, Write) { + const uint8_t kExpectedVpCodecConfigurationData[] = { + 0x02, 0x01, 0x80, 0x21, 0x00, 0x00, + }; + VPCodecConfiguration vp_config(0x02, 0x01, 0x08, 0x00, 0x02, 0x00, true, + std::vector()); + std::vector data; + vp_config.Write(&data); + + EXPECT_EQ( + std::vector(kExpectedVpCodecConfigurationData, + kExpectedVpCodecConfigurationData + + arraysize(kExpectedVpCodecConfigurationData)), + data); +} + +} // namespace media +} // namespace edash_packager diff --git a/packager/media/formats/mp4/box_definitions.cc b/packager/media/formats/mp4/box_definitions.cc index c87ec81e41..ea3ba169dc 100644 --- a/packager/media/formats/mp4/box_definitions.cc +++ b/packager/media/formats/mp4/box_definitions.cc @@ -36,6 +36,8 @@ const uint16_t kVideoFrameCount = 1; const uint16_t kVideoDepth = 0x0018; const uint32_t kCompressorNameSize = 32u; +const char kAvcCompressorName[] = "\012AVC Coding"; +const char kVpcCompressorName[] = "\012VPC Coding"; // Utility functions to check if the 64bit integers can fit in 32bit integer. bool IsFitIn32Bits(uint64_t a) { @@ -933,12 +935,33 @@ FourCC VideoSampleEntry::BoxType() const { } bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) { + std::vector compressor_name; if (buffer->Reading()) { DCHECK(buffer->reader()); format = buffer->reader()->type(); } else { RCHECK(buffer->ReadWriteUInt32(&atom_size) && buffer->ReadWriteFourCC(&format)); + + const FourCC actual_format = GetActualFormat(); + switch (actual_format) { + case FOURCC_AVC1: + compressor_name.assign( + kAvcCompressorName, + kAvcCompressorName + arraysize(kAvcCompressorName)); + break; + case FOURCC_VP08: + case FOURCC_VP09: + case FOURCC_VP10: + compressor_name.assign( + kVpcCompressorName, + kVpcCompressorName + arraysize(kVpcCompressorName)); + break; + default: + LOG(ERROR) << FourCCToString(actual_format) << " is not supported."; + return false; + } + compressor_name.resize(kCompressorNameSize); } uint32_t video_resolution = kVideoResolution; @@ -954,7 +977,7 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) { buffer->ReadWriteUInt32(&video_resolution) && buffer->IgnoreBytes(4) && // reserved. buffer->ReadWriteUInt16(&video_frame_count) && - buffer->IgnoreBytes(32) && // comparessor_name. + buffer->ReadWriteVector(&compressor_name, kCompressorNameSize) && buffer->ReadWriteUInt16(&video_depth) && buffer->ReadWriteInt16(&predefined)); @@ -978,6 +1001,11 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) { case FOURCC_AVC1: codec_config_record.box_type = FOURCC_AVCC; break; + case FOURCC_VP08: + case FOURCC_VP09: + case FOURCC_VP10: + codec_config_record.box_type = FOURCC_VPCC; + break; default: LOG(ERROR) << FourCCToString(actual_format) << " is not supported."; return false; diff --git a/packager/media/formats/mp4/fourccs.h b/packager/media/formats/mp4/fourccs.h index f123b7370a..e472f870a9 100644 --- a/packager/media/formats/mp4/fourccs.h +++ b/packager/media/formats/mp4/fourccs.h @@ -92,6 +92,10 @@ enum FourCC { FOURCC_UUID = 0x75756964, FOURCC_VIDE = 0x76696465, FOURCC_VMHD = 0x766d6864, + FOURCC_VP08 = 0x76703038, + FOURCC_VP09 = 0x76703039, + FOURCC_VP10 = 0x76703130, + FOURCC_VPCC = 0x76706343, FOURCC_WIDE = 0x77696465, }; diff --git a/packager/media/formats/mp4/mp4_media_parser.cc b/packager/media/formats/mp4/mp4_media_parser.cc index 0598a83555..ecefe7da52 100644 --- a/packager/media/formats/mp4/mp4_media_parser.cc +++ b/packager/media/formats/mp4/mp4_media_parser.cc @@ -21,12 +21,16 @@ #include "packager/media/file/file.h" #include "packager/media/file/file_closer.h" #include "packager/media/filters/avc_decoder_configuration.h" +#include "packager/media/filters/vp_codec_configuration.h" #include "packager/media/formats/mp4/box_definitions.h" #include "packager/media/formats/mp4/box_reader.h" #include "packager/media/formats/mp4/es_descriptor.h" #include "packager/media/formats/mp4/rcheck.h" #include "packager/media/formats/mp4/track_run_iterator.h" +namespace edash_packager { +namespace media { +namespace mp4 { namespace { uint64_t Rescale(uint64_t time_in_old_scale, @@ -35,15 +39,25 @@ uint64_t Rescale(uint64_t time_in_old_scale, return (static_cast(time_in_old_scale) / old_scale) * new_scale; } +VideoCodec FourCCToCodec(FourCC fourcc) { + switch (fourcc) { + case FOURCC_AVC1: + return kCodecH264; + case FOURCC_VP08: + return kCodecVP8; + case FOURCC_VP09: + return kCodecVP9; + case FOURCC_VP10: + return kCodecVP10; + default: + return kUnknownVideoCodec; + } +} const char kWidevineKeySystemId[] = "edef8ba979d64acea3c827dcd51d21ed"; } // namespace -namespace edash_packager { -namespace media { -namespace mp4 { - MP4MediaParser::MP4MediaParser() : state_(kWaitingForInit), moof_head_(0), mdat_tail_(0) {} @@ -367,6 +381,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) { uint8_t nalu_length_size = 0; const FourCC actual_format = entry.GetActualFormat(); + const VideoCodec video_codec = FourCCToCodec(actual_format); switch (actual_format) { case FOURCC_AVC1: { AVCDecoderConfiguration avc_config; @@ -404,6 +419,17 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) { } break; } + case FOURCC_VP08: + case FOURCC_VP09: + case FOURCC_VP10: { + VPCodecConfiguration vp_config; + if (!vp_config.Parse(entry.codec_config_record.data)) { + LOG(ERROR) << "Failed to parse vpcc."; + return false; + } + codec_string = vp_config.GetCodecString(video_codec); + break; + } default: LOG(ERROR) << "Unsupported video format " << FourCCToString(actual_format) << " in stsd box."; @@ -413,7 +439,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) { bool is_encrypted = entry.sinf.info.track_encryption.is_encrypted; DVLOG(1) << "is_video_track_encrypted_: " << is_encrypted; streams.push_back(new VideoStreamInfo( - track->header.track_id, timescale, duration, kCodecH264, + track->header.track_id, timescale, duration, video_codec, codec_string, track->media.header.language, coded_width, coded_height, pixel_width, pixel_height, 0, // trick_play_rate diff --git a/packager/media/formats/mp4/mp4_muxer.cc b/packager/media/formats/mp4/mp4_muxer.cc index e477a0ca7a..1901aec947 100644 --- a/packager/media/formats/mp4/mp4_muxer.cc +++ b/packager/media/formats/mp4/mp4_muxer.cc @@ -22,7 +22,12 @@ #include "packager/media/formats/mp4/multi_segment_segmenter.h" #include "packager/media/formats/mp4/single_segment_segmenter.h" +namespace edash_packager { +namespace media { +namespace mp4 { + namespace { + // Sets the range start and end value from offset and size. // |start| and |end| are for byte-range-spec specified in RFC2616. void SetStartAndEndFromOffsetAndSize(size_t offset, @@ -34,11 +39,23 @@ void SetStartAndEndFromOffsetAndSize(size_t offset, // Note that ranges are inclusive. So we need - 1. *end = *start + static_cast(size) - 1; } -} // namespace -namespace edash_packager { -namespace media { -namespace mp4 { +FourCC CodecToFourCC(VideoCodec codec) { + switch (codec) { + case kCodecH264: + return FOURCC_AVC1; + case kCodecVP8: + return FOURCC_VP08; + case kCodecVP9: + return FOURCC_VP09; + case kCodecVP10: + return FOURCC_VP10; + default: + return FOURCC_NULL; + } +} + +} // namespace MP4Muxer::MP4Muxer(const MuxerOptions& options) : Muxer(options) {} MP4Muxer::~MP4Muxer() {} @@ -53,8 +70,12 @@ Status MP4Muxer::Initialize() { ftyp->compatible_brands.push_back(FOURCC_ISO6); ftyp->compatible_brands.push_back(FOURCC_MP41); if (streams().size() == 1 && - streams()[0]->info()->stream_type() == kStreamVideo) - ftyp->compatible_brands.push_back(FOURCC_AVC1); + streams()[0]->info()->stream_type() == kStreamVideo) { + const FourCC codec_fourcc = CodecToFourCC( + static_cast(streams()[0]->info().get())->codec()); + if (codec_fourcc != FOURCC_NULL) + ftyp->compatible_brands.push_back(codec_fourcc); + } moov->header.creation_time = IsoTimeNow(); moov->header.modification_time = IsoTimeNow(); @@ -176,7 +197,7 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info, trak->media.handler.type = kVideo; VideoSampleEntry video; - video.format = FOURCC_AVC1; + video.format = CodecToFourCC(video_info->codec()); video.width = video_info->width(); video.height = video_info->height(); video.codec_config_record.data = video_info->extra_data(); diff --git a/packager/media/formats/webm/webm.gyp b/packager/media/formats/webm/webm.gyp index 562a5d39d3..4e16917ad8 100644 --- a/packager/media/formats/webm/webm.gyp +++ b/packager/media/formats/webm/webm.gyp @@ -41,6 +41,7 @@ 'dependencies': [ '../../../third_party/libwebm/libwebm.gyp:libwebm', '../../base/media_base.gyp:base', + '../../filters/filters.gyp:filters' ], }, { diff --git a/packager/media/formats/webm/webm_video_client.cc b/packager/media/formats/webm/webm_video_client.cc index c4b08e831e..373f8ae2f1 100644 --- a/packager/media/formats/webm/webm_video_client.cc +++ b/packager/media/formats/webm/webm_video_client.cc @@ -5,6 +5,8 @@ #include "packager/media/formats/webm/webm_video_client.h" #include "packager/base/logging.h" +#include "packager/base/stl_util.h" +#include "packager/media/filters/vp_codec_configuration.h" #include "packager/media/formats/webm/webm_constants.h" namespace { @@ -56,6 +58,8 @@ scoped_refptr WebMVideoClient::GetVideoStreamInfo( video_codec = kCodecVP8; } else if (codec_id == "V_VP9") { video_codec = kCodecVP9; + } else if (codec_id == "V_VP10") { + video_codec = kCodecVP10; } else { LOG(ERROR) << "Unsupported video codec_id " << codec_id; return scoped_refptr(); @@ -102,20 +106,25 @@ scoped_refptr WebMVideoClient::GetVideoStreamInfo( sar_x /= gcd; sar_y /= gcd; - const uint8_t* extra_data = NULL; - size_t extra_data_size = 0; - if (codec_private.size() > 0) { - extra_data = &codec_private[0]; - extra_data_size = codec_private.size(); - } - - // TODO(kqyang): Generate codec string. - std::string codec_string; + // TODO(kqyang): Fill in the values for vp codec configuration. + const uint8_t profile = 0; + const uint8_t level = 0; + const uint8_t bit_depth = 8; + const uint8_t color_space = 0; + const uint8_t chroma_subsampling = 0; + const uint8_t transfer_function = 0; + const bool video_full_range_flag = false; + VPCodecConfiguration vp_config(profile, level, bit_depth, color_space, + chroma_subsampling, transfer_function, + video_full_range_flag, codec_private); + std::vector extra_data; + vp_config.Write(&extra_data); return scoped_refptr(new VideoStreamInfo( - track_num, kWebMTimeScale, 0, video_codec, codec_string, std::string(), - width_after_crop, height_after_crop, sar_x, sar_y, 0, 0, extra_data, - extra_data_size, is_encrypted)); + track_num, kWebMTimeScale, 0, video_codec, + vp_config.GetCodecString(video_codec), std::string(), width_after_crop, + height_after_crop, sar_x, sar_y, 0, 0, vector_as_array(&extra_data), + extra_data.size(), is_encrypted)); } bool WebMVideoClient::OnUInt(int id, int64_t val) { diff --git a/packager/packager.gyp b/packager/packager.gyp index 2ab3accc1c..6c77b0ee3c 100644 --- a/packager/packager.gyp +++ b/packager/packager.gyp @@ -74,6 +74,7 @@ 'media/formats/mp2t/mp2t.gyp:mp2t', 'media/formats/mp4/mp4.gyp:mp4', 'media/formats/mpeg/mpeg.gyp:mpeg', + 'media/formats/webm/webm.gyp:webm', 'media/formats/wvm/wvm.gyp:wvm', 'media/test/media_test.gyp:media_test_support', 'testing/gtest.gyp:gtest', @@ -88,6 +89,7 @@ 'media/file/file.gyp:*', 'media/formats/mp2t/mp2t.gyp:*', 'media/formats/mp4/mp4.gyp:*', + 'media/formats/webm/webm.gyp:*', 'media/formats/wvm/wvm.gyp:*', 'mpd/mpd.gyp:*', ],