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

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

Issue 1235793005: Deprecate LogCB in favor of using MediaLog (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments and attempt to fix Android compilation 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
« no previous file with comments | « media/formats/mp4/mp4_stream_parser.h ('k') | media/formats/mp4/mp4_stream_parser_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 30 matching lines...) Expand all
41 MP4StreamParser::~MP4StreamParser() {} 41 MP4StreamParser::~MP4StreamParser() {}
42 42
43 void MP4StreamParser::Init( 43 void MP4StreamParser::Init(
44 const InitCB& init_cb, 44 const InitCB& init_cb,
45 const NewConfigCB& config_cb, 45 const NewConfigCB& config_cb,
46 const NewBuffersCB& new_buffers_cb, 46 const NewBuffersCB& new_buffers_cb,
47 bool /* ignore_text_tracks */, 47 bool /* ignore_text_tracks */,
48 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, 48 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
49 const NewMediaSegmentCB& new_segment_cb, 49 const NewMediaSegmentCB& new_segment_cb,
50 const base::Closure& end_of_segment_cb, 50 const base::Closure& end_of_segment_cb,
51 const LogCB& log_cb) { 51 const scoped_refptr<MediaLog>& media_log) {
52 DCHECK_EQ(state_, kWaitingForInit); 52 DCHECK_EQ(state_, kWaitingForInit);
53 DCHECK(init_cb_.is_null()); 53 DCHECK(init_cb_.is_null());
54 DCHECK(!init_cb.is_null()); 54 DCHECK(!init_cb.is_null());
55 DCHECK(!config_cb.is_null()); 55 DCHECK(!config_cb.is_null());
56 DCHECK(!new_buffers_cb.is_null()); 56 DCHECK(!new_buffers_cb.is_null());
57 DCHECK(!encrypted_media_init_data_cb.is_null()); 57 DCHECK(!encrypted_media_init_data_cb.is_null());
58 DCHECK(!end_of_segment_cb.is_null()); 58 DCHECK(!end_of_segment_cb.is_null());
59 59
60 ChangeState(kParsingBoxes); 60 ChangeState(kParsingBoxes);
61 init_cb_ = init_cb; 61 init_cb_ = init_cb;
62 config_cb_ = config_cb; 62 config_cb_ = config_cb;
63 new_buffers_cb_ = new_buffers_cb; 63 new_buffers_cb_ = new_buffers_cb;
64 encrypted_media_init_data_cb_ = encrypted_media_init_data_cb; 64 encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
65 new_segment_cb_ = new_segment_cb; 65 new_segment_cb_ = new_segment_cb;
66 end_of_segment_cb_ = end_of_segment_cb; 66 end_of_segment_cb_ = end_of_segment_cb;
67 log_cb_ = log_cb; 67 media_log_ = media_log;
68 } 68 }
69 69
70 void MP4StreamParser::Reset() { 70 void MP4StreamParser::Reset() {
71 queue_.Reset(); 71 queue_.Reset();
72 runs_.reset(); 72 runs_.reset();
73 moof_head_ = 0; 73 moof_head_ = 0;
74 mdat_tail_ = 0; 74 mdat_tail_ = 0;
75 } 75 }
76 76
77 void MP4StreamParser::Flush() { 77 void MP4StreamParser::Flush() {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 return true; 135 return true;
136 } 136 }
137 137
138 bool MP4StreamParser::ParseBox(bool* err) { 138 bool MP4StreamParser::ParseBox(bool* err) {
139 const uint8* buf; 139 const uint8* buf;
140 int size; 140 int size;
141 queue_.Peek(&buf, &size); 141 queue_.Peek(&buf, &size);
142 if (!size) return false; 142 if (!size) return false;
143 143
144 scoped_ptr<BoxReader> reader( 144 scoped_ptr<BoxReader> reader(
145 BoxReader::ReadTopLevelBox(buf, size, log_cb_, err)); 145 BoxReader::ReadTopLevelBox(buf, size, media_log_, err));
146 if (reader.get() == NULL) return false; 146 if (reader.get() == NULL) return false;
147 147
148 if (reader->type() == FOURCC_MOOV) { 148 if (reader->type() == FOURCC_MOOV) {
149 *err = !ParseMoov(reader.get()); 149 *err = !ParseMoov(reader.get());
150 } else if (reader->type() == FOURCC_MOOF) { 150 } else if (reader->type() == FOURCC_MOOF) {
151 moof_head_ = queue_.head(); 151 moof_head_ = queue_.head();
152 *err = !ParseMoof(reader.get()); 152 *err = !ParseMoof(reader.get());
153 153
154 // Set up first mdat offset for ReadMDATsUntil(). 154 // Set up first mdat offset for ReadMDATsUntil().
155 mdat_tail_ = queue_.head() + reader->size(); 155 mdat_tail_ = queue_.head() + reader->size();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 // It is not uncommon to find otherwise-valid files with incorrect sample 209 // It is not uncommon to find otherwise-valid files with incorrect sample
210 // description indices, so we fail gracefully in that case. 210 // description indices, so we fail gracefully in that case.
211 if (desc_idx >= samp_descr.audio_entries.size()) 211 if (desc_idx >= samp_descr.audio_entries.size())
212 desc_idx = 0; 212 desc_idx = 0;
213 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx]; 213 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx];
214 const AAC& aac = entry.esds.aac; 214 const AAC& aac = entry.esds.aac;
215 215
216 if (!(entry.format == FOURCC_MP4A || 216 if (!(entry.format == FOURCC_MP4A ||
217 (entry.format == FOURCC_ENCA && 217 (entry.format == FOURCC_ENCA &&
218 entry.sinf.format.format == FOURCC_MP4A))) { 218 entry.sinf.format.format == FOURCC_MP4A))) {
219 MEDIA_LOG(ERROR, log_cb_) << "Unsupported audio format 0x" << std::hex 219 MEDIA_LOG(ERROR, media_log_) << "Unsupported audio format 0x"
220 << entry.format << " in stsd box."; 220 << std::hex << entry.format
221 << " in stsd box.";
221 return false; 222 return false;
222 } 223 }
223 224
224 uint8 audio_type = entry.esds.object_type; 225 uint8 audio_type = entry.esds.object_type;
225 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type); 226 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type);
226 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) { 227 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) {
227 MEDIA_LOG(ERROR, log_cb_) << "audio object type 0x" << std::hex 228 MEDIA_LOG(ERROR, media_log_)
228 << audio_type 229 << "audio object type 0x" << std::hex << audio_type
229 << " does not match what is specified in the" 230 << " does not match what is specified in the"
230 << " mimetype."; 231 << " mimetype.";
231 return false; 232 return false;
232 } 233 }
233 234
234 AudioCodec codec = kUnknownAudioCodec; 235 AudioCodec codec = kUnknownAudioCodec;
235 ChannelLayout channel_layout = CHANNEL_LAYOUT_NONE; 236 ChannelLayout channel_layout = CHANNEL_LAYOUT_NONE;
236 int sample_per_second = 0; 237 int sample_per_second = 0;
237 std::vector<uint8> extra_data; 238 std::vector<uint8> extra_data;
238 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or 239 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or
239 // supported MPEG2 AAC varients. 240 // supported MPEG2 AAC varients.
240 if (ESDescriptor::IsAAC(audio_type)) { 241 if (ESDescriptor::IsAAC(audio_type)) {
241 codec = kCodecAAC; 242 codec = kCodecAAC;
242 channel_layout = aac.GetChannelLayout(has_sbr_); 243 channel_layout = aac.GetChannelLayout(has_sbr_);
243 sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_); 244 sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_);
244 #if defined(OS_ANDROID) 245 #if defined(OS_ANDROID)
245 extra_data = aac.codec_specific_data(); 246 extra_data = aac.codec_specific_data();
246 #endif 247 #endif
247 } else { 248 } else {
248 MEDIA_LOG(ERROR, log_cb_) << "Unsupported audio object type 0x" 249 MEDIA_LOG(ERROR, media_log_) << "Unsupported audio object type 0x"
249 << std::hex << audio_type << " in esds."; 250 << std::hex << audio_type << " in esds.";
250 return false; 251 return false;
251 } 252 }
252 253
253 SampleFormat sample_format; 254 SampleFormat sample_format;
254 if (entry.samplesize == 8) { 255 if (entry.samplesize == 8) {
255 sample_format = kSampleFormatU8; 256 sample_format = kSampleFormatU8;
256 } else if (entry.samplesize == 16) { 257 } else if (entry.samplesize == 16) {
257 sample_format = kSampleFormatS16; 258 sample_format = kSampleFormatS16;
258 } else if (entry.samplesize == 32) { 259 } else if (entry.samplesize == 32) {
259 sample_format = kSampleFormatS32; 260 sample_format = kSampleFormatS32;
(...skipping 12 matching lines...) Expand all
272 has_audio_ = true; 273 has_audio_ = true;
273 audio_track_id_ = track->header.track_id; 274 audio_track_id_ = track->header.track_id;
274 } 275 }
275 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) { 276 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) {
276 RCHECK(!samp_descr.video_entries.empty()); 277 RCHECK(!samp_descr.video_entries.empty());
277 if (desc_idx >= samp_descr.video_entries.size()) 278 if (desc_idx >= samp_descr.video_entries.size())
278 desc_idx = 0; 279 desc_idx = 0;
279 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx]; 280 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx];
280 281
281 if (!entry.IsFormatValid()) { 282 if (!entry.IsFormatValid()) {
282 MEDIA_LOG(ERROR, log_cb_) << "Unsupported video format 0x" << std::hex 283 MEDIA_LOG(ERROR, media_log_) << "Unsupported video format 0x"
283 << entry.format << " in stsd box."; 284 << std::hex << entry.format
285 << " in stsd box.";
284 return false; 286 return false;
285 } 287 }
286 288
287 // TODO(strobe): Recover correct crop box 289 // TODO(strobe): Recover correct crop box
288 gfx::Size coded_size(entry.width, entry.height); 290 gfx::Size coded_size(entry.width, entry.height);
289 gfx::Rect visible_rect(coded_size); 291 gfx::Rect visible_rect(coded_size);
290 gfx::Size natural_size = GetNaturalSize(visible_rect.size(), 292 gfx::Size natural_size = GetNaturalSize(visible_rect.size(),
291 entry.pixel_aspect.h_spacing, 293 entry.pixel_aspect.h_spacing,
292 entry.pixel_aspect.v_spacing); 294 entry.pixel_aspect.v_spacing);
293 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; 295 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 OnEncryptedMediaInitData(moov_->pssh); 336 OnEncryptedMediaInitData(moov_->pssh);
335 337
336 return true; 338 return true;
337 } 339 }
338 340
339 bool MP4StreamParser::ParseMoof(BoxReader* reader) { 341 bool MP4StreamParser::ParseMoof(BoxReader* reader) {
340 RCHECK(moov_.get()); // Must already have initialization segment 342 RCHECK(moov_.get()); // Must already have initialization segment
341 MovieFragment moof; 343 MovieFragment moof;
342 RCHECK(moof.Parse(reader)); 344 RCHECK(moof.Parse(reader));
343 if (!runs_) 345 if (!runs_)
344 runs_.reset(new TrackRunIterator(moov_.get(), log_cb_)); 346 runs_.reset(new TrackRunIterator(moov_.get(), media_log_));
345 RCHECK(runs_->Init(moof)); 347 RCHECK(runs_->Init(moof));
346 RCHECK(ComputeHighestEndOffset(moof)); 348 RCHECK(ComputeHighestEndOffset(moof));
347 349
348 if (!moof.pssh.empty()) 350 if (!moof.pssh.empty())
349 OnEncryptedMediaInitData(moof.pssh); 351 OnEncryptedMediaInitData(moof.pssh);
350 352
351 new_segment_cb_.Run(); 353 new_segment_cb_.Run();
352 ChangeState(kWaitingForSampleData); 354 ChangeState(kWaitingForSampleData);
353 return true; 355 return true;
354 } 356 }
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 *err = true; 489 *err = true;
488 return false; 490 return false;
489 } 491 }
490 subsamples = decrypt_config->subsamples(); 492 subsamples = decrypt_config->subsamples();
491 } 493 }
492 494
493 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); 495 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size());
494 if (video) { 496 if (video) {
495 if (!PrepareAVCBuffer(runs_->video_description().avcc, 497 if (!PrepareAVCBuffer(runs_->video_description().avcc,
496 &frame_buf, &subsamples)) { 498 &frame_buf, &subsamples)) {
497 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AVC sample for decode"; 499 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AVC sample for decode";
498 *err = true; 500 *err = true;
499 return false; 501 return false;
500 } 502 }
501 } 503 }
502 504
503 if (audio) { 505 if (audio) {
504 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && 506 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) &&
505 !PrepareAACBuffer(runs_->audio_description().esds.aac, 507 !PrepareAACBuffer(runs_->audio_description().esds.aac,
506 &frame_buf, &subsamples)) { 508 &frame_buf, &subsamples)) {
507 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AAC sample for decode"; 509 MEDIA_LOG(ERROR, media_log_) << "Failed to prepare AAC sample for decode";
508 *err = true; 510 *err = true;
509 return false; 511 return false;
510 } 512 }
511 } 513 }
512 514
513 if (decrypt_config) { 515 if (decrypt_config) {
514 if (!subsamples.empty()) { 516 if (!subsamples.empty()) {
515 // Create a new config with the updated subsamples. 517 // Create a new config with the updated subsamples.
516 decrypt_config.reset(new DecryptConfig( 518 decrypt_config.reset(new DecryptConfig(
517 decrypt_config->key_id(), 519 decrypt_config->key_id(),
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64 max_clear_offset) { 585 bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64 max_clear_offset) {
584 bool err = false; 586 bool err = false;
585 int64 upper_bound = std::min(max_clear_offset, queue_.tail()); 587 int64 upper_bound = std::min(max_clear_offset, queue_.tail());
586 while (mdat_tail_ < upper_bound) { 588 while (mdat_tail_ < upper_bound) {
587 const uint8* buf = NULL; 589 const uint8* buf = NULL;
588 int size = 0; 590 int size = 0;
589 queue_.PeekAt(mdat_tail_, &buf, &size); 591 queue_.PeekAt(mdat_tail_, &buf, &size);
590 592
591 FourCC type; 593 FourCC type;
592 int box_sz; 594 int box_sz;
593 if (!BoxReader::StartTopLevelBox(buf, size, log_cb_, 595 if (!BoxReader::StartTopLevelBox(buf, size, media_log_, &type, &box_sz,
594 &type, &box_sz, &err)) 596 &err))
595 break; 597 break;
596 598
597 if (type != FOURCC_MDAT) { 599 if (type != FOURCC_MDAT) {
598 MEDIA_LOG(DEBUG, log_cb_) << "Unexpected box type while parsing MDATs: " 600 MEDIA_LOG(DEBUG, media_log_)
599 << FourCCToString(type); 601 << "Unexpected box type while parsing MDATs: "
602 << FourCCToString(type);
600 } 603 }
601 mdat_tail_ += box_sz; 604 mdat_tail_ += box_sz;
602 } 605 }
603 queue_.Trim(std::min(mdat_tail_, upper_bound)); 606 queue_.Trim(std::min(mdat_tail_, upper_bound));
604 return !err; 607 return !err;
605 } 608 }
606 609
607 void MP4StreamParser::ChangeState(State new_state) { 610 void MP4StreamParser::ChangeState(State new_state) {
608 DVLOG(2) << "Changing state: " << new_state; 611 DVLOG(2) << "Changing state: " << new_state;
609 state_ = new_state; 612 state_ = new_state;
610 } 613 }
611 614
612 bool MP4StreamParser::HaveEnoughDataToEnqueueSamples() { 615 bool MP4StreamParser::HaveEnoughDataToEnqueueSamples() {
613 DCHECK_EQ(state_, kWaitingForSampleData); 616 DCHECK_EQ(state_, kWaitingForSampleData);
614 // For muxed content, make sure we have data up to |highest_end_offset_| 617 // For muxed content, make sure we have data up to |highest_end_offset_|
615 // so we can ensure proper enqueuing behavior. Otherwise assume we have enough 618 // so we can ensure proper enqueuing behavior. Otherwise assume we have enough
616 // data and allow per sample offset checks to meter sample enqueuing. 619 // data and allow per sample offset checks to meter sample enqueuing.
617 // TODO(acolwell): Fix trun box handling so we don't have to special case 620 // TODO(acolwell): Fix trun box handling so we don't have to special case
618 // muxed content. 621 // muxed content.
619 return !(has_audio_ && has_video_ && 622 return !(has_audio_ && has_video_ &&
620 queue_.tail() < highest_end_offset_ + moof_head_); 623 queue_.tail() < highest_end_offset_ + moof_head_);
621 } 624 }
622 625
623 bool MP4StreamParser::ComputeHighestEndOffset(const MovieFragment& moof) { 626 bool MP4StreamParser::ComputeHighestEndOffset(const MovieFragment& moof) {
624 highest_end_offset_ = 0; 627 highest_end_offset_ = 0;
625 628
626 TrackRunIterator runs(moov_.get(), log_cb_); 629 TrackRunIterator runs(moov_.get(), media_log_);
627 RCHECK(runs.Init(moof)); 630 RCHECK(runs.Init(moof));
628 631
629 while (runs.IsRunValid()) { 632 while (runs.IsRunValid()) {
630 int64 aux_info_end_offset = runs.aux_info_offset() + runs.aux_info_size(); 633 int64 aux_info_end_offset = runs.aux_info_offset() + runs.aux_info_size();
631 if (aux_info_end_offset > highest_end_offset_) 634 if (aux_info_end_offset > highest_end_offset_)
632 highest_end_offset_ = aux_info_end_offset; 635 highest_end_offset_ = aux_info_end_offset;
633 636
634 while (runs.IsSampleValid()) { 637 while (runs.IsSampleValid()) {
635 int64 sample_end_offset = runs.sample_offset() + runs.sample_size(); 638 int64 sample_end_offset = runs.sample_offset() + runs.sample_size();
636 if (sample_end_offset > highest_end_offset_) 639 if (sample_end_offset > highest_end_offset_)
637 highest_end_offset_ = sample_end_offset; 640 highest_end_offset_ = sample_end_offset;
638 641
639 runs.AdvanceSample(); 642 runs.AdvanceSample();
640 } 643 }
641 runs.AdvanceRun(); 644 runs.AdvanceRun();
642 } 645 }
643 646
644 return true; 647 return true;
645 } 648 }
646 649
647 } // namespace mp4 650 } // namespace mp4
648 } // namespace media 651 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/mp4/mp4_stream_parser.h ('k') | media/formats/mp4/mp4_stream_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698