| 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(log_cb_, DEBUG) << "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(log_cb_, ERROR) << "Unsupported audio format 0x" |
| 221 << std::hex << entry.format << " in stsd box."; | 221 << std::hex << entry.format |
| 222 << " in stsd box."; |
| 222 return false; | 223 return false; |
| 223 } | 224 } |
| 224 | 225 |
| 225 uint8 audio_type = entry.esds.object_type; | 226 uint8 audio_type = entry.esds.object_type; |
| 226 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type); | 227 DVLOG(1) << "audio_type " << std::hex << static_cast<int>(audio_type); |
| 227 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) { | 228 if (audio_object_types_.find(audio_type) == audio_object_types_.end()) { |
| 228 MEDIA_LOG(log_cb_) << "audio object type 0x" << std::hex << audio_type | 229 MEDIA_LOG(log_cb_, ERROR) << "audio object type 0x" |
| 229 << " does not match what is specified in the" | 230 << std::hex << audio_type |
| 230 << " mimetype."; | 231 << " does not match what is specified in the" |
| 232 << " mimetype."; |
| 231 return false; | 233 return false; |
| 232 } | 234 } |
| 233 | 235 |
| 234 AudioCodec codec = kUnknownAudioCodec; | 236 AudioCodec codec = kUnknownAudioCodec; |
| 235 ChannelLayout channel_layout = CHANNEL_LAYOUT_NONE; | 237 ChannelLayout channel_layout = CHANNEL_LAYOUT_NONE; |
| 236 int sample_per_second = 0; | 238 int sample_per_second = 0; |
| 237 std::vector<uint8> extra_data; | 239 std::vector<uint8> extra_data; |
| 238 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or | 240 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3 or |
| 239 // supported MPEG2 AAC varients. | 241 // supported MPEG2 AAC varients. |
| 240 if (ESDescriptor::IsAAC(audio_type)) { | 242 if (ESDescriptor::IsAAC(audio_type)) { |
| 241 codec = kCodecAAC; | 243 codec = kCodecAAC; |
| 242 channel_layout = aac.GetChannelLayout(has_sbr_); | 244 channel_layout = aac.GetChannelLayout(has_sbr_); |
| 243 sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_); | 245 sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_); |
| 244 #if defined(OS_ANDROID) | 246 #if defined(OS_ANDROID) |
| 245 extra_data = aac.codec_specific_data(); | 247 extra_data = aac.codec_specific_data(); |
| 246 #endif | 248 #endif |
| 247 } else { | 249 } else { |
| 248 MEDIA_LOG(log_cb_) << "Unsupported audio object type 0x" << std::hex | 250 MEDIA_LOG(log_cb_, ERROR) << "Unsupported audio object type 0x" |
| 249 << audio_type << " in esds."; | 251 << std::hex << audio_type << " in esds."; |
| 250 return false; | 252 return false; |
| 251 } | 253 } |
| 252 | 254 |
| 253 SampleFormat sample_format; | 255 SampleFormat sample_format; |
| 254 if (entry.samplesize == 8) { | 256 if (entry.samplesize == 8) { |
| 255 sample_format = kSampleFormatU8; | 257 sample_format = kSampleFormatU8; |
| 256 } else if (entry.samplesize == 16) { | 258 } else if (entry.samplesize == 16) { |
| 257 sample_format = kSampleFormatS16; | 259 sample_format = kSampleFormatS16; |
| 258 } else if (entry.samplesize == 32) { | 260 } else if (entry.samplesize == 32) { |
| 259 sample_format = kSampleFormatS32; | 261 sample_format = kSampleFormatS32; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 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 if (!entry.IsFormatValid()) { |
| 282 MEDIA_LOG(log_cb_) << "Unsupported video format 0x" | 284 MEDIA_LOG(log_cb_, ERROR) << "Unsupported video format 0x" |
| 283 << std::hex << entry.format << " in stsd box."; | 285 << std::hex << entry.format |
| 286 << " in stsd box."; |
| 284 return false; | 287 return false; |
| 285 } | 288 } |
| 286 | 289 |
| 287 // TODO(strobe): Recover correct crop box | 290 // TODO(strobe): Recover correct crop box |
| 288 gfx::Size coded_size(entry.width, entry.height); | 291 gfx::Size coded_size(entry.width, entry.height); |
| 289 gfx::Rect visible_rect(coded_size); | 292 gfx::Rect visible_rect(coded_size); |
| 290 gfx::Size natural_size = GetNaturalSize(visible_rect.size(), | 293 gfx::Size natural_size = GetNaturalSize(visible_rect.size(), |
| 291 entry.pixel_aspect.h_spacing, | 294 entry.pixel_aspect.h_spacing, |
| 292 entry.pixel_aspect.v_spacing); | 295 entry.pixel_aspect.v_spacing); |
| 293 is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; | 296 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; | 477 *err = true; |
| 475 return false; | 478 return false; |
| 476 } | 479 } |
| 477 subsamples = decrypt_config->subsamples(); | 480 subsamples = decrypt_config->subsamples(); |
| 478 } | 481 } |
| 479 | 482 |
| 480 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); | 483 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); |
| 481 if (video) { | 484 if (video) { |
| 482 if (!PrepareAVCBuffer(runs_->video_description().avcc, | 485 if (!PrepareAVCBuffer(runs_->video_description().avcc, |
| 483 &frame_buf, &subsamples)) { | 486 &frame_buf, &subsamples)) { |
| 484 MEDIA_LOG(log_cb_) << "Failed to prepare AVC sample for decode"; | 487 MEDIA_LOG(log_cb_, ERROR) << "Failed to prepare AVC sample for decode"; |
| 485 *err = true; | 488 *err = true; |
| 486 return false; | 489 return false; |
| 487 } | 490 } |
| 488 } | 491 } |
| 489 | 492 |
| 490 if (audio) { | 493 if (audio) { |
| 491 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && | 494 if (ESDescriptor::IsAAC(runs_->audio_description().esds.object_type) && |
| 492 !PrepareAACBuffer(runs_->audio_description().esds.aac, | 495 !PrepareAACBuffer(runs_->audio_description().esds.aac, |
| 493 &frame_buf, &subsamples)) { | 496 &frame_buf, &subsamples)) { |
| 494 MEDIA_LOG(log_cb_) << "Failed to prepare AAC sample for decode"; | 497 MEDIA_LOG(log_cb_, ERROR) << "Failed to prepare AAC sample for decode"; |
| 495 *err = true; | 498 *err = true; |
| 496 return false; | 499 return false; |
| 497 } | 500 } |
| 498 } | 501 } |
| 499 | 502 |
| 500 if (decrypt_config) { | 503 if (decrypt_config) { |
| 501 if (!subsamples.empty()) { | 504 if (!subsamples.empty()) { |
| 502 // Create a new config with the updated subsamples. | 505 // Create a new config with the updated subsamples. |
| 503 decrypt_config.reset(new DecryptConfig( | 506 decrypt_config.reset(new DecryptConfig( |
| 504 decrypt_config->key_id(), | 507 decrypt_config->key_id(), |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 int size = 0; | 578 int size = 0; |
| 576 queue_.PeekAt(mdat_tail_, &buf, &size); | 579 queue_.PeekAt(mdat_tail_, &buf, &size); |
| 577 | 580 |
| 578 FourCC type; | 581 FourCC type; |
| 579 int box_sz; | 582 int box_sz; |
| 580 if (!BoxReader::StartTopLevelBox(buf, size, log_cb_, | 583 if (!BoxReader::StartTopLevelBox(buf, size, log_cb_, |
| 581 &type, &box_sz, &err)) | 584 &type, &box_sz, &err)) |
| 582 break; | 585 break; |
| 583 | 586 |
| 584 if (type != FOURCC_MDAT) { | 587 if (type != FOURCC_MDAT) { |
| 585 MEDIA_LOG(log_cb_) << "Unexpected box type while parsing MDATs: " | 588 MEDIA_LOG(log_cb_, DEBUG) << "Unexpected box type while parsing MDATs: " |
| 586 << FourCCToString(type); | 589 << FourCCToString(type); |
| 587 } | 590 } |
| 588 mdat_tail_ += box_sz; | 591 mdat_tail_ += box_sz; |
| 589 } | 592 } |
| 590 queue_.Trim(std::min(mdat_tail_, upper_bound)); | 593 queue_.Trim(std::min(mdat_tail_, upper_bound)); |
| 591 return !err; | 594 return !err; |
| 592 } | 595 } |
| 593 | 596 |
| 594 void MP4StreamParser::ChangeState(State new_state) { | 597 void MP4StreamParser::ChangeState(State new_state) { |
| 595 DVLOG(2) << "Changing state: " << new_state; | 598 DVLOG(2) << "Changing state: " << new_state; |
| 596 state_ = new_state; | 599 state_ = new_state; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 626 runs.AdvanceSample(); | 629 runs.AdvanceSample(); |
| 627 } | 630 } |
| 628 runs.AdvanceRun(); | 631 runs.AdvanceRun(); |
| 629 } | 632 } |
| 630 | 633 |
| 631 return true; | 634 return true; |
| 632 } | 635 } |
| 633 | 636 |
| 634 } // namespace mp4 | 637 } // namespace mp4 |
| 635 } // namespace media | 638 } // namespace media |
| OLD | NEW |