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

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

Powered by Google App Engine
This is Rietveld 408576698