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

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: Add kCodecHEVC in media/base/android/demuxer_stream_player_params.cc Created 5 years, 5 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 240 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(ERROR, log_cb_) << "Unsupported video format 0x" << std::hex 286 MEDIA_LOG(ERROR, log_cb_) << "Unsupported video format 0x" << std::hex
283 << entry.format << " in stsd box."; 287 << 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 VideoFrame::COLOR_SPACE_UNSPECIFIED, coded_size,
297 visible_rect, natural_size,
298 // No decoder-specific buffer needed for AVC;
299 // SPS/PPS are embedded in the video stream
300 NULL, 0, is_video_track_encrypted_, false);
301 has_video_ = true; 293 has_video_ = true;
302 video_track_id_ = track->header.track_id; 294 video_track_id_ = track->header.track_id;
303 } 295 }
304 } 296 }
305 297
306 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap())); 298 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap()));
307 299
308 StreamParser::InitParameters params(kInfiniteDuration()); 300 StreamParser::InitParameters params(kInfiniteDuration());
309 if (moov_->extends.header.fragment_duration > 0) { 301 if (moov_->extends.header.fragment_duration > 0) {
310 params.duration = TimeDeltaFromRational( 302 params.duration = TimeDeltaFromRational(
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of 387 // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of
396 // a frame. If subsample info is present, we also update the clear byte 388 // a frame. If subsample info is present, we also update the clear byte
397 // count for that first subsample. 389 // count for that first subsample.
398 RCHECK(AVC::InsertParamSetsAnnexB(avc_config, frame_buf, subsamples)); 390 RCHECK(AVC::InsertParamSetsAnnexB(avc_config, frame_buf, subsamples));
399 } 391 }
400 392
401 DCHECK(AVC::IsValidAnnexB(*frame_buf, *subsamples)); 393 DCHECK(AVC::IsValidAnnexB(*frame_buf, *subsamples));
402 return true; 394 return true;
403 } 395 }
404 396
397 #if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING)
398 bool MP4StreamParser::PrepareHEVCBuffer(
399 const HEVCDecoderConfigurationRecord& hevc_config,
400 std::vector<uint8>* frame_buf,
401 std::vector<SubsampleEntry>* subsamples) const {
402 DVLOG(2) << __FUNCTION__ << " size=" << frame_buf->size();
403 RCHECK(AVC::ConvertFrameToAnnexB(hevc_config.lengthSizeMinusOne + 1,
404 frame_buf));
405 if (!subsamples->empty()) {
406 const int nalu_size_diff = 4 - (hevc_config.lengthSizeMinusOne + 1);
407 size_t expected_size = runs_->sample_size() +
408 subsamples->size() * nalu_size_diff;
409 RCHECK(frame_buf->size() == expected_size);
410 for (size_t i = 0; i < subsamples->size(); i++)
411 (*subsamples)[i].clear_bytes += nalu_size_diff;
412 }
413
414 if (runs_->is_keyframe()) {
415 // If this is a keyframe, we (re-)inject HEVC params headers at the start of
416 // a frame. If subsample info is present, we also update the clear byte
417 // count for that first subsample.
418 RCHECK(HEVC::InsertParamSetsAnnexB(hevc_config, frame_buf, subsamples));
419 }
420
421 DCHECK(HEVC::IsValidAnnexB(*frame_buf, *subsamples));
422 return true;
423 }
424 #endif
425
405 bool MP4StreamParser::PrepareAACBuffer( 426 bool MP4StreamParser::PrepareAACBuffer(
406 const AAC& aac_config, std::vector<uint8>* frame_buf, 427 const AAC& aac_config, std::vector<uint8>* frame_buf,
407 std::vector<SubsampleEntry>* subsamples) const { 428 std::vector<SubsampleEntry>* subsamples) const {
408 // Append an ADTS header to every audio sample. 429 // Append an ADTS header to every audio sample.
409 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf)); 430 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf));
410 431
411 // As above, adjust subsample information to account for the headers. AAC is 432 // As above, adjust subsample information to account for the headers. AAC is
412 // not required to use subsample encryption, so we may need to add an entry. 433 // not required to use subsample encryption, so we may need to add an entry.
413 if (subsamples->empty()) { 434 if (subsamples->empty()) {
414 subsamples->push_back(SubsampleEntry( 435 subsamples->push_back(SubsampleEntry(
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 decrypt_config = runs_->GetDecryptConfig(); 506 decrypt_config = runs_->GetDecryptConfig();
486 if (!decrypt_config) { 507 if (!decrypt_config) {
487 *err = true; 508 *err = true;
488 return false; 509 return false;
489 } 510 }
490 subsamples = decrypt_config->subsamples(); 511 subsamples = decrypt_config->subsamples();
491 } 512 }
492 513
493 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); 514 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size());
494 if (video) { 515 if (video) {
495 if (!PrepareAVCBuffer(runs_->video_description().avcc, 516 VideoCodec codec =
517 runs_->video_description().GetVideoDecoderConfig().codec();
518 if (codec == kCodecH264 &&
519 !PrepareAVCBuffer(runs_->video_description().avcConfig,
496 &frame_buf, &subsamples)) { 520 &frame_buf, &subsamples)) {
497 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AVC sample for decode"; 521 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AVC sample for decode";
498 *err = true; 522 *err = true;
499 return false; 523 return false;
500 } 524 }
525 #if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING)
526 if (codec == kCodecHEVC &&
527 !PrepareHEVCBuffer(runs_->video_description().hevcConfig,
528 &frame_buf, &subsamples)) {
529 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare HEVC sample for decode";
530 *err = true;
531 return false;
532 }
533 #endif
501 } 534 }
502 535
503 if (audio) { 536 if (audio) {
504 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && 537 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) &&
505 !PrepareAACBuffer(runs_->audio_description().esds.aac, 538 !PrepareAACBuffer(runs_->audio_description().esds.aac,
506 &frame_buf, &subsamples)) { 539 &frame_buf, &subsamples)) {
507 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AAC sample for decode"; 540 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AAC sample for decode";
508 *err = true; 541 *err = true;
509 return false; 542 return false;
510 } 543 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 runs.AdvanceSample(); 672 runs.AdvanceSample();
640 } 673 }
641 runs.AdvanceRun(); 674 runs.AdvanceRun();
642 } 675 }
643 676
644 return true; 677 return true;
645 } 678 }
646 679
647 } // namespace mp4 680 } // namespace mp4
648 } // namespace media 681 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698