Index: media/formats/mp4/mp4_stream_parser.cc |
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc |
index e6ad09d9171cabcd5fc23b19468ebbb25b7b54e7..319ef2d7bd7a20662a80bb7c07104574ae673996 100644 |
--- a/media/formats/mp4/mp4_stream_parser.cc |
+++ b/media/formats/mp4/mp4_stream_parser.cc |
@@ -12,13 +12,16 @@ |
#include "media/base/stream_parser_buffer.h" |
#include "media/base/text_track_config.h" |
#include "media/base/video_decoder_config.h" |
-#include "media/base/video_util.h" |
#include "media/formats/mp4/box_definitions.h" |
#include "media/formats/mp4/box_reader.h" |
#include "media/formats/mp4/es_descriptor.h" |
#include "media/formats/mp4/rcheck.h" |
#include "media/formats/mpeg/adts_constants.h" |
+#if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING) |
+#include "media/formats/mp4/hevc.h" |
+#endif |
+ |
namespace media { |
namespace mp4 { |
@@ -278,25 +281,15 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { |
desc_idx = 0; |
const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx]; |
- if (!entry.IsFormatValid()) { |
+ video_config = entry.GetVideoDecoderConfig(); |
+ if (!video_config.IsValidConfig()) { |
MEDIA_LOG(log_cb_) << "Unsupported video format 0x" |
<< std::hex << entry.format << " in stsd box."; |
return false; |
} |
- // TODO(strobe): Recover correct crop box |
- gfx::Size coded_size(entry.width, entry.height); |
- gfx::Rect visible_rect(coded_size); |
- gfx::Size natural_size = GetNaturalSize(visible_rect.size(), |
- entry.pixel_aspect.h_spacing, |
- entry.pixel_aspect.v_spacing); |
is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; |
DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_; |
- video_config.Initialize(kCodecH264, H264PROFILE_MAIN, VideoFrame::YV12, |
- coded_size, visible_rect, natural_size, |
- // No decoder-specific buffer needed for AVC; |
- // SPS/PPS are embedded in the video stream |
- NULL, 0, is_video_track_encrypted_, false); |
has_video_ = true; |
video_track_id_ = track->header.track_id; |
} |
@@ -389,6 +382,35 @@ bool MP4StreamParser::PrepareAVCBuffer( |
return true; |
} |
+#if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING) |
+bool MP4StreamParser::PrepareHEVCBuffer( |
+ const HEVCDecoderConfigurationRecord& hevc_config, |
+ std::vector<uint8>* frame_buf, |
+ std::vector<SubsampleEntry>* subsamples) const { |
+ DVLOG(2) << __FUNCTION__ << " size=" << frame_buf->size(); |
+ RCHECK(AVC::ConvertFrameToAnnexB(hevc_config.lengthSizeMinusOne + 1, |
+ frame_buf)); |
+ if (!subsamples->empty()) { |
+ const int nalu_size_diff = 4 - (hevc_config.lengthSizeMinusOne + 1); |
+ size_t expected_size = runs_->sample_size() + |
+ subsamples->size() * nalu_size_diff; |
+ RCHECK(frame_buf->size() == expected_size); |
+ for (size_t i = 0; i < subsamples->size(); i++) |
+ (*subsamples)[i].clear_bytes += nalu_size_diff; |
+ } |
+ |
+ if (runs_->is_keyframe()) { |
+ // If this is a keyframe, we (re-)inject HEVC params headers at the start of |
+ // a frame. If subsample info is present, we also update the clear byte |
+ // count for that first subsample. |
+ RCHECK(HEVC::InsertParamSetsAnnexB(hevc_config, frame_buf, subsamples)); |
+ } |
+ |
+ DCHECK(HEVC::IsValidAnnexB(*frame_buf, *subsamples)); |
+ return true; |
+} |
+#endif |
+ |
bool MP4StreamParser::PrepareAACBuffer( |
const AAC& aac_config, std::vector<uint8>* frame_buf, |
std::vector<SubsampleEntry>* subsamples) const { |
@@ -479,12 +501,24 @@ bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, |
std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); |
if (video) { |
- if (!PrepareAVCBuffer(runs_->video_description().avcc, |
+ VideoCodec codec = |
+ runs_->video_description().GetVideoDecoderConfig().codec(); |
+ if (codec == kCodecH264 && |
+ !PrepareAVCBuffer(runs_->video_description().avcConfig, |
&frame_buf, &subsamples)) { |
MEDIA_LOG(log_cb_) << "Failed to prepare AVC sample for decode"; |
*err = true; |
return false; |
} |
+#if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING) |
+ if (codec == kCodecHEVC && |
+ !PrepareHEVCBuffer(runs_->video_description().hevcConfig, |
+ &frame_buf, &subsamples)) { |
+ MEDIA_LOG(log_cb_) << "Failed to prepare HEVC sample for decode"; |
+ *err = true; |
+ return false; |
+ } |
+#endif |
} |
if (audio) { |