OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/mp4/mp4_stream_parser.h" | 5 #include "media/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.h" | 10 #include "base/time.h" |
(...skipping 24 matching lines...) Expand all Loading... |
35 } | 35 } |
36 | 36 |
37 MP4StreamParser::~MP4StreamParser() {} | 37 MP4StreamParser::~MP4StreamParser() {} |
38 | 38 |
39 void MP4StreamParser::Init(const InitCB& init_cb, | 39 void MP4StreamParser::Init(const InitCB& init_cb, |
40 const NewConfigCB& config_cb, | 40 const NewConfigCB& config_cb, |
41 const NewBuffersCB& audio_cb, | 41 const NewBuffersCB& audio_cb, |
42 const NewBuffersCB& video_cb, | 42 const NewBuffersCB& video_cb, |
43 const NeedKeyCB& need_key_cb, | 43 const NeedKeyCB& need_key_cb, |
44 const NewMediaSegmentCB& new_segment_cb, | 44 const NewMediaSegmentCB& new_segment_cb, |
45 const base::Closure& end_of_segment_cb) { | 45 const base::Closure& end_of_segment_cb, |
| 46 const LogCB& log_cb) { |
46 DCHECK_EQ(state_, kWaitingForInit); | 47 DCHECK_EQ(state_, kWaitingForInit); |
47 DCHECK(init_cb_.is_null()); | 48 DCHECK(init_cb_.is_null()); |
48 DCHECK(!init_cb.is_null()); | 49 DCHECK(!init_cb.is_null()); |
49 DCHECK(!config_cb.is_null()); | 50 DCHECK(!config_cb.is_null()); |
50 DCHECK(!audio_cb.is_null() || !video_cb.is_null()); | 51 DCHECK(!audio_cb.is_null() || !video_cb.is_null()); |
51 DCHECK(!need_key_cb.is_null()); | 52 DCHECK(!need_key_cb.is_null()); |
52 DCHECK(!end_of_segment_cb.is_null()); | 53 DCHECK(!end_of_segment_cb.is_null()); |
53 | 54 |
54 ChangeState(kParsingBoxes); | 55 ChangeState(kParsingBoxes); |
55 init_cb_ = init_cb; | 56 init_cb_ = init_cb; |
56 config_cb_ = config_cb; | 57 config_cb_ = config_cb; |
57 audio_cb_ = audio_cb; | 58 audio_cb_ = audio_cb; |
58 video_cb_ = video_cb; | 59 video_cb_ = video_cb; |
59 need_key_cb_ = need_key_cb; | 60 need_key_cb_ = need_key_cb; |
60 new_segment_cb_ = new_segment_cb; | 61 new_segment_cb_ = new_segment_cb; |
61 end_of_segment_cb_ = end_of_segment_cb; | 62 end_of_segment_cb_ = end_of_segment_cb; |
| 63 log_cb_ = log_cb; |
62 } | 64 } |
63 | 65 |
64 void MP4StreamParser::Reset() { | 66 void MP4StreamParser::Reset() { |
65 queue_.Reset(); | 67 queue_.Reset(); |
66 moov_.reset(); | 68 moov_.reset(); |
67 runs_.reset(); | 69 runs_.reset(); |
68 moof_head_ = 0; | 70 moof_head_ = 0; |
69 mdat_tail_ = 0; | 71 mdat_tail_ = 0; |
70 } | 72 } |
71 | 73 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 115 |
114 return true; | 116 return true; |
115 } | 117 } |
116 | 118 |
117 bool MP4StreamParser::ParseBox(bool* err) { | 119 bool MP4StreamParser::ParseBox(bool* err) { |
118 const uint8* buf; | 120 const uint8* buf; |
119 int size; | 121 int size; |
120 queue_.Peek(&buf, &size); | 122 queue_.Peek(&buf, &size); |
121 if (!size) return false; | 123 if (!size) return false; |
122 | 124 |
123 scoped_ptr<BoxReader> reader(BoxReader::ReadTopLevelBox(buf, size, err)); | 125 scoped_ptr<BoxReader> reader( |
| 126 BoxReader::ReadTopLevelBox(buf, size, log_cb_, err)); |
124 if (reader.get() == NULL) return false; | 127 if (reader.get() == NULL) return false; |
125 | 128 |
126 if (reader->type() == FOURCC_MOOV) { | 129 if (reader->type() == FOURCC_MOOV) { |
127 *err = !ParseMoov(reader.get()); | 130 *err = !ParseMoov(reader.get()); |
128 } else if (reader->type() == FOURCC_MOOF) { | 131 } else if (reader->type() == FOURCC_MOOF) { |
129 moof_head_ = queue_.head(); | 132 moof_head_ = queue_.head(); |
130 *err = !ParseMoof(reader.get()); | 133 *err = !ParseMoof(reader.get()); |
131 | 134 |
132 // Set up first mdat offset for ReadMDATsUntil(). | 135 // Set up first mdat offset for ReadMDATsUntil(). |
133 mdat_tail_ = queue_.head() + reader->size(); | 136 mdat_tail_ = queue_.head() + reader->size(); |
134 | 137 |
135 // Return early to avoid evicting 'moof' data from queue. Auxiliary info may | 138 // Return early to avoid evicting 'moof' data from queue. Auxiliary info may |
136 // be located anywhere in the file, including inside the 'moof' itself. | 139 // be located anywhere in the file, including inside the 'moof' itself. |
137 // (Since 'default-base-is-moof' is mandated, no data references can come | 140 // (Since 'default-base-is-moof' is mandated, no data references can come |
138 // before the head of the 'moof', so keeping this box around is sufficient.) | 141 // before the head of the 'moof', so keeping this box around is sufficient.) |
139 return !(*err); | 142 return !(*err); |
140 } else { | 143 } else { |
141 DVLOG(2) << "Skipping unrecognized top-level box: " | 144 MEDIA_LOG(log_cb_) << "Skipping unrecognized top-level box: " |
142 << FourCCToString(reader->type()); | 145 << FourCCToString(reader->type()); |
143 } | 146 } |
144 | 147 |
145 queue_.Pop(reader->size()); | 148 queue_.Pop(reader->size()); |
146 return !(*err); | 149 return !(*err); |
147 } | 150 } |
148 | 151 |
149 | 152 |
150 bool MP4StreamParser::ParseMoov(BoxReader* reader) { | 153 bool MP4StreamParser::ParseMoov(BoxReader* reader) { |
151 moov_.reset(new Movie); | 154 moov_.reset(new Movie); |
152 RCHECK(moov_->Parse(reader)); | 155 RCHECK(moov_->Parse(reader)); |
153 runs_.reset(new TrackRunIterator(moov_.get())); | 156 runs_.reset(new TrackRunIterator(moov_.get(), log_cb_)); |
154 | 157 |
155 has_audio_ = false; | 158 has_audio_ = false; |
156 has_video_ = false; | 159 has_video_ = false; |
157 | 160 |
158 AudioDecoderConfig audio_config; | 161 AudioDecoderConfig audio_config; |
159 VideoDecoderConfig video_config; | 162 VideoDecoderConfig video_config; |
160 | 163 |
161 for (std::vector<Track>::const_iterator track = moov_->tracks.begin(); | 164 for (std::vector<Track>::const_iterator track = moov_->tracks.begin(); |
162 track != moov_->tracks.end(); ++track) { | 165 track != moov_->tracks.end(); ++track) { |
163 // TODO(strobe): Only the first audio and video track present in a file are | 166 // TODO(strobe): Only the first audio and video track present in a file are |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 std::vector<SubsampleEntry> subsamples; | 408 std::vector<SubsampleEntry> subsamples; |
406 if (runs_->is_encrypted()) { | 409 if (runs_->is_encrypted()) { |
407 decrypt_config = runs_->GetDecryptConfig(); | 410 decrypt_config = runs_->GetDecryptConfig(); |
408 subsamples = decrypt_config->subsamples(); | 411 subsamples = decrypt_config->subsamples(); |
409 } | 412 } |
410 | 413 |
411 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); | 414 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); |
412 if (video) { | 415 if (video) { |
413 if (!PrepareAVCBuffer(runs_->video_description().avcc, | 416 if (!PrepareAVCBuffer(runs_->video_description().avcc, |
414 &frame_buf, &subsamples)) { | 417 &frame_buf, &subsamples)) { |
415 DLOG(ERROR) << "Failed to prepare AVC sample for decode"; | 418 MEDIA_LOG(log_cb_) << "Failed to prepare AVC sample for decode"; |
416 *err = true; | 419 *err = true; |
417 return false; | 420 return false; |
418 } | 421 } |
419 } | 422 } |
420 | 423 |
421 if (audio) { | 424 if (audio) { |
422 if (!PrepareAACBuffer(runs_->audio_description().esds.aac, | 425 if (!PrepareAACBuffer(runs_->audio_description().esds.aac, |
423 &frame_buf, &subsamples)) { | 426 &frame_buf, &subsamples)) { |
424 DLOG(ERROR) << "Failed to prepare AAC sample for decode"; | 427 MEDIA_LOG(log_cb_) << "Failed to prepare AAC sample for decode"; |
425 *err = true; | 428 *err = true; |
426 return false; | 429 return false; |
427 } | 430 } |
428 } | 431 } |
429 | 432 |
430 if (decrypt_config.get() != NULL && !subsamples.empty()) { | 433 if (decrypt_config.get() != NULL && !subsamples.empty()) { |
431 decrypt_config.reset(new DecryptConfig( | 434 decrypt_config.reset(new DecryptConfig( |
432 decrypt_config->key_id(), | 435 decrypt_config->key_id(), |
433 decrypt_config->iv(), | 436 decrypt_config->iv(), |
434 decrypt_config->data_offset(), | 437 decrypt_config->data_offset(), |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 | 482 |
480 bool MP4StreamParser::ReadAndDiscardMDATsUntil(const int64 offset) { | 483 bool MP4StreamParser::ReadAndDiscardMDATsUntil(const int64 offset) { |
481 bool err = false; | 484 bool err = false; |
482 while (mdat_tail_ < offset) { | 485 while (mdat_tail_ < offset) { |
483 const uint8* buf; | 486 const uint8* buf; |
484 int size; | 487 int size; |
485 queue_.PeekAt(mdat_tail_, &buf, &size); | 488 queue_.PeekAt(mdat_tail_, &buf, &size); |
486 | 489 |
487 FourCC type; | 490 FourCC type; |
488 int box_sz; | 491 int box_sz; |
489 if (!BoxReader::StartTopLevelBox(buf, size, &type, &box_sz, &err)) | 492 if (!BoxReader::StartTopLevelBox(buf, size, log_cb_, |
| 493 &type, &box_sz, &err)) |
490 break; | 494 break; |
491 | 495 |
492 if (type != FOURCC_MDAT) { | 496 if (type != FOURCC_MDAT) { |
493 DLOG(WARNING) << "Unexpected box type while parsing MDATs: " | 497 MEDIA_LOG(log_cb_) << "Unexpected box type while parsing MDATs: " |
494 << FourCCToString(type); | 498 << FourCCToString(type); |
495 } | 499 } |
496 mdat_tail_ += box_sz; | 500 mdat_tail_ += box_sz; |
497 } | 501 } |
498 queue_.Trim(std::min(mdat_tail_, offset)); | 502 queue_.Trim(std::min(mdat_tail_, offset)); |
499 return !err; | 503 return !err; |
500 } | 504 } |
501 | 505 |
502 void MP4StreamParser::ChangeState(State new_state) { | 506 void MP4StreamParser::ChangeState(State new_state) { |
503 DVLOG(2) << "Changing state: " << new_state; | 507 DVLOG(2) << "Changing state: " << new_state; |
504 state_ = new_state; | 508 state_ = new_state; |
505 } | 509 } |
506 | 510 |
507 } // namespace mp4 | 511 } // namespace mp4 |
508 } // namespace media | 512 } // namespace media |
OLD | NEW |