Implement initial support for vpx in iso-bmff
Also update the code to generate CompressorName in VideoSampleEntry for both AVC1 and various VP codecs. Change-Id: I2355f8008a72806e852aa1ec6c80e9141b97d963
This commit is contained in:
parent
749571fc07
commit
c577e6132f
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -17,6 +17,7 @@
|
||||||
#include "packager/media/file/file.h"
|
#include "packager/media/file/file.h"
|
||||||
#include "packager/media/formats/mp2t/mp2t_media_parser.h"
|
#include "packager/media/formats/mp2t/mp2t_media_parser.h"
|
||||||
#include "packager/media/formats/mp4/mp4_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"
|
#include "packager/media/formats/wvm/wvm_media_parser.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -83,6 +84,9 @@ Status Demuxer::Initialize() {
|
||||||
case CONTAINER_MPEG2PS:
|
case CONTAINER_MPEG2PS:
|
||||||
parser_.reset(new wvm::WvmMediaParser());
|
parser_.reset(new wvm::WvmMediaParser());
|
||||||
break;
|
break;
|
||||||
|
case CONTAINER_WEBM:
|
||||||
|
parser_.reset(new WebMMediaParser());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
return Status(error::UNIMPLEMENTED, "Container not supported.");
|
return Status(error::UNIMPLEMENTED, "Container not supported.");
|
||||||
|
|
|
@ -33,6 +33,8 @@ std::string VideoCodecToString(VideoCodec video_codec) {
|
||||||
return "VP8";
|
return "VP8";
|
||||||
case kCodecVP9:
|
case kCodecVP9:
|
||||||
return "VP9";
|
return "VP9";
|
||||||
|
case kCodecVP10:
|
||||||
|
return "VP10";
|
||||||
default:
|
default:
|
||||||
NOTIMPLEMENTED() << "Unknown Video Codec: " << video_codec;
|
NOTIMPLEMENTED() << "Unknown Video Codec: " << video_codec;
|
||||||
return "UnknownVideoCodec";
|
return "UnknownVideoCodec";
|
||||||
|
|
|
@ -21,6 +21,7 @@ enum VideoCodec {
|
||||||
kCodecTheora,
|
kCodecTheora,
|
||||||
kCodecVP8,
|
kCodecVP8,
|
||||||
kCodecVP9,
|
kCodecVP9,
|
||||||
|
kCodecVP10,
|
||||||
kNumVideoCodec
|
kNumVideoCodec
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
'h264_byte_to_unit_stream_converter.h',
|
'h264_byte_to_unit_stream_converter.h',
|
||||||
'h264_parser.cc',
|
'h264_parser.cc',
|
||||||
'h264_parser.h',
|
'h264_parser.h',
|
||||||
|
'vp_codec_configuration.cc',
|
||||||
|
'vp_codec_configuration.h',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'../../base/base.gyp:base',
|
'../../base/base.gyp:base',
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
'h264_bit_reader_unittest.cc',
|
'h264_bit_reader_unittest.cc',
|
||||||
'h264_byte_to_unit_stream_converter_unittest.cc',
|
'h264_byte_to_unit_stream_converter_unittest.cc',
|
||||||
'h264_parser_unittest.cc',
|
'h264_parser_unittest.cc',
|
||||||
|
'vp_codec_configuration_unittest.cc',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'../../media/base/media_base.gyp:base',
|
'../../media/base/media_base.gyp:base',
|
||||||
|
|
|
@ -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<uint8_t>& 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<uint8_t>& 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<uint8_t>* 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
|
|
@ -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 <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#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<uint8_t>& codec_initialization_data);
|
||||||
|
~VPCodecConfiguration();
|
||||||
|
|
||||||
|
/// Parses input to extract VP codec configuration data.
|
||||||
|
/// @return false if there is parsing errors.
|
||||||
|
bool Parse(const std::vector<uint8_t>& data);
|
||||||
|
|
||||||
|
/// @param data should not be null.
|
||||||
|
/// Writes VP codec configuration data to buffer.
|
||||||
|
void Write(std::vector<uint8_t>* 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<uint8_t> codec_initialization_data_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(VPCodecConfiguration);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
|
#endif // MEDIA_FILTERS_VP_CODEC_CONFIGURATION_H_
|
|
@ -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 <gtest/gtest.h>
|
||||||
|
|
||||||
|
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<uint8_t>(
|
||||||
|
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<uint8_t>(
|
||||||
|
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<uint8_t>());
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
vp_config.Write(&data);
|
||||||
|
|
||||||
|
EXPECT_EQ(
|
||||||
|
std::vector<uint8_t>(kExpectedVpCodecConfigurationData,
|
||||||
|
kExpectedVpCodecConfigurationData +
|
||||||
|
arraysize(kExpectedVpCodecConfigurationData)),
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
|
@ -36,6 +36,8 @@ const uint16_t kVideoFrameCount = 1;
|
||||||
const uint16_t kVideoDepth = 0x0018;
|
const uint16_t kVideoDepth = 0x0018;
|
||||||
|
|
||||||
const uint32_t kCompressorNameSize = 32u;
|
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.
|
// Utility functions to check if the 64bit integers can fit in 32bit integer.
|
||||||
bool IsFitIn32Bits(uint64_t a) {
|
bool IsFitIn32Bits(uint64_t a) {
|
||||||
|
@ -933,12 +935,33 @@ FourCC VideoSampleEntry::BoxType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
||||||
|
std::vector<uint8_t> compressor_name;
|
||||||
if (buffer->Reading()) {
|
if (buffer->Reading()) {
|
||||||
DCHECK(buffer->reader());
|
DCHECK(buffer->reader());
|
||||||
format = buffer->reader()->type();
|
format = buffer->reader()->type();
|
||||||
} else {
|
} else {
|
||||||
RCHECK(buffer->ReadWriteUInt32(&atom_size) &&
|
RCHECK(buffer->ReadWriteUInt32(&atom_size) &&
|
||||||
buffer->ReadWriteFourCC(&format));
|
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;
|
uint32_t video_resolution = kVideoResolution;
|
||||||
|
@ -954,7 +977,7 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
||||||
buffer->ReadWriteUInt32(&video_resolution) &&
|
buffer->ReadWriteUInt32(&video_resolution) &&
|
||||||
buffer->IgnoreBytes(4) && // reserved.
|
buffer->IgnoreBytes(4) && // reserved.
|
||||||
buffer->ReadWriteUInt16(&video_frame_count) &&
|
buffer->ReadWriteUInt16(&video_frame_count) &&
|
||||||
buffer->IgnoreBytes(32) && // comparessor_name.
|
buffer->ReadWriteVector(&compressor_name, kCompressorNameSize) &&
|
||||||
buffer->ReadWriteUInt16(&video_depth) &&
|
buffer->ReadWriteUInt16(&video_depth) &&
|
||||||
buffer->ReadWriteInt16(&predefined));
|
buffer->ReadWriteInt16(&predefined));
|
||||||
|
|
||||||
|
@ -978,6 +1001,11 @@ bool VideoSampleEntry::ReadWrite(BoxBuffer* buffer) {
|
||||||
case FOURCC_AVC1:
|
case FOURCC_AVC1:
|
||||||
codec_config_record.box_type = FOURCC_AVCC;
|
codec_config_record.box_type = FOURCC_AVCC;
|
||||||
break;
|
break;
|
||||||
|
case FOURCC_VP08:
|
||||||
|
case FOURCC_VP09:
|
||||||
|
case FOURCC_VP10:
|
||||||
|
codec_config_record.box_type = FOURCC_VPCC;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(ERROR) << FourCCToString(actual_format) << " is not supported.";
|
LOG(ERROR) << FourCCToString(actual_format) << " is not supported.";
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -92,6 +92,10 @@ enum FourCC {
|
||||||
FOURCC_UUID = 0x75756964,
|
FOURCC_UUID = 0x75756964,
|
||||||
FOURCC_VIDE = 0x76696465,
|
FOURCC_VIDE = 0x76696465,
|
||||||
FOURCC_VMHD = 0x766d6864,
|
FOURCC_VMHD = 0x766d6864,
|
||||||
|
FOURCC_VP08 = 0x76703038,
|
||||||
|
FOURCC_VP09 = 0x76703039,
|
||||||
|
FOURCC_VP10 = 0x76703130,
|
||||||
|
FOURCC_VPCC = 0x76706343,
|
||||||
FOURCC_WIDE = 0x77696465,
|
FOURCC_WIDE = 0x77696465,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,16 @@
|
||||||
#include "packager/media/file/file.h"
|
#include "packager/media/file/file.h"
|
||||||
#include "packager/media/file/file_closer.h"
|
#include "packager/media/file/file_closer.h"
|
||||||
#include "packager/media/filters/avc_decoder_configuration.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_definitions.h"
|
||||||
#include "packager/media/formats/mp4/box_reader.h"
|
#include "packager/media/formats/mp4/box_reader.h"
|
||||||
#include "packager/media/formats/mp4/es_descriptor.h"
|
#include "packager/media/formats/mp4/es_descriptor.h"
|
||||||
#include "packager/media/formats/mp4/rcheck.h"
|
#include "packager/media/formats/mp4/rcheck.h"
|
||||||
#include "packager/media/formats/mp4/track_run_iterator.h"
|
#include "packager/media/formats/mp4/track_run_iterator.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
namespace mp4 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
uint64_t Rescale(uint64_t time_in_old_scale,
|
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<double>(time_in_old_scale) / old_scale) * new_scale;
|
return (static_cast<double>(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";
|
const char kWidevineKeySystemId[] = "edef8ba979d64acea3c827dcd51d21ed";
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace edash_packager {
|
|
||||||
namespace media {
|
|
||||||
namespace mp4 {
|
|
||||||
|
|
||||||
MP4MediaParser::MP4MediaParser()
|
MP4MediaParser::MP4MediaParser()
|
||||||
: state_(kWaitingForInit), moof_head_(0), mdat_tail_(0) {}
|
: state_(kWaitingForInit), moof_head_(0), mdat_tail_(0) {}
|
||||||
|
|
||||||
|
@ -367,6 +381,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
uint8_t nalu_length_size = 0;
|
uint8_t nalu_length_size = 0;
|
||||||
|
|
||||||
const FourCC actual_format = entry.GetActualFormat();
|
const FourCC actual_format = entry.GetActualFormat();
|
||||||
|
const VideoCodec video_codec = FourCCToCodec(actual_format);
|
||||||
switch (actual_format) {
|
switch (actual_format) {
|
||||||
case FOURCC_AVC1: {
|
case FOURCC_AVC1: {
|
||||||
AVCDecoderConfiguration avc_config;
|
AVCDecoderConfiguration avc_config;
|
||||||
|
@ -404,6 +419,17 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
LOG(ERROR) << "Unsupported video format "
|
LOG(ERROR) << "Unsupported video format "
|
||||||
<< FourCCToString(actual_format) << " in stsd box.";
|
<< 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;
|
bool is_encrypted = entry.sinf.info.track_encryption.is_encrypted;
|
||||||
DVLOG(1) << "is_video_track_encrypted_: " << is_encrypted;
|
DVLOG(1) << "is_video_track_encrypted_: " << is_encrypted;
|
||||||
streams.push_back(new VideoStreamInfo(
|
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,
|
codec_string, track->media.header.language, coded_width, coded_height,
|
||||||
pixel_width, pixel_height,
|
pixel_width, pixel_height,
|
||||||
0, // trick_play_rate
|
0, // trick_play_rate
|
||||||
|
|
|
@ -22,7 +22,12 @@
|
||||||
#include "packager/media/formats/mp4/multi_segment_segmenter.h"
|
#include "packager/media/formats/mp4/multi_segment_segmenter.h"
|
||||||
#include "packager/media/formats/mp4/single_segment_segmenter.h"
|
#include "packager/media/formats/mp4/single_segment_segmenter.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
namespace mp4 {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Sets the range start and end value from offset and size.
|
// Sets the range start and end value from offset and size.
|
||||||
// |start| and |end| are for byte-range-spec specified in RFC2616.
|
// |start| and |end| are for byte-range-spec specified in RFC2616.
|
||||||
void SetStartAndEndFromOffsetAndSize(size_t offset,
|
void SetStartAndEndFromOffsetAndSize(size_t offset,
|
||||||
|
@ -34,11 +39,23 @@ void SetStartAndEndFromOffsetAndSize(size_t offset,
|
||||||
// Note that ranges are inclusive. So we need - 1.
|
// Note that ranges are inclusive. So we need - 1.
|
||||||
*end = *start + static_cast<uint32_t>(size) - 1;
|
*end = *start + static_cast<uint32_t>(size) - 1;
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace edash_packager {
|
FourCC CodecToFourCC(VideoCodec codec) {
|
||||||
namespace media {
|
switch (codec) {
|
||||||
namespace mp4 {
|
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(const MuxerOptions& options) : Muxer(options) {}
|
||||||
MP4Muxer::~MP4Muxer() {}
|
MP4Muxer::~MP4Muxer() {}
|
||||||
|
@ -53,8 +70,12 @@ Status MP4Muxer::Initialize() {
|
||||||
ftyp->compatible_brands.push_back(FOURCC_ISO6);
|
ftyp->compatible_brands.push_back(FOURCC_ISO6);
|
||||||
ftyp->compatible_brands.push_back(FOURCC_MP41);
|
ftyp->compatible_brands.push_back(FOURCC_MP41);
|
||||||
if (streams().size() == 1 &&
|
if (streams().size() == 1 &&
|
||||||
streams()[0]->info()->stream_type() == kStreamVideo)
|
streams()[0]->info()->stream_type() == kStreamVideo) {
|
||||||
ftyp->compatible_brands.push_back(FOURCC_AVC1);
|
const FourCC codec_fourcc = CodecToFourCC(
|
||||||
|
static_cast<VideoStreamInfo*>(streams()[0]->info().get())->codec());
|
||||||
|
if (codec_fourcc != FOURCC_NULL)
|
||||||
|
ftyp->compatible_brands.push_back(codec_fourcc);
|
||||||
|
}
|
||||||
|
|
||||||
moov->header.creation_time = IsoTimeNow();
|
moov->header.creation_time = IsoTimeNow();
|
||||||
moov->header.modification_time = IsoTimeNow();
|
moov->header.modification_time = IsoTimeNow();
|
||||||
|
@ -176,7 +197,7 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info,
|
||||||
trak->media.handler.type = kVideo;
|
trak->media.handler.type = kVideo;
|
||||||
|
|
||||||
VideoSampleEntry video;
|
VideoSampleEntry video;
|
||||||
video.format = FOURCC_AVC1;
|
video.format = CodecToFourCC(video_info->codec());
|
||||||
video.width = video_info->width();
|
video.width = video_info->width();
|
||||||
video.height = video_info->height();
|
video.height = video_info->height();
|
||||||
video.codec_config_record.data = video_info->extra_data();
|
video.codec_config_record.data = video_info->extra_data();
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'../../../third_party/libwebm/libwebm.gyp:libwebm',
|
'../../../third_party/libwebm/libwebm.gyp:libwebm',
|
||||||
'../../base/media_base.gyp:base',
|
'../../base/media_base.gyp:base',
|
||||||
|
'../../filters/filters.gyp:filters'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "packager/media/formats/webm/webm_video_client.h"
|
#include "packager/media/formats/webm/webm_video_client.h"
|
||||||
|
|
||||||
#include "packager/base/logging.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"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -56,6 +58,8 @@ scoped_refptr<VideoStreamInfo> WebMVideoClient::GetVideoStreamInfo(
|
||||||
video_codec = kCodecVP8;
|
video_codec = kCodecVP8;
|
||||||
} else if (codec_id == "V_VP9") {
|
} else if (codec_id == "V_VP9") {
|
||||||
video_codec = kCodecVP9;
|
video_codec = kCodecVP9;
|
||||||
|
} else if (codec_id == "V_VP10") {
|
||||||
|
video_codec = kCodecVP10;
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Unsupported video codec_id " << codec_id;
|
LOG(ERROR) << "Unsupported video codec_id " << codec_id;
|
||||||
return scoped_refptr<VideoStreamInfo>();
|
return scoped_refptr<VideoStreamInfo>();
|
||||||
|
@ -102,20 +106,25 @@ scoped_refptr<VideoStreamInfo> WebMVideoClient::GetVideoStreamInfo(
|
||||||
sar_x /= gcd;
|
sar_x /= gcd;
|
||||||
sar_y /= gcd;
|
sar_y /= gcd;
|
||||||
|
|
||||||
const uint8_t* extra_data = NULL;
|
// TODO(kqyang): Fill in the values for vp codec configuration.
|
||||||
size_t extra_data_size = 0;
|
const uint8_t profile = 0;
|
||||||
if (codec_private.size() > 0) {
|
const uint8_t level = 0;
|
||||||
extra_data = &codec_private[0];
|
const uint8_t bit_depth = 8;
|
||||||
extra_data_size = codec_private.size();
|
const uint8_t color_space = 0;
|
||||||
}
|
const uint8_t chroma_subsampling = 0;
|
||||||
|
const uint8_t transfer_function = 0;
|
||||||
// TODO(kqyang): Generate codec string.
|
const bool video_full_range_flag = false;
|
||||||
std::string codec_string;
|
VPCodecConfiguration vp_config(profile, level, bit_depth, color_space,
|
||||||
|
chroma_subsampling, transfer_function,
|
||||||
|
video_full_range_flag, codec_private);
|
||||||
|
std::vector<uint8_t> extra_data;
|
||||||
|
vp_config.Write(&extra_data);
|
||||||
|
|
||||||
return scoped_refptr<VideoStreamInfo>(new VideoStreamInfo(
|
return scoped_refptr<VideoStreamInfo>(new VideoStreamInfo(
|
||||||
track_num, kWebMTimeScale, 0, video_codec, codec_string, std::string(),
|
track_num, kWebMTimeScale, 0, video_codec,
|
||||||
width_after_crop, height_after_crop, sar_x, sar_y, 0, 0, extra_data,
|
vp_config.GetCodecString(video_codec), std::string(), width_after_crop,
|
||||||
extra_data_size, is_encrypted));
|
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) {
|
bool WebMVideoClient::OnUInt(int id, int64_t val) {
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
'media/formats/mp2t/mp2t.gyp:mp2t',
|
'media/formats/mp2t/mp2t.gyp:mp2t',
|
||||||
'media/formats/mp4/mp4.gyp:mp4',
|
'media/formats/mp4/mp4.gyp:mp4',
|
||||||
'media/formats/mpeg/mpeg.gyp:mpeg',
|
'media/formats/mpeg/mpeg.gyp:mpeg',
|
||||||
|
'media/formats/webm/webm.gyp:webm',
|
||||||
'media/formats/wvm/wvm.gyp:wvm',
|
'media/formats/wvm/wvm.gyp:wvm',
|
||||||
'media/test/media_test.gyp:media_test_support',
|
'media/test/media_test.gyp:media_test_support',
|
||||||
'testing/gtest.gyp:gtest',
|
'testing/gtest.gyp:gtest',
|
||||||
|
@ -88,6 +89,7 @@
|
||||||
'media/file/file.gyp:*',
|
'media/file/file.gyp:*',
|
||||||
'media/formats/mp2t/mp2t.gyp:*',
|
'media/formats/mp2t/mp2t.gyp:*',
|
||||||
'media/formats/mp4/mp4.gyp:*',
|
'media/formats/mp4/mp4.gyp:*',
|
||||||
|
'media/formats/webm/webm.gyp:*',
|
||||||
'media/formats/wvm/wvm.gyp:*',
|
'media/formats/wvm/wvm.gyp:*',
|
||||||
'mpd/mpd.gyp:*',
|
'mpd/mpd.gyp:*',
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue