Index: media/formats/mp4/box_definitions.cc |
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc |
index fec356afd50fd55215a514bc973d3c59f5d52eca..0c083816a765fdf3b5f6443fa127fcb9e1ed2a28 100644 |
--- a/media/formats/mp4/box_definitions.cc |
+++ b/media/formats/mp4/box_definitions.cc |
@@ -5,6 +5,7 @@ |
#include "media/formats/mp4/box_definitions.h" |
#include "base/logging.h" |
+#include "media/base/video_util.h" |
#include "media/formats/mp4/es_descriptor.h" |
#include "media/formats/mp4/rcheck.h" |
@@ -413,6 +414,109 @@ bool AVCDecoderConfigurationRecord::ParseInternal(BufferReader* reader, |
return true; |
} |
+#if defined(ENABLE_HEVC_DEMUXING) |
+HEVCDecoderConfigurationRecord::HEVCDecoderConfigurationRecord() |
+ : configurationVersion(0), |
+ general_profile_space(0), |
+ general_tier_flag(0), |
+ general_profile_idc(0), |
+ general_profile_compatibility_flags(0), |
+ general_constraint_indicator_flags(0), |
+ general_level_idc(0), |
+ min_spatial_segmentation_idc(0), |
+ parallelismType(0), |
+ chromaFormat(0), |
+ bitDepthLumaMinus8(0), |
+ bitDepthChromaMinus8(0), |
+ avgFrameRate(0), |
+ constantFrameRate(0), |
+ numTemporalLayers(0), |
+ temporalIdNested(0), |
+ lengthSizeMinusOne(0), |
+ numOfArrays(0) {} |
+ |
+HEVCDecoderConfigurationRecord::~HEVCDecoderConfigurationRecord() {} |
+FourCC HEVCDecoderConfigurationRecord::BoxType() const { return FOURCC_HVCC; } |
+ |
+bool HEVCDecoderConfigurationRecord::Parse(BoxReader* reader) { |
+ return ParseInternal(reader, reader->log_cb()); |
+} |
+ |
+bool HEVCDecoderConfigurationRecord::Parse(const uint8* data, int data_size) { |
+ BufferReader reader(data, data_size); |
+ return ParseInternal(&reader, LogCB()); |
+} |
+ |
+HEVCDecoderConfigurationRecord::HVCCNALArray::HVCCNALArray() |
+ : first_byte(0) {} |
+ |
+HEVCDecoderConfigurationRecord::HVCCNALArray::~HVCCNALArray() {} |
+ |
+bool HEVCDecoderConfigurationRecord::ParseInternal(BufferReader* reader, |
+ const LogCB& log_cb) { |
+ uint8 profile_indication = 0; |
+ uint32 general_constraint_indicator_flags_hi = 0; |
+ uint16 general_constraint_indicator_flags_lo = 0; |
+ uint8 misc = 0; |
+ RCHECK(reader->Read1(&configurationVersion) && configurationVersion == 1 && |
+ reader->Read1(&profile_indication) && |
+ reader->Read4(&general_profile_compatibility_flags) && |
+ reader->Read4(&general_constraint_indicator_flags_hi) && |
+ reader->Read2(&general_constraint_indicator_flags_lo) && |
+ reader->Read1(&general_level_idc) && |
+ reader->Read2(&min_spatial_segmentation_idc) && |
+ reader->Read1(¶llelismType) && |
+ reader->Read1(&chromaFormat) && |
+ reader->Read1(&bitDepthLumaMinus8) && |
+ reader->Read1(&bitDepthChromaMinus8) && |
+ reader->Read2(&avgFrameRate) && |
+ reader->Read1(&misc) && |
+ reader->Read1(&numOfArrays)); |
+ |
+ general_profile_space = profile_indication >> 6; |
+ general_tier_flag = (profile_indication >> 5) & 1; |
+ general_profile_idc = profile_indication & 0x1f; |
+ |
+ general_constraint_indicator_flags = general_constraint_indicator_flags_hi; |
+ general_constraint_indicator_flags <<= 16; |
+ general_constraint_indicator_flags |= general_constraint_indicator_flags_lo; |
+ |
+ min_spatial_segmentation_idc &= 0xfff; |
+ parallelismType &= 3; |
+ chromaFormat &= 3; |
+ bitDepthLumaMinus8 &= 7; |
+ bitDepthChromaMinus8 &= 7; |
+ |
+ constantFrameRate = misc >> 6; |
+ numTemporalLayers = (misc >> 3) & 7; |
+ temporalIdNested = (misc >> 2) & 1; |
+ lengthSizeMinusOne = misc & 3; |
+ |
+ DVLOG(2) << __FUNCTION__ << " numOfArrays=" << (int)numOfArrays; |
+ arrays.resize(numOfArrays); |
+ for (uint32 j = 0; j < numOfArrays; j++) { |
+ RCHECK(reader->Read1(&arrays[j].first_byte)); |
+ uint16 numNalus = 0; |
+ RCHECK(reader->Read2(&numNalus)); |
+ arrays[j].units.resize(numNalus); |
+ for (uint32 i = 0; i < numNalus; ++i) { |
+ uint16 naluLength = 0; |
+ RCHECK(reader->Read2(&naluLength) && |
+ reader->ReadVec(&arrays[j].units[i], naluLength)); |
+ DVLOG(4) << __FUNCTION__ << " naluType=" |
+ << (int)(arrays[j].first_byte & 0x3f) |
+ << " size=" << arrays[j].units[i].size(); |
+ } |
+ } |
+ |
+ if (!log_cb.is_null()) { |
+ MEDIA_LOG(log_cb) << "Video codec: hevc"; |
+ } |
+ |
+ return true; |
+} |
+#endif |
+ |
PixelAspectRatioBox::PixelAspectRatioBox() : h_spacing(1), v_spacing(1) {} |
PixelAspectRatioBox::~PixelAspectRatioBox() {} |
FourCC PixelAspectRatioBox::BoxType() const { return FOURCC_PASP; } |
@@ -457,16 +561,50 @@ bool VideoSampleEntry::Parse(BoxReader* reader) { |
} |
} |
- if (IsFormatValid()) |
- RCHECK(reader->ReadChild(&avcc)); |
+ VideoCodec codec = kUnknownVideoCodec; |
+ VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
+ if ((format == FOURCC_AVC1 || format == FOURCC_AVC3) || |
+ (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 || |
+ sinf.format.format == FOURCC_AVC3))) { |
+ DVLOG(2) << __FUNCTION__ |
+ << " reading AVCDecoderConfigurationRecord (avcC)"; |
+ RCHECK(reader->ReadChild(&avcConfig)); |
+ codec = kCodecH264; |
+ profile = H264PROFILE_MAIN; |
+#if defined(ENABLE_HEVC_DEMUXING) |
+ } else if ((format == FOURCC_HEV1 || format == FOURCC_HVC1) || |
+ (format == FOURCC_ENCV && (sinf.format.format == FOURCC_HEV1 || |
+ sinf.format.format == FOURCC_HVC1))) { |
+ DVLOG(2) << __FUNCTION__ |
+ << " parsing HEVCDecoderConfigurationRecord (hvcC)"; |
+ RCHECK(reader->ReadChild(&hevcConfig)); |
+ codec = kCodecHEVC; |
+#endif |
+ } else { |
+ // Unknown/unsupported format |
+ MEDIA_LOG(reader->log_cb()) << __FUNCTION__ << " unsupported video format " |
+ << FourCCToString(format); |
+ return false; |
+ } |
+ // TODO(strobe): Recover correct crop box |
+ gfx::Size coded_size(width, height); |
+ gfx::Rect visible_rect(coded_size); |
+ gfx::Size natural_size = GetNaturalSize(visible_rect.size(), |
+ pixel_aspect.h_spacing, |
+ pixel_aspect.v_spacing); |
+ bool is_encrypted = sinf.info.track_encryption.is_encrypted; |
+ video_decoder_config_.Initialize( |
+ codec, profile, VideoFrame::YV12, |
+ coded_size, visible_rect, natural_size, |
+ // No decoder-specific buffer needed. |
+ // Decoder parameters (SPS/PPS) are embedded in the video stream. |
+ NULL, 0, is_encrypted, false); |
return true; |
} |
-bool VideoSampleEntry::IsFormatValid() const { |
- return format == FOURCC_AVC1 || format == FOURCC_AVC3 || |
- (format == FOURCC_ENCV && (sinf.format.format == FOURCC_AVC1 || |
- sinf.format.format == FOURCC_AVC3)); |
+VideoDecoderConfig VideoSampleEntry::GetVideoDecoderConfig() const { |
+ return video_decoder_config_; |
} |
ElementaryStreamDescriptor::ElementaryStreamDescriptor() |