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

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: CR feedback Created 5 years, 6 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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 0); 279 0);
277 has_audio_ = true; 280 has_audio_ = true;
278 audio_track_id_ = track->header.track_id; 281 audio_track_id_ = track->header.track_id;
279 } 282 }
280 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) { 283 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) {
281 RCHECK(!samp_descr.video_entries.empty()); 284 RCHECK(!samp_descr.video_entries.empty());
282 if (desc_idx >= samp_descr.video_entries.size()) 285 if (desc_idx >= samp_descr.video_entries.size())
283 desc_idx = 0; 286 desc_idx = 0;
284 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx]; 287 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx];
285 288
286 if (!entry.IsFormatValid()) { 289 video_config = entry.GetVideoDecoderConfig();
290 if (!video_config.IsValidConfig()) {
287 MEDIA_LOG(ERROR, log_cb_) << "Unsupported video format 0x" << std::hex 291 MEDIA_LOG(ERROR, log_cb_) << "Unsupported video format 0x" << std::hex
288 << entry.format << " in stsd box."; 292 << entry.format << " in stsd box.";
289 return false; 293 return false;
290 } 294 }
291 295
292 // TODO(strobe): Recover correct crop box
293 gfx::Size coded_size(entry.width, entry.height);
294 gfx::Rect visible_rect(coded_size);
295 gfx::Size natural_size = GetNaturalSize(visible_rect.size(),
296 entry.pixel_aspect.h_spacing,
297 entry.pixel_aspect.v_spacing);
298 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; 296 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
299 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_; 297 DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_;
300 video_config.Initialize(kCodecH264, H264PROFILE_MAIN, VideoFrame::YV12,
301 VideoFrame::COLOR_SPACE_UNSPECIFIED, coded_size,
302 visible_rect, natural_size,
303 // No decoder-specific buffer needed for AVC;
304 // SPS/PPS are embedded in the video stream
305 NULL, 0, is_video_track_encrypted_, false);
306 has_video_ = true; 298 has_video_ = true;
307 video_track_id_ = track->header.track_id; 299 video_track_id_ = track->header.track_id;
308 } 300 }
309 } 301 }
310 302
311 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap())); 303 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap()));
312 304
313 StreamParser::InitParameters params(kInfiniteDuration()); 305 StreamParser::InitParameters params(kInfiniteDuration());
314 if (moov_->extends.header.fragment_duration > 0) { 306 if (moov_->extends.header.fragment_duration > 0) {
315 params.duration = TimeDeltaFromRational( 307 params.duration = TimeDeltaFromRational(
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of 392 // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of
401 // a frame. If subsample info is present, we also update the clear byte 393 // a frame. If subsample info is present, we also update the clear byte
402 // count for that first subsample. 394 // count for that first subsample.
403 RCHECK(AVC::InsertParamSetsAnnexB(avc_config, frame_buf, subsamples)); 395 RCHECK(AVC::InsertParamSetsAnnexB(avc_config, frame_buf, subsamples));
404 } 396 }
405 397
406 DCHECK(AVC::IsValidAnnexB(*frame_buf, *subsamples)); 398 DCHECK(AVC::IsValidAnnexB(*frame_buf, *subsamples));
407 return true; 399 return true;
408 } 400 }
409 401
402 #if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING)
403 bool MP4StreamParser::PrepareHEVCBuffer(
404 const HEVCDecoderConfigurationRecord& hevc_config,
405 std::vector<uint8>* frame_buf,
406 std::vector<SubsampleEntry>* subsamples) const {
407 DVLOG(2) << __FUNCTION__ << " size=" << frame_buf->size();
408 RCHECK(AVC::ConvertFrameToAnnexB(hevc_config.lengthSizeMinusOne + 1,
409 frame_buf));
410 if (!subsamples->empty()) {
411 const int nalu_size_diff = 4 - (hevc_config.lengthSizeMinusOne + 1);
412 size_t expected_size = runs_->sample_size() +
413 subsamples->size() * nalu_size_diff;
414 RCHECK(frame_buf->size() == expected_size);
415 for (size_t i = 0; i < subsamples->size(); i++)
416 (*subsamples)[i].clear_bytes += nalu_size_diff;
417 }
418
419 if (runs_->is_keyframe()) {
420 // If this is a keyframe, we (re-)inject HEVC params headers at the start of
421 // a frame. If subsample info is present, we also update the clear byte
422 // count for that first subsample.
423 RCHECK(HEVC::InsertParamSetsAnnexB(hevc_config, frame_buf, subsamples));
424 }
425
426 DCHECK(HEVC::IsValidAnnexB(*frame_buf, *subsamples));
427 return true;
428 }
429 #endif
430
410 bool MP4StreamParser::PrepareAACBuffer( 431 bool MP4StreamParser::PrepareAACBuffer(
411 const AAC& aac_config, std::vector<uint8>* frame_buf, 432 const AAC& aac_config, std::vector<uint8>* frame_buf,
412 std::vector<SubsampleEntry>* subsamples) const { 433 std::vector<SubsampleEntry>* subsamples) const {
413 // Append an ADTS header to every audio sample. 434 // Append an ADTS header to every audio sample.
414 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf)); 435 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf));
415 436
416 // As above, adjust subsample information to account for the headers. AAC is 437 // As above, adjust subsample information to account for the headers. AAC is
417 // not required to use subsample encryption, so we may need to add an entry. 438 // not required to use subsample encryption, so we may need to add an entry.
418 if (subsamples->empty()) { 439 if (subsamples->empty()) {
419 subsamples->push_back(SubsampleEntry( 440 subsamples->push_back(SubsampleEntry(
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 decrypt_config = runs_->GetDecryptConfig(); 511 decrypt_config = runs_->GetDecryptConfig();
491 if (!decrypt_config) { 512 if (!decrypt_config) {
492 *err = true; 513 *err = true;
493 return false; 514 return false;
494 } 515 }
495 subsamples = decrypt_config->subsamples(); 516 subsamples = decrypt_config->subsamples();
496 } 517 }
497 518
498 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); 519 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size());
499 if (video) { 520 if (video) {
500 if (!PrepareAVCBuffer(runs_->video_description().avcc, 521 VideoCodec codec =
522 runs_->video_description().GetVideoDecoderConfig().codec();
523 if (codec == kCodecH264 &&
524 !PrepareAVCBuffer(runs_->video_description().avcConfig,
501 &frame_buf, &subsamples)) { 525 &frame_buf, &subsamples)) {
502 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AVC sample for decode"; 526 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AVC sample for decode";
503 *err = true; 527 *err = true;
504 return false; 528 return false;
505 } 529 }
530 #if defined(USE_PROPRIETARY_CODECS) && defined(ENABLE_HEVC_DEMUXING)
531 if (codec == kCodecHEVC &&
532 !PrepareHEVCBuffer(runs_->video_description().hevcConfig,
533 &frame_buf, &subsamples)) {
534 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare HEVC sample for decode";
535 *err = true;
536 return false;
537 }
538 #endif
506 } 539 }
507 540
508 if (audio) { 541 if (audio) {
509 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && 542 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) &&
510 !PrepareAACBuffer(runs_->audio_description().esds.aac, 543 !PrepareAACBuffer(runs_->audio_description().esds.aac,
511 &frame_buf, &subsamples)) { 544 &frame_buf, &subsamples)) {
512 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AAC sample for decode"; 545 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AAC sample for decode";
513 *err = true; 546 *err = true;
514 return false; 547 return false;
515 } 548 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 runs.AdvanceSample(); 677 runs.AdvanceSample();
645 } 678 }
646 runs.AdvanceRun(); 679 runs.AdvanceRun();
647 } 680 }
648 681
649 return true; 682 return true;
650 } 683 }
651 684
652 } // namespace mp4 685 } // namespace mp4
653 } // namespace media 686 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698