Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: media/formats/mp4/mp4_stream_parser.cc

Issue 816353010: Implemented HEVC video demuxing and parsing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added hevc handling in media/base/android/media_codec_bridge.cc Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/formats/mp4/mp4_stream_parser.h" 5 #include "media/formats/mp4/mp4_stream_parser.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
11 #include "media/base/audio_decoder_config.h" 11 #include "media/base/audio_decoder_config.h"
12 #include "media/base/stream_parser_buffer.h" 12 #include "media/base/stream_parser_buffer.h"
13 #include "media/base/text_track_config.h" 13 #include "media/base/text_track_config.h"
14 #include "media/base/video_decoder_config.h" 14 #include "media/base/video_decoder_config.h"
15 #include "media/base/video_util.h"
16 #include "media/formats/mp4/box_definitions.h" 15 #include "media/formats/mp4/box_definitions.h"
17 #include "media/formats/mp4/box_reader.h" 16 #include "media/formats/mp4/box_reader.h"
18 #include "media/formats/mp4/es_descriptor.h" 17 #include "media/formats/mp4/es_descriptor.h"
19 #include "media/formats/mp4/rcheck.h" 18 #include "media/formats/mp4/rcheck.h"
20 #include "media/formats/mpeg/adts_constants.h" 19 #include "media/formats/mpeg/adts_constants.h"
21 20
21 #if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING)
22 #include "media/formats/mp4/hevc.h"
23 #endif
24
22 namespace media { 25 namespace media {
23 namespace mp4 { 26 namespace mp4 {
24 27
25 static const char kCencInitDataType[] = "cenc"; 28 static const char kCencInitDataType[] = "cenc";
26 29
27 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, 30 MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types,
28 bool has_sbr) 31 bool has_sbr)
29 : state_(kWaitingForInit), 32 : state_(kWaitingForInit),
30 moof_head_(0), 33 moof_head_(0),
31 mdat_tail_(0), 34 mdat_tail_(0),
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 0); 274 0);
272 has_audio_ = true; 275 has_audio_ = true;
273 audio_track_id_ = track->header.track_id; 276 audio_track_id_ = track->header.track_id;
274 } 277 }
275 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) { 278 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) {
276 RCHECK(!samp_descr.video_entries.empty()); 279 RCHECK(!samp_descr.video_entries.empty());
277 if (desc_idx >= samp_descr.video_entries.size()) 280 if (desc_idx >= samp_descr.video_entries.size())
278 desc_idx = 0; 281 desc_idx = 0;
279 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx]; 282 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx];
280 283
281 if (!entry.IsFormatValid()) { 284 video_config = entry.GetVideoDecoderConfig();
285 if (!video_config.IsValidConfig()) {
282 MEDIA_LOG(log_cb_) << "Unsupported video format 0x" 286 MEDIA_LOG(log_cb_) << "Unsupported video format 0x"
283 << std::hex << entry.format << " in stsd box."; 287 << std::hex << entry.format << " in stsd box.";
284 return false; 288 return false;
285 } 289 }
286 290
287 // TODO(strobe): Recover correct crop box
288 gfx::Size coded_size(entry.width, entry.height);
289 gfx::Rect visible_rect(coded_size);
290 gfx::Size natural_size = GetNaturalSize(visible_rect.size(),
291 entry.pixel_aspect.h_spacing,
292 entry.pixel_aspect.v_spacing);
293 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; 291 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
294 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_; 292 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_;
295 video_config.Initialize(kCodecH264, H264PROFILE_MAIN, VideoFrame::YV12,
296 coded_size, visible_rect, natural_size,
297 // No decoder-specific buffer needed for AVC;
298 // SPS/PPS are embedded in the video stream
299 NULL, 0, is_video_track_encrypted_, false);
300 has_video_ = true; 293 has_video_ = true;
301 video_track_id_ = track->header.track_id; 294 video_track_id_ = track->header.track_id;
302 } 295 }
303 } 296 }
304 297
305 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap())); 298 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap()));
306 299
307 StreamParser::InitParameters params(kInfiniteDuration()); 300 StreamParser::InitParameters params(kInfiniteDuration());
308 if (moov_->extends.header.fragment_duration > 0) { 301 if (moov_->extends.header.fragment_duration > 0) {
309 params.duration = TimeDeltaFromRational( 302 params.duration = TimeDeltaFromRational(
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of 375 // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of
383 // a frame. If subsample info is present, we also update the clear byte 376 // a frame. If subsample info is present, we also update the clear byte
384 // count for that first subsample. 377 // count for that first subsample.
385 RCHECK(AVC::InsertParamSetsAnnexB(avc_config, frame_buf, subsamples)); 378 RCHECK(AVC::InsertParamSetsAnnexB(avc_config, frame_buf, subsamples));
386 } 379 }
387 380
388 DCHECK(AVC::IsValidAnnexB(*frame_buf, *subsamples)); 381 DCHECK(AVC::IsValidAnnexB(*frame_buf, *subsamples));
389 return true; 382 return true;
390 } 383 }
391 384
385 #if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING)
386 bool MP4StreamParser::PrepareHEVCBuffer(
387 const HEVCDecoderConfigurationRecord& hevc_config,
388 std::vector<uint8>* frame_buf,
389 std::vector<SubsampleEntry>* subsamples) const {
390 DVLOG(2) << __FUNCTION__ << " size=" << frame_buf->size();
391 RCHECK(AVC::ConvertFrameToAnnexB(hevc_config.lengthSizeMinusOne + 1,
392 frame_buf));
393 if (!subsamples->empty()) {
394 const int nalu_size_diff = 4 - (hevc_config.lengthSizeMinusOne + 1);
395 size_t expected_size = runs_->sample_size() +
396 subsamples->size() * nalu_size_diff;
397 RCHECK(frame_buf->size() == expected_size);
398 for (size_t i = 0; i < subsamples->size(); i++)
399 (*subsamples)[i].clear_bytes += nalu_size_diff;
400 }
401
402 if (runs_->is_keyframe()) {
403 // If this is a keyframe, we (re-)inject HEVC params headers at the start of
404 // a frame. If subsample info is present, we also update the clear byte
405 // count for that first subsample.
406 RCHECK(HEVC::InsertParamSetsAnnexB(hevc_config, frame_buf, subsamples));
407 }
408
409 DCHECK(HEVC::IsValidAnnexB(*frame_buf, *subsamples));
410 return true;
411 }
412 #endif
413
392 bool MP4StreamParser::PrepareAACBuffer( 414 bool MP4StreamParser::PrepareAACBuffer(
393 const AAC& aac_config, std::vector<uint8>* frame_buf, 415 const AAC& aac_config, std::vector<uint8>* frame_buf,
394 std::vector<SubsampleEntry>* subsamples) const { 416 std::vector<SubsampleEntry>* subsamples) const {
395 // Append an ADTS header to every audio sample. 417 // Append an ADTS header to every audio sample.
396 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf)); 418 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf));
397 419
398 // As above, adjust subsample information to account for the headers. AAC is 420 // As above, adjust subsample information to account for the headers. AAC is
399 // not required to use subsample encryption, so we may need to add an entry. 421 // not required to use subsample encryption, so we may need to add an entry.
400 if (subsamples->empty()) { 422 if (subsamples->empty()) {
401 subsamples->push_back(SubsampleEntry( 423 subsamples->push_back(SubsampleEntry(
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 decrypt_config = runs_->GetDecryptConfig(); 494 decrypt_config = runs_->GetDecryptConfig();
473 if (!decrypt_config) { 495 if (!decrypt_config) {
474 *err = true; 496 *err = true;
475 return false; 497 return false;
476 } 498 }
477 subsamples = decrypt_config->subsamples(); 499 subsamples = decrypt_config->subsamples();
478 } 500 }
479 501
480 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); 502 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size());
481 if (video) { 503 if (video) {
482 if (!PrepareAVCBuffer(runs_->video_description().avcc, 504 VideoCodec codec =
505 runs_->video_description().GetVideoDecoderConfig().codec();
506 if (codec == kCodecH264 &&
507 !PrepareAVCBuffer(runs_->video_description().avcConfig,
483 &frame_buf, &subsamples)) { 508 &frame_buf, &subsamples)) {
484 MEDIA_LOG(log_cb_) << "Failed to prepare AVC sample for decode"; 509 MEDIA_LOG(log_cb_) << "Failed to prepare AVC sample for decode";
485 *err = true; 510 *err = true;
486 return false; 511 return false;
487 } 512 }
513 #if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING)
514 if (codec == kCodecHEVC &&
515 !PrepareHEVCBuffer(runs_->video_description().hevcConfig,
516 &frame_buf, &subsamples)) {
517 MEDIA_LOG(log_cb_) << "Failed to prepare HEVC sample for decode";
518 *err = true;
519 return false;
520 }
521 #endif
488 } 522 }
489 523
490 if (audio) { 524 if (audio) {
491 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && 525 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) &&
492 !PrepareAACBuffer(runs_->audio_description().esds.aac, 526 !PrepareAACBuffer(runs_->audio_description().esds.aac,
493 &frame_buf, &subsamples)) { 527 &frame_buf, &subsamples)) {
494 MEDIA_LOG(log_cb_) << "Failed to prepare AAC sample for decode"; 528 MEDIA_LOG(log_cb_) << "Failed to prepare AAC sample for decode";
495 *err = true; 529 *err = true;
496 return false; 530 return false;
497 } 531 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 runs.AdvanceSample(); 660 runs.AdvanceSample();
627 } 661 }
628 runs.AdvanceRun(); 662 runs.AdvanceRun();
629 } 663 }
630 664
631 return true; 665 return true;
632 } 666 }
633 667
634 } // namespace mp4 668 } // namespace mp4
635 } // namespace media 669 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698