VPCodecConfiguration box should inherit from FullBox instead of Box

Change-Id: If53c6cab009bdeadc37a1bac34272056a2b7d1dc
This commit is contained in:
Kongqun Yang 2016-05-24 18:07:14 -07:00
parent 2ef100e87d
commit e9ad85c945
10 changed files with 126 additions and 56 deletions

View File

@ -3,14 +3,14 @@
<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" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.7360000610351562S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="320" height="240" frameRate="1000000/34000" subsegmentAlignment="true" par="16:9">
<Representation id="0" bandwidth="210135" codecs="vp09.00.00.08.00.01.00.00" mimeType="video/mp4" sar="427:320">
<Representation id="0" bandwidth="210158" codecs="vp09.00.00.08.00.01.00.00" mimeType="video/mp4" sar="427:320">
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
</ContentProtection>
<BaseURL>output_video.mp4</BaseURL>
<SegmentBase indexRange="1039-1106" timescale="1000000">
<Initialization range="0-1038"/>
<SegmentBase indexRange="1047-1114" timescale="1000000">
<Initialization range="0-1046"/>
</SegmentBase>
</Representation>
</AdaptationSet>

View File

@ -3,14 +3,14 @@
<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" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.7360000610351562S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="1000000/33000" subsegmentAlignment="true" par="16:9">
<Representation id="0" bandwidth="342164" codecs="vp08.00.00.08.01.01.00.00" mimeType="video/mp4" sar="1:1">
<Representation id="0" bandwidth="342188" codecs="vp08.00.00.08.01.01.00.00" mimeType="video/mp4" sar="1:1">
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
</ContentProtection>
<BaseURL>output_video.mp4</BaseURL>
<SegmentBase indexRange="1007-1074" timescale="1000000">
<Initialization range="0-1006"/>
<SegmentBase indexRange="1015-1082" timescale="1000000">
<Initialization range="0-1014"/>
</SegmentBase>
</Representation>
</AdaptationSet>

View File

