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