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

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

Powered by Google App Engine
This is Rietveld 408576698