@ -1186,16 +1186,27 @@ uint32_t Metadata::ComputeSizeInternal() {
: HeaderSize() + handler.ComputeSize() + id3v2_size;
}
CodecConfigurationRecord::CodecConfigurationRecord() : box_type(FOURCC_NULL) {}
CodecConfigurationRecord::~CodecConfigurationRecord() {}
FourCC CodecConfigurationRecord::BoxType() const {
// CodecConfigurationRecord should be parsed according to format recovered in
CodecConfiguration::CodecConfiguration() : box_type(FOURCC_NULL) {}
CodecConfiguration::~CodecConfiguration() {}
FourCC CodecConfiguration::BoxType() const {
// CodecConfiguration box should be parsed according to format recovered in
// VideoSampleEntry. |box_type| is determined dynamically there.
return box_type;
}
bool CodecConfigurationRecord::ReadWriteInternal(BoxBuffer* buffer) {
bool CodecConfiguration::ReadWriteInternal(BoxBuffer* buffer) {
DCHECK_NE(box_type, FOURCC_NULL);
RCHECK(ReadWriteHeaderInternal(buffer));
// VPCodecConfiguration box inherits from FullBox instead of Box. The extra 4
// bytes are handled here.
if (box_type == FOURCC_VPCC) {
uint32_t version_flags = 0;
RCHECK(buffer->ReadWriteUInt32(&version_flags));
RCHECK(version_flags == 0);
}
if (buffer->Reading()) {
RCHECK(buffer->ReadWriteVector(&data, buffer->BytesLeft()));
} else {
@ -1204,10 +1215,11 @@ bool CodecConfigurationRecord::ReadWriteInternal(BoxBuffer* buffer) {
return true;
}
uint32_t CodecConfigurationRecord::ComputeSizeInternal() {
uint32_t CodecConfiguration::ComputeSizeInternal() {
if (data.empty())
return 0;
return HeaderSize() + data.size();
DCHECK_NE(box_type, FOURCC_NULL);
return HeaderSize() + (box_type == FOURCC_VPCC ? 4 : 0) + data.size();
}
PixelAspectRatio::PixelAspectRatio() : h_spacing(0), v_spacing(0) {}
@ -1310,37 +1322,50 @@ bool VideoSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
}
const FourCC actual_format = GetActualFormat();
switch (actual_format) {
case FOURCC_AVC1:
codec_config_record.box_type = FOURCC_AVCC;
break;
case FOURCC_HEV1:
case FOURCC_HVC1:
codec_config_record.box_type = FOURCC_HVCC;
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;
if (buffer->Reading()) {
codec_configuration.box_type = GetCodecConfigurationBoxType(actual_format);
} else {
DCHECK_EQ(codec_configuration.box_type,
GetCodecConfigurationBoxType(actual_format));
}
RCHECK(buffer->ReadWriteChild(&codec_config_record));
DCHECK_NE(codec_configuration.box_type, FOURCC_NULL);
RCHECK(buffer->ReadWriteChild(&codec_configuration));
RCHECK(buffer->TryReadWriteChild(&pixel_aspect));
return true;
}
uint32_t VideoSampleEntry::ComputeSizeInternal() {
const FourCC actual_format = GetActualFormat();
if (actual_format == FOURCC_NULL)
return 0;
codec_configuration.box_type = GetCodecConfigurationBoxType(actual_format);
DCHECK_NE(codec_configuration.box_type, FOURCC_NULL);
return HeaderSize() + sizeof(data_reference_index) + sizeof(width) +
sizeof(height) + sizeof(kVideoResolution) * 2 +
sizeof(kVideoFrameCount) + sizeof(kVideoDepth) +
pixel_aspect.ComputeSize() + sinf.ComputeSize() +
codec_config_record.ComputeSize() + kCompressorNameSize + 6 + 4 + 16 +
codec_configuration.ComputeSize() + kCompressorNameSize + 6 + 4 + 16 +
2; // 6 + 4 bytes reserved, 16 + 2 bytes predefined.
}
FourCC VideoSampleEntry::GetCodecConfigurationBoxType(FourCC format) const {
switch (format) {
case FOURCC_AVC1:
return FOURCC_AVCC;
case FOURCC_HEV1:
case FOURCC_HVC1:
return FOURCC_HVCC;
case FOURCC_VP08:
case FOURCC_VP09:
case FOURCC_VP10:
return FOURCC_VPCC;
default:
LOG(ERROR) << FourCCToString(format) << " is not supported.";
return FOURCC_NULL;
}
}
ElementaryStreamDescriptor::ElementaryStreamDescriptor() {}
ElementaryStreamDescriptor::~ElementaryStreamDescriptor() {}
FourCC ElementaryStreamDescriptor::BoxType() const { return FOURCC_ESDS; }
@ -1502,6 +1527,8 @@ bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
}
uint32_t AudioSampleEntry::ComputeSizeInternal() {
if (GetActualFormat() == FOURCC_NULL)
return 0;
return HeaderSize() + sizeof(data_reference_index) + sizeof(channelcount) +
sizeof(samplesize) + sizeof(samplerate) + sinf.ComputeSize() +
esds.ComputeSize() + ddts.ComputeSize() + dac3.ComputeSize() +

View File

@ -257,8 +257,14 @@ struct Metadata : FullBox {
ID3v2 id3v2;
};
struct CodecConfigurationRecord : Box {
DECLARE_BOX_METHODS(CodecConfigurationRecord);
// This defines a common structure for various CodecConfiguration boxes:
// AVCConfiguration, HEVCConfiguration and VPCodecConfiguration.
// Note that unlike the other two CodecConfiguration boxes, VPCodecConfiguration
// box inherits from FullBox instead of Box, according to VP Codec ISO Media
// File Format Binding specification. It will be handled properly in the
// implementation.
struct CodecConfiguration: Box {
DECLARE_BOX_METHODS(CodecConfiguration);
FourCC box_type;
// Contains full codec configuration record, including possible extension
@ -279,6 +285,8 @@ struct VideoSampleEntry : Box {
FourCC GetActualFormat() const {
return format == FOURCC_ENCV ? sinf.format.format : format;
}
// Returns the box type of codec configuration box from video format.
FourCC GetCodecConfigurationBoxType(FourCC format) const;
FourCC format;
uint16_t data_reference_index;
@ -287,7 +295,7 @@ struct VideoSampleEntry : Box {
PixelAspectRatio pixel_aspect;
ProtectionSchemeInfo sinf;
CodecConfigurationRecord codec_config_record;
CodecConfiguration codec_configuration;
};
struct ElementaryStreamDescriptor : FullBox {

View File

@ -200,9 +200,9 @@ inline bool operator==(const Metadata& lhs, const Metadata& rhs) {
return lhs.handler == rhs.handler && lhs.id3v2 == rhs.id3v2;
}
inline bool operator==(const CodecConfigurationRecord& lhs,
const CodecConfigurationRecord& rhs) {
return lhs.data == rhs.data;
inline bool operator==(const CodecConfiguration& lhs,
const CodecConfiguration& rhs) {
return lhs.box_type == rhs.box_type && lhs.data == rhs.data;
}
inline bool operator==(const PixelAspectRatio& lhs,
@ -216,7 +216,7 @@ inline bool operator==(const VideoSampleEntry& lhs,
lhs.data_reference_index == rhs.data_reference_index &&
lhs.width == rhs.width && lhs.height == rhs.height &&
lhs.pixel_aspect == rhs.pixel_aspect && lhs.sinf == rhs.sinf &&
lhs.codec_config_record == rhs.codec_config_record;
lhs.codec_configuration == rhs.codec_configuration;
}
inline bool operator==(const ESDescriptor& lhs, const ESDescriptor& rhs) {

View File

@ -328,24 +328,26 @@ class BoxDefinitionsTestGeneral : public testing::Test {
void Modify(PixelAspectRatio* pasp) { pasp->v_spacing *= 8; }
void Fill(CodecConfigurationRecord* codec_config_record) {
const uint8_t kAvccData[] = {
void Fill(CodecConfiguration* codec_configuration) {
const uint8_t kCodecConfigurationData[] = {
0x01, 0x64, 0x00, 0x1f, 0xff, 0xe1, 0x00, 0x18, 0x67, 0x64, 0x00,
0x1f, 0xac, 0xd9, 0x40, 0x50, 0x05, 0xbb, 0x01, 0x10, 0x00, 0x00,
0x3e, 0x90, 0x00, 0x0e, 0xa6, 0x00, 0xf1, 0x83, 0x19, 0x60, 0x01,
0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0};
codec_config_record->data.assign(kAvccData,
kAvccData + arraysize(kAvccData));
codec_configuration->data.assign(
kCodecConfigurationData,
kCodecConfigurationData + arraysize(kCodecConfigurationData));
}
void Modify(CodecConfigurationRecord* codec_config_record) {
const uint8_t kAvccData[] = {
void Modify(CodecConfiguration* codec_configuration) {
const uint8_t kCodecConfigurationData[] = {
0x01, 0x64, 0x00, 0x1e, 0xff, 0xe1, 0x00, 0x19, 0x67, 0x64, 0x00,
0x1e, 0xac, 0xd9, 0x40, 0xa0, 0x2f, 0xf9, 0x70, 0x11, 0x00, 0x00,
0x03, 0x03, 0xe9, 0x00, 0x00, 0xea, 0x60, 0x0f, 0x16, 0x2d, 0x96,
0x01, 0x00, 0x05, 0x68, 0xeb, 0xec, 0xb2, 0x2c};
codec_config_record->data.assign(kAvccData,
kAvccData + arraysize(kAvccData));
codec_configuration->data.assign(
kCodecConfigurationData,
kCodecConfigurationData + arraysize(kCodecConfigurationData));
}
void Fill(VideoSampleEntry* encv) {
@ -355,12 +357,12 @@ class BoxDefinitionsTestGeneral : public testing::Test {
encv->height = 600;
Fill(&encv->pixel_aspect);
Fill(&encv->sinf);
Fill(&encv->codec_config_record);
Fill(&encv->codec_configuration);
}
void Modify(VideoSampleEntry* encv) {
encv->height += 600;
Modify(&encv->codec_config_record);
Modify(&encv->codec_configuration);
}
void Fill(ElementaryStreamDescriptor* esds) {
@ -913,11 +915,13 @@ class BoxDefinitionsTestGeneral : public testing::Test {
bool IsOptional(const ProtectionSchemeInfo* box) { return true; }
bool IsOptional(const EditList* box) { return true; }
bool IsOptional(const Edit* box) { return true; }
bool IsOptional(const CodecConfigurationRecord* box) { return true; }
bool IsOptional(const CodecConfiguration* box) { return true; }
bool IsOptional(const PixelAspectRatio* box) { return true; }
bool IsOptional(const VideoSampleEntry* box) { return true; }
bool IsOptional(const ElementaryStreamDescriptor* box) { return true; }
bool IsOptional(const AC3Specific* box) { return true; }
bool IsOptional(const EC3Specific* box) { return true; }
bool IsOptional(const AudioSampleEntry* box) { return true; }
// Recommended, but optional.
bool IsOptional(const ProtectionSystemSpecificHeader* box) { return true; }
bool IsOptional(const WebVTTSourceLabelBox* box) { return true; }
@ -956,7 +960,6 @@ typedef testing::Types<FileType,
HandlerReference,
ID3v2,
Metadata,
CodecConfigurationRecord,
PixelAspectRatio,
VideoSampleEntry,
ElementaryStreamDescriptor,
@ -1094,6 +1097,38 @@ TEST_F(BoxDefinitionsTest, MediaHandlerType) {
ASSERT_EQ(FOURCC_VIDE, media_readback.handler.handler_type);
}
TEST_F(BoxDefinitionsTest, AvcCodecConfiguration) {
CodecConfiguration codec_configuration;
Fill(&codec_configuration);
codec_configuration.box_type = FOURCC_AVCC;
codec_configuration.Write(this->buffer_.get());
// Should inherit from Box.
EXPECT_EQ(
8u, codec_configuration.ComputeSize() - codec_configuration.data.size());
CodecConfiguration codec_configuration_readback;
// BoxType should be provided before parsing the box.
codec_configuration_readback.box_type = FOURCC_AVCC;
ASSERT_TRUE(ReadBack(&codec_configuration_readback));
EXPECT_EQ(codec_configuration, codec_configuration_readback);
}
TEST_F(BoxDefinitionsTest, VPCodecConfiguration) {
CodecConfiguration codec_configuration;
Fill(&codec_configuration);
codec_configuration.box_type = FOURCC_VPCC;
codec_configuration.Write(this->buffer_.get());
// Should inherit from FullBox.
EXPECT_EQ(
12u, codec_configuration.ComputeSize() - codec_configuration.data.size());
CodecConfiguration codec_configuration_readback;
// BoxType should be provided before parsing the box.
codec_configuration_readback.box_type = FOURCC_VPCC;
ASSERT_TRUE(ReadBack(&codec_configuration_readback));
EXPECT_EQ(codec_configuration, codec_configuration_readback);
}
TEST_F(BoxDefinitionsTest, DTSSampleEntry) {
AudioSampleEntry entry;
entry.format = FOURCC_DTSE;

View File

@ -471,7 +471,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
switch (actual_format) {
case FOURCC_AVC1: {
AVCDecoderConfiguration avc_config;
if (!avc_config.Parse(entry.codec_config_record.data)) {
if (!avc_config.Parse(entry.codec_configuration.data)) {
LOG(ERROR) << "Failed to parse avcc.";
return false;
}
@ -508,7 +508,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
case FOURCC_HEV1:
case FOURCC_HVC1: {
HEVCDecoderConfiguration hevc_config;
if (!hevc_config.Parse(entry.codec_config_record.data)) {
if (!hevc_config.Parse(entry.codec_configuration.data)) {
LOG(ERROR) << "Failed to parse hevc.";
return false;
}
@ -520,7 +520,7 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
case FOURCC_VP09:
case FOURCC_VP10: {
VPCodecConfiguration vp_config;
if (!vp_config.Parse(entry.codec_config_record.data)) {
if (!vp_config.Parse(entry.codec_configuration.data)) {
LOG(ERROR) << "Failed to parse vpcc.";
return false;
}
@ -540,8 +540,8 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
codec_string, track->media.header.language.code, coded_width,
coded_height, pixel_width, pixel_height,
0, // trick_play_rate
nalu_length_size, entry.codec_config_record.data.data(),
entry.codec_config_record.data.size(), is_encrypted));
nalu_length_size, entry.codec_configuration.data.data(),
entry.codec_configuration.data.size(), is_encrypted));
}
}

View File

@ -232,7 +232,7 @@ void MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info,
video.format = VideoCodecToFourCC(video_info->codec());
video.width = video_info->width();
video.height = video_info->height();
video.codec_config_record.data = video_info->extra_data();
video.codec_configuration.data = video_info->extra_data();
if (pixel_width != 1 || pixel_height != 1) {
video.pixel_aspect.h_spacing = pixel_width;
video.pixel_aspect.v_spacing = pixel_height;