OLD | NEW |
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" |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 | 155 |
156 // Set up first mdat offset for ReadMDATsUntil(). | 156 // Set up first mdat offset for ReadMDATsUntil(). |
157 mdat_tail_ = queue_.head() + reader->size(); | 157 mdat_tail_ = queue_.head() + reader->size(); |
158 | 158 |
159 // Return early to avoid evicting 'moof' data from queue. Auxiliary info may | 159 // Return early to avoid evicting 'moof' data from queue. Auxiliary info may |
160 // be located anywhere in the file, including inside the 'moof' itself. | 160 // be located anywhere in the file, including inside the 'moof' itself. |
161 // (Since 'default-base-is-moof' is mandated, no data references can come | 161 // (Since 'default-base-is-moof' is mandated, no data references can come |
162 // before the head of the 'moof', so keeping this box around is sufficient.) | 162 // before the head of the 'moof', so keeping this box around is sufficient.) |
163 return !(*err); | 163 return !(*err); |
164 } else { | 164 } else { |
165 MEDIA_LOG(log_cb_) << "Skipping unrecognized top-level box: " | 165 MEDIA_LOG(DEBUG, log_cb_) << "Skipping unrecognized top-level box: " |
166 << FourCCToString(reader->type()); | 166 << FourCCToString(reader->type()); |
167 } | 167 } |
168 | 168 |
169 queue_.Pop(reader->size()); | 169 queue_.Pop(reader->size()); |
170 return !(*err); | 170 return !(*err); |
171 } | 171 } |
172 | 172 |
173 | 173 |
174 bool MP4StreamParser::ParseMoov(BoxReader* reader) { | 174 bool MP4StreamParser::ParseMoov(BoxReader* reader) { |
175 moov_.reset(new Movie); | 175 moov_.reset(new Movie); |
176 RCHECK(moov_->Parse(reader)); | 176 RCHECK(moov_->Parse(reader)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 // It is not uncommon to find otherwise-valid files with incorrect sample | 210 // It is not uncommon to find otherwise-valid files with incorrect sample |
211 // description indices, so we fail gracefully in that case. | 211 // description indices, so we fail gracefully in that case. |
212 if (desc_idx >= samp_descr.audio_entries.size()) | 212 if (desc_idx >= samp_descr.audio_entries.size()) |
213 desc_idx = 0; | 213 desc_idx = 0; |
214 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx]; | 214 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx]; |
215 const AAC& aac = entry.esds.aac; | 215 const AAC& aac = entry.esds.aac; |
216 | 216 |
217 if (!(entry.format == FOURCC_MP4A || | 217 if (!(entry.format == FOURCC_MP4A || |
218 (entry.format == FOURCC_ENCA && | 218 (entry.format == FOURCC_ENCA && |
219 entry.sinf.format.format == FOURCC_MP4A))) { | 219 entry.sinf.format.format == FOURCC_MP4A))) { |
220 MEDIA_LOG(log_cb_) << "Unsupported audio format 0x" | 220 MEDIA_LOG(ERROR, log_cb_) << "Unsupported audio format 0x" << std::hex |
221 << std::hex << entry.format << " in stsd box."; | 221 << entry.format << " in stsd box."; |
222 return false; | 222 return false; |
223 } | 223 } |
224 | 224 |
225 uint8 audio_type = entry.esds.object_type; | 225 uint8 audio_type = entry.esds.object_type; |
226 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type); | 226 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type); |
227 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) { | 227 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) { |
228 MEDIA_LOG(log_cb_) << "audio object type 0x" << std::hex << audio_type | 228 MEDIA_LOG(ERROR, log_cb_) << "audio object type 0x" << std::hex |
229 << " does not match what is specified in the" | 229 << audio_type |
230 << " mimetype."; | 230 << " does not match what is specified in the" |
| 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(log_cb_) << "Unsupported audio object type 0x" << std::hex | 249 MEDIA_LOG(ERROR, log_cb_) << "Unsupported audio object type 0x" |
249 << 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 Loading... |
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(log_cb_) << "Unsupported video format 0x" | 283 MEDIA_LOG(ERROR, log_cb_) << "Unsupported video format 0x" << std::hex |
283 << std::hex << entry.format << " in stsd box."; | 284 << entry.format << " in stsd box."; |
284 return false; | 285 return false; |
285 } | 286 } |
286 | 287 |
287 // TODO(strobe): Recover correct crop box | 288 // TODO(strobe): Recover correct crop box |
288 gfx::Size coded_size(entry.width, entry.height); | 289 gfx::Size coded_size(entry.width, entry.height); |
289 gfx::Rect visible_rect(coded_size); | 290 gfx::Rect visible_rect(coded_size); |
290 gfx::Size natural_size = GetNaturalSize(visible_rect.size(), | 291 gfx::Size natural_size = GetNaturalSize(visible_rect.size(), |
291 entry.pixel_aspect.h_spacing, | 292 entry.pixel_aspect.h_spacing, |
292 entry.pixel_aspect.v_spacing); | 293 entry.pixel_aspect.v_spacing); |
293 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; | 294 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 *err = true; | 475 *err = true; |
475 return false; | 476 return false; |
476 } | 477 } |
477 subsamples = decrypt_config->subsamples(); | 478 subsamples = decrypt_config->subsamples(); |
478 } | 479 } |
479 | 480 |
480 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); | 481 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); |
481 if (video) { | 482 if (video) { |
482 if (!PrepareAVCBuffer(runs_->video_description().avcc, | 483 if (!PrepareAVCBuffer(runs_->video_description().avcc, |
483 &frame_buf, &subsamples)) { | 484 &frame_buf, &subsamples)) { |
484 MEDIA_LOG(log_cb_) << "Failed to prepare AVC sample for decode"; | 485 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AVC sample for decode"; |
485 *err = true; | 486 *err = true; |
486 return false; | 487 return false; |
487 } | 488 } |
488 } | 489 } |
489 | 490 |
490 if (audio) { | 491 if (audio) { |
491 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && | 492 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && |
492 !PrepareAACBuffer(runs_->audio_description().esds.aac, | 493 !PrepareAACBuffer(runs_->audio_description().esds.aac, |
493 &frame_buf, &subsamples)) { | 494 &frame_buf, &subsamples)) { |
494 MEDIA_LOG(log_cb_) << "Failed to prepare AAC sample for decode"; | 495 MEDIA_LOG(ERROR, log_cb_) << "Failed to prepare AAC sample for decode"; |
495 *err = true; | 496 *err = true; |
496 return false; | 497 return false; |
497 } | 498 } |
498 } | 499 } |
499 | 500 |
500 if (decrypt_config) { | 501 if (decrypt_config) { |
501 if (!subsamples.empty()) { | 502 if (!subsamples.empty()) { |
502 // Create a new config with the updated subsamples. | 503 // Create a new config with the updated subsamples. |
503 decrypt_config.reset(new DecryptConfig( | 504 decrypt_config.reset(new DecryptConfig( |
504 decrypt_config->key_id(), | 505 decrypt_config->key_id(), |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 int size = 0; | 576 int size = 0; |
576 queue_.PeekAt(mdat_tail_, &buf, &size); | 577 queue_.PeekAt(mdat_tail_, &buf, &size); |
577 | 578 |
578 FourCC type; | 579 FourCC type; |
579 int box_sz; | 580 int box_sz; |
580 if (!BoxReader::StartTopLevelBox(buf, size, log_cb_, | 581 if (!BoxReader::StartTopLevelBox(buf, size, log_cb_, |
581 &type, &box_sz, &err)) | 582 &type, &box_sz, &err)) |
582 break; | 583 break; |
583 | 584 |
584 if (type != FOURCC_MDAT) { | 585 if (type != FOURCC_MDAT) { |
585 MEDIA_LOG(log_cb_) << "Unexpected box type while parsing MDATs: " | 586 MEDIA_LOG(DEBUG, log_cb_) << "Unexpected box type while parsing MDATs: " |
586 << FourCCToString(type); | 587 << FourCCToString(type); |
587 } | 588 } |
588 mdat_tail_ += box_sz; | 589 mdat_tail_ += box_sz; |
589 } | 590 } |
590 queue_.Trim(std::min(mdat_tail_, upper_bound)); | 591 queue_.Trim(std::min(mdat_tail_, upper_bound)); |
591 return !err; | 592 return !err; |
592 } | 593 } |
593 | 594 |
594 void MP4StreamParser::ChangeState(State new_state) { | 595 void MP4StreamParser::ChangeState(State new_state) { |
595 DVLOG(2) << "Changing state: " << new_state; | 596 DVLOG(2) << "Changing state: " << new_state; |
596 state_ = new_state; | 597 state_ = new_state; |
(...skipping 29 matching lines...) Expand all Loading... |
626 runs.AdvanceSample(); | 627 runs.AdvanceSample(); |
627 } | 628 } |
628 runs.AdvanceRun(); | 629 runs.AdvanceRun(); |
629 } | 630 } |
630 | 631 |
631 return true; | 632 return true; |
632 } | 633 } |
633 | 634 |
634 } // namespace mp4 | 635 } // namespace mp4 |
635 } // namespace media | 636 } // namespace media |
OLD | NEW |