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

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

Issue 1502503004: Remove kuint64max. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@kint8
Patch Set: rebase Created 5 years 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 <limits>
7 #include <vector> 8 #include <vector>
8 9
9 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/time/time.h" 12 #include "base/time/time.h"
12 #include "media/base/audio_decoder_config.h" 13 #include "media/base/audio_decoder_config.h"
13 #include "media/base/stream_parser_buffer.h" 14 #include "media/base/stream_parser_buffer.h"
14 #include "media/base/text_track_config.h" 15 #include "media/base/text_track_config.h"
15 #include "media/base/timestamp_constants.h" 16 #include "media/base/timestamp_constants.h"
16 #include "media/base/video_decoder_config.h" 17 #include "media/base/video_decoder_config.h"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 moof_head_ = 0; 77 moof_head_ = 0;
77 mdat_tail_ = 0; 78 mdat_tail_ = 0;
78 } 79 }
79 80
80 void MP4StreamParser::Flush() { 81 void MP4StreamParser::Flush() {
81 DCHECK_NE(state_, kWaitingForInit); 82 DCHECK_NE(state_, kWaitingForInit);
82 Reset(); 83 Reset();
83 ChangeState(kParsingBoxes); 84 ChangeState(kParsingBoxes);
84 } 85 }
85 86
86 bool MP4StreamParser::Parse(const uint8* buf, int size) { 87 bool MP4StreamParser::Parse(const uint8_t* buf, int size) {
87 DCHECK_NE(state_, kWaitingForInit); 88 DCHECK_NE(state_, kWaitingForInit);
88 89
89 if (state_ == kError) 90 if (state_ == kError)
90 return false; 91 return false;
91 92
92 queue_.Push(buf, size); 93 queue_.Push(buf, size);
93 94
94 BufferQueue audio_buffers; 95 BufferQueue audio_buffers;
95 BufferQueue video_buffers; 96 BufferQueue video_buffers;
96 97
(...skipping 13 matching lines...) Expand all
110 111
111 case kWaitingForSampleData: 112 case kWaitingForSampleData:
112 result = HaveEnoughDataToEnqueueSamples(); 113 result = HaveEnoughDataToEnqueueSamples();
113 if (result) 114 if (result)
114 ChangeState(kEmittingSamples); 115 ChangeState(kEmittingSamples);
115 break; 116 break;
116 117
117 case kEmittingSamples: 118 case kEmittingSamples:
118 result = EnqueueSample(&audio_buffers, &video_buffers, &err); 119 result = EnqueueSample(&audio_buffers, &video_buffers, &err);
119 if (result) { 120 if (result) {
120 int64 max_clear = runs_->GetMaxClearOffset() + moof_head_; 121 int64_t max_clear = runs_->GetMaxClearOffset() + moof_head_;
121 err = !ReadAndDiscardMDATsUntil(max_clear); 122 err = !ReadAndDiscardMDATsUntil(max_clear);
122 } 123 }
123 break; 124 break;
124 } 125 }
125 } while (result && !err); 126 } while (result && !err);
126 127
127 if (!err) 128 if (!err)
128 err = !SendAndFlushSamples(&audio_buffers, &video_buffers); 129 err = !SendAndFlushSamples(&audio_buffers, &video_buffers);
129 130
130 if (err) { 131 if (err) {
131 DLOG(ERROR) << "Error while parsing MP4"; 132 DLOG(ERROR) << "Error while parsing MP4";
132 moov_.reset(); 133 moov_.reset();
133 Reset(); 134 Reset();
134 ChangeState(kError); 135 ChangeState(kError);
135 return false; 136 return false;
136 } 137 }
137 138
138 return true; 139 return true;
139 } 140 }
140 141
141 bool MP4StreamParser::ParseBox(bool* err) { 142 bool MP4StreamParser::ParseBox(bool* err) {
142 const uint8* buf; 143 const uint8_t* buf;
143 int size; 144 int size;
144 queue_.Peek(&buf, &size); 145 queue_.Peek(&buf, &size);
145 if (!size) return false; 146 if (!size) return false;
146 147
147 scoped_ptr<BoxReader> reader( 148 scoped_ptr<BoxReader> reader(
148 BoxReader::ReadTopLevelBox(buf, size, media_log_, err)); 149 BoxReader::ReadTopLevelBox(buf, size, media_log_, err));
149 if (reader.get() == NULL) return false; 150 if (reader.get() == NULL) return false;
150 151
151 if (reader->type() == FOURCC_MOOV) { 152 if (reader->type() == FOURCC_MOOV) {
152 *err = !ParseMoov(reader.get()); 153 *err = !ParseMoov(reader.get());
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 219
219 if (!(entry.format == FOURCC_MP4A || 220 if (!(entry.format == FOURCC_MP4A ||
220 (entry.format == FOURCC_ENCA && 221 (entry.format == FOURCC_ENCA &&
221 entry.sinf.format.format == FOURCC_MP4A))) { 222 entry.sinf.format.format == FOURCC_MP4A))) {
222 MEDIA_LOG(ERROR, media_log_) << "Unsupported audio format 0x" 223 MEDIA_LOG(ERROR, media_log_) << "Unsupported audio format 0x"
223 << std::hex << entry.format 224 << std::hex << entry.format
224 << " in stsd box."; 225 << " in stsd box.";
225 return false; 226 return false;
226 } 227 }
227 228
228 uint8 audio_type = entry.esds.object_type; 229 uint8_t audio_type = entry.esds.object_type;
229 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type); 230 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type);
230 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) { 231 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) {
231 MEDIA_LOG(ERROR, media_log_) 232 MEDIA_LOG(ERROR, media_log_)
232 << "audio object type 0x" << std::hex << audio_type 233 << "audio object type 0x" << std::hex << audio_type
233 << " does not match what is specified in the" 234 << " does not match what is specified in the"
234 << " mimetype."; 235 << " mimetype.";
235 return false; 236 return false;
236 } 237 }
237 238
238 AudioCodec codec = kUnknownAudioCodec; 239 AudioCodec codec = kUnknownAudioCodec;
239 ChannelLayout channel_layout = CHANNEL_LAYOUT_NONE; 240 ChannelLayout channel_layout = CHANNEL_LAYOUT_NONE;
240 int sample_per_second = 0; 241 int sample_per_second = 0;
241 std::vector<uint8> extra_data; 242 std::vector<uint8_t> extra_data;
242 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or 243 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or
243 // supported MPEG2 AAC varients. 244 // supported MPEG2 AAC varients.
244 if (ESDescriptor::IsAAC(audio_type)) { 245 if (ESDescriptor::IsAAC(audio_type)) {
245 codec = kCodecAAC; 246 codec = kCodecAAC;
246 channel_layout = aac.GetChannelLayout(has_sbr_); 247 channel_layout = aac.GetChannelLayout(has_sbr_);
247 sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_); 248 sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_);
248 #if defined(OS_ANDROID) 249 #if defined(OS_ANDROID)
249 extra_data = aac.codec_specific_data(); 250 extra_data = aac.codec_specific_data();
250 #endif 251 #endif
251 } else { 252 } else {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 } 319 }
319 320
320 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap())); 321 RCHECK(config_cb_.Run(audio_config, video_config, TextTrackConfigMap()));
321 322
322 StreamParser::InitParameters params(kInfiniteDuration()); 323 StreamParser::InitParameters params(kInfiniteDuration());
323 if (moov_->extends.header.fragment_duration > 0) { 324 if (moov_->extends.header.fragment_duration > 0) {
324 params.duration = TimeDeltaFromRational( 325 params.duration = TimeDeltaFromRational(
325 moov_->extends.header.fragment_duration, moov_->header.timescale); 326 moov_->extends.header.fragment_duration, moov_->header.timescale);
326 params.liveness = DemuxerStream::LIVENESS_RECORDED; 327 params.liveness = DemuxerStream::LIVENESS_RECORDED;
327 } else if (moov_->header.duration > 0 && 328 } else if (moov_->header.duration > 0 &&
328 moov_->header.duration != kuint64max) { 329 moov_->header.duration != std::numeric_limits<uint64_t>::max()) {
329 params.duration = 330 params.duration =
330 TimeDeltaFromRational(moov_->header.duration, moov_->header.timescale); 331 TimeDeltaFromRational(moov_->header.duration, moov_->header.timescale);
331 params.liveness = DemuxerStream::LIVENESS_RECORDED; 332 params.liveness = DemuxerStream::LIVENESS_RECORDED;
332 } else { 333 } else {
333 // In ISO/IEC 14496-12:2005(E), 8.30.2: ".. If an MP4 file is created in 334 // In ISO/IEC 14496-12:2005(E), 8.30.2: ".. If an MP4 file is created in
334 // real-time, such as used in live streaming, it is not likely that the 335 // real-time, such as used in live streaming, it is not likely that the
335 // fragment_duration is known in advance and this (mehd) box may be 336 // fragment_duration is known in advance and this (mehd) box may be
336 // omitted." 337 // omitted."
337 // TODO(wolenetz): Investigate gating liveness detection on timeline_offset 338 // TODO(wolenetz): Investigate gating liveness detection on timeline_offset
338 // when it's populated. See http://crbug.com/312699 339 // when it's populated. See http://crbug.com/312699
(...skipping 30 matching lines...) Expand all
369 370
370 void MP4StreamParser::OnEncryptedMediaInitData( 371 void MP4StreamParser::OnEncryptedMediaInitData(
371 const std::vector<ProtectionSystemSpecificHeader>& headers) { 372 const std::vector<ProtectionSystemSpecificHeader>& headers) {
372 // TODO(strobe): ensure that the value of init_data (all PSSH headers 373 // TODO(strobe): ensure that the value of init_data (all PSSH headers
373 // concatenated in arbitrary order) matches the EME spec. 374 // concatenated in arbitrary order) matches the EME spec.
374 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=17673. 375 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=17673.
375 size_t total_size = 0; 376 size_t total_size = 0;
376 for (size_t i = 0; i < headers.size(); i++) 377 for (size_t i = 0; i < headers.size(); i++)
377 total_size += headers[i].raw_box.size(); 378 total_size += headers[i].raw_box.size();
378 379
379 std::vector<uint8> init_data(total_size); 380 std::vector<uint8_t> init_data(total_size);
380 size_t pos = 0; 381 size_t pos = 0;
381 for (size_t i = 0; i < headers.size(); i++) { 382 for (size_t i = 0; i < headers.size(); i++) {
382 memcpy(&init_data[pos], &headers[i].raw_box[0], 383 memcpy(&init_data[pos], &headers[i].raw_box[0],
383 headers[i].raw_box.size()); 384 headers[i].raw_box.size());
384 pos += headers[i].raw_box.size(); 385 pos += headers[i].raw_box.size();
385 } 386 }
386 encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data); 387 encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data);
387 } 388 }
388 389
389 bool MP4StreamParser::PrepareAACBuffer( 390 bool MP4StreamParser::PrepareAACBuffer(
390 const AAC& aac_config, std::vector<uint8>* frame_buf, 391 const AAC& aac_config,
392 std::vector<uint8_t>* frame_buf,
391 std::vector<SubsampleEntry>* subsamples) const { 393 std::vector<SubsampleEntry>* subsamples) const {
392 // Append an ADTS header to every audio sample. 394 // Append an ADTS header to every audio sample.
393 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf)); 395 RCHECK(aac_config.ConvertEsdsToADTS(frame_buf));
394 396
395 // As above, adjust subsample information to account for the headers. AAC is 397 // As above, adjust subsample information to account for the headers. AAC is
396 // not required to use subsample encryption, so we may need to add an entry. 398 // not required to use subsample encryption, so we may need to add an entry.
397 if (subsamples->empty()) { 399 if (subsamples->empty()) {
398 subsamples->push_back(SubsampleEntry( 400 subsamples->push_back(SubsampleEntry(
399 kADTSHeaderMinSize, frame_buf->size() - kADTSHeaderMinSize)); 401 kADTSHeaderMinSize, frame_buf->size() - kADTSHeaderMinSize));
400 } else { 402 } else {
(...skipping 24 matching lines...) Expand all
425 return true; 427 return true;
426 } 428 }
427 429
428 if (!runs_->IsSampleValid()) { 430 if (!runs_->IsSampleValid()) {
429 runs_->AdvanceRun(); 431 runs_->AdvanceRun();
430 return true; 432 return true;
431 } 433 }
432 434
433 DCHECK(!(*err)); 435 DCHECK(!(*err));
434 436
435 const uint8* buf; 437 const uint8_t* buf;
436 int buf_size; 438 int buf_size;
437 queue_.Peek(&buf, &buf_size); 439 queue_.Peek(&buf, &buf_size);
438 if (!buf_size) return false; 440 if (!buf_size) return false;
439 441
440 bool audio = has_audio_ && audio_track_id_ == runs_->track_id(); 442 bool audio = has_audio_ && audio_track_id_ == runs_->track_id();
441 bool video = has_video_ && video_track_id_ == runs_->track_id(); 443 bool video = has_video_ && video_track_id_ == runs_->track_id();
442 444
443 // Skip this entire track if it's not one we're interested in 445 // Skip this entire track if it's not one we're interested in
444 if (!audio && !video) { 446 if (!audio && !video) {
445 runs_->AdvanceRun(); 447 runs_->AdvanceRun();
(...skipping 21 matching lines...) Expand all
467 std::vector<SubsampleEntry> subsamples; 469 std::vector<SubsampleEntry> subsamples;
468 if (runs_->is_encrypted()) { 470 if (runs_->is_encrypted()) {
469 decrypt_config = runs_->GetDecryptConfig(); 471 decrypt_config = runs_->GetDecryptConfig();
470 if (!decrypt_config) { 472 if (!decrypt_config) {
471 *err = true; 473 *err = true;
472 return false; 474 return false;
473 } 475 }
474 subsamples = decrypt_config->subsamples(); 476 subsamples = decrypt_config->subsamples();
475 } 477 }
476 478
477 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); 479 std::vector<uint8_t> frame_buf(buf, buf + runs_->sample_size());
478 if (video) { 480 if (video) {
479 DCHECK(runs_->video_description().frame_bitstream_converter); 481 DCHECK(runs_->video_description().frame_bitstream_converter);
480 if (!runs_->video_description().frame_bitstream_converter->ConvertFrame( 482 if (!runs_->video_description().frame_bitstream_converter->ConvertFrame(
481 &frame_buf, runs_->is_keyframe(), &subsamples)) { 483 &frame_buf, runs_->is_keyframe(), &subsamples)) {
482 MEDIA_LOG(ERROR, media_log_) 484 MEDIA_LOG(ERROR, media_log_)
483 << "Failed to prepare video sample for decode"; 485 << "Failed to prepare video sample for decode";
484 *err = true; 486 *err = true;
485 return false; 487 return false;
486 } 488 }
487 } 489 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 557
556 TextBufferQueueMap empty_text_map; 558 TextBufferQueueMap empty_text_map;
557 bool success = new_buffers_cb_.Run(*audio_buffers, 559 bool success = new_buffers_cb_.Run(*audio_buffers,
558 *video_buffers, 560 *video_buffers,
559 empty_text_map); 561 empty_text_map);
560 audio_buffers->clear(); 562 audio_buffers->clear();
561 video_buffers->clear(); 563 video_buffers->clear();
562 return success; 564 return success;
563 } 565 }
564 566
565 bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64 max_clear_offset) { 567 bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64_t max_clear_offset) {
566 bool err = false; 568 bool err = false;
567 int64 upper_bound = std::min(max_clear_offset, queue_.tail()); 569 int64_t upper_bound = std::min(max_clear_offset, queue_.tail());
568 while (mdat_tail_ < upper_bound) { 570 while (mdat_tail_ < upper_bound) {
569 const uint8* buf = NULL; 571 const uint8_t* buf = NULL;
570 int size = 0; 572 int size = 0;
571 queue_.PeekAt(mdat_tail_, &buf, &size); 573 queue_.PeekAt(mdat_tail_, &buf, &size);
572 574
573 FourCC type; 575 FourCC type;
574 int box_sz; 576 int box_sz;
575 if (!BoxReader::StartTopLevelBox(buf, size, media_log_, &type, &box_sz, 577 if (!BoxReader::StartTopLevelBox(buf, size, media_log_, &type, &box_sz,
576 &err)) 578 &err))
577 break; 579 break;
578 580
579 if (type != FOURCC_MDAT) { 581 if (type != FOURCC_MDAT) {
(...skipping 23 matching lines...) Expand all
603 queue_.tail() < highest_end_offset_ + moof_head_); 605 queue_.tail() < highest_end_offset_ + moof_head_);
604 } 606 }
605 607
606 bool MP4StreamParser::ComputeHighestEndOffset(const MovieFragment& moof) { 608 bool MP4StreamParser::ComputeHighestEndOffset(const MovieFragment& moof) {
607 highest_end_offset_ = 0; 609 highest_end_offset_ = 0;
608 610
609 TrackRunIterator runs(moov_.get(), media_log_); 611 TrackRunIterator runs(moov_.get(), media_log_);
610 RCHECK(runs.Init(moof)); 612 RCHECK(runs.Init(moof));
611 613
612 while (runs.IsRunValid()) { 614 while (runs.IsRunValid()) {
613 int64 aux_info_end_offset = runs.aux_info_offset() + runs.aux_info_size(); 615 int64_t aux_info_end_offset = runs.aux_info_offset() + runs.aux_info_size();
614 if (aux_info_end_offset > highest_end_offset_) 616 if (aux_info_end_offset > highest_end_offset_)
615 highest_end_offset_ = aux_info_end_offset; 617 highest_end_offset_ = aux_info_end_offset;
616 618
617 while (runs.IsSampleValid()) { 619 while (runs.IsSampleValid()) {
618 int64 sample_end_offset = runs.sample_offset() + runs.sample_size(); 620 int64_t sample_end_offset = runs.sample_offset() + runs.sample_size();
619 if (sample_end_offset > highest_end_offset_) 621 if (sample_end_offset > highest_end_offset_)
620 highest_end_offset_ = sample_end_offset; 622 highest_end_offset_ = sample_end_offset;
621 623
622 runs.AdvanceSample(); 624 runs.AdvanceSample();
623 } 625 }
624 runs.AdvanceRun(); 626 runs.AdvanceRun();
625 } 627 }
626 628
627 return true; 629 return true;
628 } 630 }
629 631
630 } // namespace mp4 632 } // namespace mp4
631 } // namespace media 633 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698