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 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 } | 167 } |
168 } | 168 } |
169 RCHECK(desc_idx > 0); | 169 RCHECK(desc_idx > 0); |
170 desc_idx -= 1; // BMFF descriptor index is one-based | 170 desc_idx -= 1; // BMFF descriptor index is one-based |
171 | 171 |
172 if (track->media.handler.type == kAudio && !audio_config.IsValidConfig()) { | 172 if (track->media.handler.type == kAudio && !audio_config.IsValidConfig()) { |
173 RCHECK(!samp_descr.audio_entries.empty()); | 173 RCHECK(!samp_descr.audio_entries.empty()); |
174 | 174 |
175 // It is not uncommon to find otherwise-valid files with incorrect sample | 175 // It is not uncommon to find otherwise-valid files with incorrect sample |
176 // description indices, so we fail gracefully in that case. | 176 // description indices, so we fail gracefully in that case. |
177 if (static_cast<uint32>(desc_idx) >= samp_descr.audio_entries.size()) | 177 if (desc_idx >= samp_descr.audio_entries.size()) |
178 desc_idx = 0; | 178 desc_idx = 0; |
179 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx]; | 179 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx]; |
180 const AAC& aac = entry.esds.aac; | 180 const AAC& aac = entry.esds.aac; |
181 | 181 |
182 // TODO(strobe): We accept all format values, pending clarification on | 182 if (!(entry.format == FOURCC_MP4A || |
183 // the formats used for encrypted media (http://crbug.com/132351). | 183 (entry.format == FOURCC_ENCA && |
184 // RCHECK(entry.format == FOURCC_MP4A || | 184 entry.sinf.format.format == FOURCC_MP4A))) { |
185 // (entry.format == FOURCC_ENCA && | 185 LOG(ERROR) << "Unsupported audio format."; |
186 // entry.sinf.format.format == FOURCC_MP4A)); | 186 return false; |
| 187 } |
| 188 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3. |
| 189 if (entry.esds.object_type != kISO_14496_3) { |
| 190 LOG(ERROR) << "Unsupported audio object type."; |
| 191 return false; |
| 192 } |
| 193 RCHECK(EmitKeyNeeded(entry.sinf.info.track_encryption)); |
187 | 194 |
188 // Check if it is MPEG4 AAC defined in ISO 14496 Part 3. | |
189 RCHECK(entry.esds.object_type == kISO_14496_3); | |
190 audio_config.Initialize(kCodecAAC, entry.samplesize, | 195 audio_config.Initialize(kCodecAAC, entry.samplesize, |
191 aac.channel_layout(), | 196 aac.channel_layout(), |
192 aac.GetOutputSamplesPerSecond(has_sbr_), | 197 aac.GetOutputSamplesPerSecond(has_sbr_), |
193 NULL, 0, false); | 198 NULL, 0, false); |
194 has_audio_ = true; | 199 has_audio_ = true; |
195 audio_track_id_ = track->header.track_id; | 200 audio_track_id_ = track->header.track_id; |
196 } | 201 } |
197 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) { | 202 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) { |
198 RCHECK(!samp_descr.video_entries.empty()); | 203 RCHECK(!samp_descr.video_entries.empty()); |
199 if (static_cast<uint32>(desc_idx) >= samp_descr.video_entries.size()) | 204 if (desc_idx >= samp_descr.video_entries.size()) |
200 desc_idx = 0; | 205 desc_idx = 0; |
201 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx]; | 206 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx]; |
202 | 207 |
203 // RCHECK(entry.format == FOURCC_AVC1 || | 208 if (!(entry.format == FOURCC_AVC1 || |
204 // (entry.format == FOURCC_ENCV && | 209 (entry.format == FOURCC_ENCV && |
205 // entry.sinf.format.format == FOURCC_AVC1)); | 210 entry.sinf.format.format == FOURCC_AVC1))) { |
| 211 LOG(ERROR) << "Unsupported video format."; |
| 212 return false; |
| 213 } |
| 214 RCHECK(EmitKeyNeeded(entry.sinf.info.track_encryption)); |
206 | 215 |
207 // TODO(strobe): Recover correct crop box | 216 // TODO(strobe): Recover correct crop box |
208 video_config.Initialize(kCodecH264, H264PROFILE_MAIN, VideoFrame::YV12, | 217 video_config.Initialize(kCodecH264, H264PROFILE_MAIN, VideoFrame::YV12, |
209 gfx::Size(entry.width, entry.height), | 218 gfx::Size(entry.width, entry.height), |
210 gfx::Rect(0, 0, entry.width, entry.height), | 219 gfx::Rect(0, 0, entry.width, entry.height), |
211 // Framerate of zero is provided to signal that | 220 // Framerate of zero is provided to signal that |
212 // the decoder should trust demuxer timestamps | 221 // the decoder should trust demuxer timestamps |
213 0, 1, | 222 0, 1, |
214 entry.pixel_aspect.h_spacing, | 223 entry.pixel_aspect.h_spacing, |
215 entry.pixel_aspect.v_spacing, | 224 entry.pixel_aspect.v_spacing, |
216 // No decoder-specific buffer needed for AVC; | 225 // No decoder-specific buffer needed for AVC; |
217 // SPS/PPS are embedded in the video stream | 226 // SPS/PPS are embedded in the video stream |
218 NULL, 0, false); | 227 NULL, 0, false); |
219 has_video_ = true; | 228 has_video_ = true; |
220 video_track_id_ = track->header.track_id; | 229 video_track_id_ = track->header.track_id; |
221 } | 230 } |
222 } | 231 } |
223 | 232 |
224 // TODO(strobe): For now, we avoid sending new configs on a new | 233 // TODO(strobe): For now, we avoid sending new configs on a new |
225 // reinitialization segment, and instead simply embed the updated parameter | 234 // reinitialization segment, and instead simply embed the updated parameter |
226 // sets into the video stream. The conditional should be removed when | 235 // sets into the video stream. The conditional should be removed when |
227 // http://crbug.com/122913 is fixed. | 236 // http://crbug.com/122913 is fixed. (We detect whether we've already sent |
| 237 // configs by looking at init_cb_ instead of config_cb_, because init_cb_ |
| 238 // should only be fired once even after that bug is fixed.) |
228 if (!init_cb_.is_null()) | 239 if (!init_cb_.is_null()) |
229 RCHECK(config_cb_.Run(audio_config, video_config)); | 240 RCHECK(config_cb_.Run(audio_config, video_config)); |
230 | 241 |
231 base::TimeDelta duration; | 242 base::TimeDelta duration; |
232 if (moov_->extends.header.fragment_duration > 0) { | 243 if (moov_->extends.header.fragment_duration > 0) { |
233 duration = TimeDeltaFromFrac(moov_->extends.header.fragment_duration, | 244 duration = TimeDeltaFromRational(moov_->extends.header.fragment_duration, |
234 moov_->header.timescale); | 245 moov_->header.timescale); |
235 } else if (moov_->header.duration > 0) { | 246 } else if (moov_->header.duration > 0) { |
236 duration = TimeDeltaFromFrac(moov_->header.duration, | 247 duration = TimeDeltaFromRational(moov_->header.duration, |
237 moov_->header.timescale); | 248 moov_->header.timescale); |
238 } else { | 249 } else { |
239 duration = kInfiniteDuration(); | 250 duration = kInfiniteDuration(); |
240 } | 251 } |
241 | 252 |
242 if (!init_cb_.is_null()) | 253 if (!init_cb_.is_null()) |
243 base::ResetAndReturn(&init_cb_).Run(true, duration); | 254 base::ResetAndReturn(&init_cb_).Run(true, duration); |
244 return true; | 255 return true; |
245 } | 256 } |
246 | 257 |
247 bool MP4StreamParser::ParseMoof(BoxReader* reader) { | 258 bool MP4StreamParser::ParseMoof(BoxReader* reader) { |
248 RCHECK(moov_.get()); // Must already have initialization segment | 259 RCHECK(moov_.get()); // Must already have initialization segment |
249 MovieFragment moof; | 260 MovieFragment moof; |
250 RCHECK(moof.Parse(reader)); | 261 RCHECK(moof.Parse(reader)); |
251 RCHECK(runs_->Init(moof)); | 262 RCHECK(runs_->Init(moof)); |
252 new_segment_cb_.Run(runs_->GetMinDecodeTimestamp()); | 263 new_segment_cb_.Run(runs_->GetMinDecodeTimestamp()); |
253 ChangeState(kEmittingSamples); | 264 ChangeState(kEmittingSamples); |
254 return true; | 265 return true; |
255 } | 266 } |
256 | 267 |
| 268 bool MP4StreamParser::EmitKeyNeeded(const TrackEncryption& track_encryption) { |
| 269 // TODO(strobe): Send the correct value for initData. The format of initData |
| 270 // has not yet been defined; see |
| 271 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17673. |
| 272 if (!track_encryption.is_encrypted) return true; |
| 273 scoped_array<uint8> kid(new uint8[track_encryption.default_kid.size()]); |
| 274 memcpy(kid.get(), &track_encryption.default_kid[0], |
| 275 track_encryption.default_kid.size()); |
| 276 return need_key_cb_.Run(kid.Pass(), track_encryption.default_kid.size()); |
| 277 } |
| 278 |
| 279 bool MP4StreamParser::PrepareAVCBuffer( |
| 280 const AVCDecoderConfigurationRecord& avc_config, |
| 281 std::vector<uint8>* frame_buf, |
| 282 std::vector<SubsampleEntry>* subsamples) const { |
| 283 // Convert the AVC NALU length fields to Annex B headers, as expected by |
| 284 // decoding libraries. Since this may enlarge the size of the buffer, we also |
| 285 // update the clear byte count for each subsample if encryption is used to |
| 286 // account for the difference in size between the length prefix and Annex B |
| 287 // start code. |
| 288 RCHECK(AVC::ConvertFrameToAnnexB(avc_config.length_size, frame_buf)); |
| 289 if (!subsamples->empty()) { |
| 290 const int nalu_size_diff = 4 - avc_config.length_size; |
| 291 size_t expected_size = runs_->sample_size() + |
| 292 subsamples->size() * nalu_size_diff; |
| 293 RCHECK(frame_buf->size() == expected_size); |
| 294 for (size_t i = 0; i < subsamples->size(); i++) |
| 295 (*subsamples)[i].clear_bytes += nalu_size_diff; |
| 296 } |
| 297 |
| 298 if (runs_->is_keyframe()) { |
| 299 // If this is a keyframe, we (re-)inject SPS and PPS headers at the start of |
| 300 // a frame. If subsample info is present, we also update the clear byte |
| 301 // count for that first subsample. |
| 302 std::vector<uint8> param_sets; |
| 303 RCHECK(AVC::ConvertConfigToAnnexB(avc_config, ¶m_sets)); |
| 304 frame_buf->insert(frame_buf->begin(), |
| 305 param_sets.begin(), param_sets.end()); |
| 306 if (!subsamples->empty()) |
| 307 (*subsamples)[0].clear_bytes += param_sets.size(); |
| 308 } |
| 309 return true; |
| 310 } |
| 311 |
257 bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, | 312 bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, |
258 BufferQueue* video_buffers, | 313 BufferQueue* video_buffers, |
259 bool* err) { | 314 bool* err) { |
260 if (!runs_->RunIsValid()) { | 315 if (!runs_->IsRunValid()) { |
261 // Flush any buffers we've gotten in this chunk so that buffers don't | 316 // Flush any buffers we've gotten in this chunk so that buffers don't |
262 // cross NewSegment() calls | 317 // cross NewSegment() calls |
263 *err = !SendAndFlushSamples(audio_buffers, video_buffers); | 318 *err = !SendAndFlushSamples(audio_buffers, video_buffers); |
264 if (*err) return false; | 319 if (*err) return false; |
265 ChangeState(kParsingBoxes); | 320 ChangeState(kParsingBoxes); |
266 return true; | 321 return true; |
267 } | 322 } |
268 | 323 |
269 if (!runs_->SampleIsValid()) { | 324 if (!runs_->IsSampleValid()) { |
270 runs_->AdvanceRun(); | 325 runs_->AdvanceRun(); |
271 return true; | 326 return true; |
272 } | 327 } |
273 | 328 |
274 DCHECK(!(*err)); | 329 DCHECK(!(*err)); |
275 | 330 |
276 const uint8* buf; | 331 const uint8* buf; |
277 int size; | 332 int buf_size; |
278 queue_.Peek(&buf, &size); | 333 queue_.Peek(&buf, &buf_size); |
279 if (!size) return false; | 334 if (!buf_size) return false; |
280 | 335 |
281 bool audio = has_audio_ && audio_track_id_ == runs_->track_id(); | 336 bool audio = has_audio_ && audio_track_id_ == runs_->track_id(); |
282 bool video = has_video_ && video_track_id_ == runs_->track_id(); | 337 bool video = has_video_ && video_track_id_ == runs_->track_id(); |
283 | 338 |
284 // Skip this entire track if it's not one we're interested in | 339 // Skip this entire track if it's not one we're interested in |
285 if (!audio && !video) runs_->AdvanceRun(); | 340 if (!audio && !video) runs_->AdvanceRun(); |
286 | 341 |
287 queue_.PeekAt(runs_->sample_offset() + moof_head_, &buf, &size); | 342 // Attempt to cache the auxiliary information first. Aux info is usually |
288 if (size < runs_->sample_size()) return false; | 343 // placed in a contiguous block before the sample data, rather than being |
| 344 // interleaved. If we didn't cache it, this would require that we retain the |
| 345 // start of the segment buffer while reading samples. Aux info is typically |
| 346 // quite small compared to sample data, so this pattern is useful on |
| 347 // memory-constrained devices where the source buffer consumes a substantial |
| 348 // portion of the total system memory. |
| 349 if (runs_->AuxInfoNeedsToBeCached()) { |
| 350 queue_.PeekAt(runs_->aux_info_offset() + moof_head_, &buf, &buf_size); |
| 351 if (buf_size < runs_->aux_info_size()) return false; |
| 352 *err = !runs_->CacheAuxInfo(buf, buf_size); |
| 353 return !*err; |
| 354 } |
| 355 |
| 356 queue_.PeekAt(runs_->sample_offset() + moof_head_, &buf, &buf_size); |
| 357 if (buf_size < runs_->sample_size()) return false; |
| 358 |
| 359 scoped_ptr<DecryptConfig> decrypt_config; |
| 360 if (runs_->is_encrypted()) |
| 361 decrypt_config = runs_->GetDecryptConfig(); |
289 | 362 |
290 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); | 363 std::vector<uint8> frame_buf(buf, buf + runs_->sample_size()); |
291 if (video) { | 364 if (video) { |
292 const AVCDecoderConfigurationRecord& avc_config = | 365 std::vector<SubsampleEntry> subsamples; |
293 runs_->video_description().avcc; | 366 if (decrypt_config.get()) |
294 RCHECK(AVC::ConvertToAnnexB(avc_config.length_size, &frame_buf)); | 367 subsamples = decrypt_config->subsamples(); |
295 if (runs_->is_keyframe()) | 368 RCHECK(PrepareAVCBuffer(runs_->video_description().avcc, |
296 RCHECK(AVC::InsertParameterSets(avc_config, &frame_buf)); | 369 &frame_buf, &subsamples)); |
| 370 if (!subsamples.empty()) { |
| 371 decrypt_config.reset(new DecryptConfig( |
| 372 decrypt_config->key_id(), |
| 373 decrypt_config->iv(), |
| 374 decrypt_config->checksum(), |
| 375 decrypt_config->data_offset(), |
| 376 subsamples)); |
| 377 } |
297 } | 378 } |
298 | 379 |
299 if (audio) { | 380 if (audio) { |
300 const AAC& aac = runs_->audio_description().esds.aac; | 381 const AAC& aac = runs_->audio_description().esds.aac; |
301 RCHECK(aac.ConvertEsdsToADTS(&frame_buf)); | 382 RCHECK(aac.ConvertEsdsToADTS(&frame_buf)); |
302 } | 383 } |
303 | 384 |
304 scoped_refptr<StreamParserBuffer> stream_buf = | 385 scoped_refptr<StreamParserBuffer> stream_buf = |
305 StreamParserBuffer::CopyFrom(&frame_buf[0], frame_buf.size(), | 386 StreamParserBuffer::CopyFrom(&frame_buf[0], frame_buf.size(), |
306 runs_->is_keyframe()); | 387 runs_->is_keyframe()); |
307 | 388 |
| 389 if (runs_->is_encrypted()) |
| 390 stream_buf->SetDecryptConfig(decrypt_config.Pass()); |
| 391 |
308 stream_buf->SetDuration(runs_->duration()); | 392 stream_buf->SetDuration(runs_->duration()); |
309 stream_buf->SetTimestamp(runs_->cts()); | 393 stream_buf->SetTimestamp(runs_->cts()); |
310 stream_buf->SetDecodeTimestamp(runs_->dts()); | 394 stream_buf->SetDecodeTimestamp(runs_->dts()); |
311 | 395 |
312 DVLOG(3) << "Pushing frame: aud=" << audio | 396 DVLOG(3) << "Pushing frame: aud=" << audio |
313 << ", key=" << runs_->is_keyframe() | 397 << ", key=" << runs_->is_keyframe() |
314 << ", dur=" << runs_->duration().InMilliseconds() | 398 << ", dur=" << runs_->duration().InMilliseconds() |
315 << ", dts=" << runs_->dts().InMilliseconds() | 399 << ", dts=" << runs_->dts().InMilliseconds() |
316 << ", cts=" << runs_->cts().InMilliseconds() | 400 << ", cts=" << runs_->cts().InMilliseconds() |
317 << ", size=" << runs_->sample_size(); | 401 << ", size=" << runs_->sample_size(); |
318 | 402 |
319 if (audio) { | 403 if (audio) { |
320 audio_buffers->push_back(stream_buf); | 404 audio_buffers->push_back(stream_buf); |
321 } else { | 405 } else { |
322 video_buffers->push_back(stream_buf); | 406 video_buffers->push_back(stream_buf); |
323 } | 407 } |
324 | 408 |
325 runs_->AdvanceSample(); | 409 runs_->AdvanceSample(); |
326 return true; | 410 return true; |
327 } | 411 } |
328 | 412 |
329 bool MP4StreamParser::SendAndFlushSamples(BufferQueue* audio_buffers, | 413 bool MP4StreamParser::SendAndFlushSamples(BufferQueue* audio_buffers, |
330 BufferQueue* video_buffers) { | 414 BufferQueue* video_buffers) { |
| 415 bool err = false; |
331 if (!audio_buffers->empty()) { | 416 if (!audio_buffers->empty()) { |
332 if (audio_cb_.is_null() || !audio_cb_.Run(*audio_buffers)) | 417 err |= (audio_cb_.is_null() || !audio_cb_.Run(*audio_buffers)); |
333 return false; | |
334 audio_buffers->clear(); | 418 audio_buffers->clear(); |
335 } | 419 } |
336 if (!video_buffers->empty()) { | 420 if (!video_buffers->empty()) { |
337 if (video_cb_.is_null() || !video_cb_.Run(*video_buffers)) | 421 err |= (video_cb_.is_null() || !video_cb_.Run(*video_buffers)); |
338 return false; | |
339 video_buffers->clear(); | 422 video_buffers->clear(); |
340 } | 423 } |
341 return true; | 424 return !err; |
342 } | 425 } |
343 | 426 |
344 bool MP4StreamParser::ReadMDATsUntil(const int64 tgt_offset) { | 427 bool MP4StreamParser::ReadMDATsUntil(const int64 tgt_offset) { |
345 DCHECK(tgt_offset <= queue_.tail()); | 428 DCHECK(tgt_offset <= queue_.tail()); |
346 | 429 |
347 while (mdat_tail_ < tgt_offset) { | 430 while (mdat_tail_ < tgt_offset) { |
348 const uint8* buf; | 431 const uint8* buf; |
349 int size; | 432 int size; |
350 queue_.PeekAt(mdat_tail_, &buf, &size); | 433 queue_.PeekAt(mdat_tail_, &buf, &size); |
351 | 434 |
(...skipping 14 matching lines...) Expand all Loading... |
366 return true; | 449 return true; |
367 } | 450 } |
368 | 451 |
369 void MP4StreamParser::ChangeState(State new_state) { | 452 void MP4StreamParser::ChangeState(State new_state) { |
370 DVLOG(2) << "Changing state: " << new_state; | 453 DVLOG(2) << "Changing state: " << new_state; |
371 state_ = new_state; | 454 state_ = new_state; |
372 } | 455 } |
373 | 456 |
374 } // namespace mp4 | 457 } // namespace mp4 |
375 } // namespace media | 458 } // namespace media |
OLD | NEW |