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/filters/ffmpeg_video_decoder.h" | 5 #include "media/filters/ffmpeg_video_decoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 void FFmpegVideoDecoder::ReadFromDemuxerStream() { | 275 void FFmpegVideoDecoder::ReadFromDemuxerStream() { |
276 DCHECK_NE(state_, kUninitialized); | 276 DCHECK_NE(state_, kUninitialized); |
277 DCHECK_NE(state_, kDecodeFinished); | 277 DCHECK_NE(state_, kDecodeFinished); |
278 DCHECK(!read_cb_.is_null()); | 278 DCHECK(!read_cb_.is_null()); |
279 | 279 |
280 demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::DecryptOrDecodeBuffer, | 280 demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::DecryptOrDecodeBuffer, |
281 this)); | 281 this)); |
282 } | 282 } |
283 | 283 |
284 void FFmpegVideoDecoder::DecryptOrDecodeBuffer( | 284 void FFmpegVideoDecoder::DecryptOrDecodeBuffer( |
| 285 DemuxerStream::Status status, |
285 const scoped_refptr<DecoderBuffer>& buffer) { | 286 const scoped_refptr<DecoderBuffer>& buffer) { |
| 287 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; |
286 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read | 288 // TODO(scherkus): fix FFmpegDemuxerStream::Read() to not execute our read |
287 // callback on the same execution stack so we can get rid of forced task post. | 289 // callback on the same execution stack so we can get rid of forced task post. |
288 message_loop_->PostTask(FROM_HERE, base::Bind( | 290 message_loop_->PostTask(FROM_HERE, base::Bind( |
289 &FFmpegVideoDecoder::DoDecryptOrDecodeBuffer, this, buffer)); | 291 &FFmpegVideoDecoder::DoDecryptOrDecodeBuffer, this, status, buffer)); |
290 } | 292 } |
291 | 293 |
292 void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer( | 294 void FFmpegVideoDecoder::DoDecryptOrDecodeBuffer( |
| 295 DemuxerStream::Status status, |
293 const scoped_refptr<DecoderBuffer>& buffer) { | 296 const scoped_refptr<DecoderBuffer>& buffer) { |
294 DCHECK_EQ(MessageLoop::current(), message_loop_); | 297 DCHECK_EQ(MessageLoop::current(), message_loop_); |
295 DCHECK_NE(state_, kUninitialized); | 298 DCHECK_NE(state_, kUninitialized); |
296 DCHECK_NE(state_, kDecodeFinished); | 299 DCHECK_NE(state_, kDecodeFinished); |
297 DCHECK(!read_cb_.is_null()); | 300 DCHECK(!read_cb_.is_null()); |
298 | 301 |
299 if (!reset_cb_.is_null()) { | 302 if (!reset_cb_.is_null()) { |
300 DeliverFrame(NULL); | 303 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
301 DoReset(); | 304 DoReset(); |
302 return; | 305 return; |
303 } | 306 } |
304 | 307 |
305 if (!buffer) { | 308 if (status != DemuxerStream::kOk) { |
306 DeliverFrame(NULL); | 309 DecoderStatus decoder_status = |
| 310 (status == DemuxerStream::kAborted) ? kOk : kDecodeError; |
| 311 base::ResetAndReturn(&read_cb_).Run(decoder_status, NULL); |
307 return; | 312 return; |
308 } | 313 } |
309 | 314 |
| 315 DCHECK_EQ(status, DemuxerStream::kOk); |
| 316 |
310 if (buffer->GetDecryptConfig() && buffer->GetDataSize()) { | 317 if (buffer->GetDecryptConfig() && buffer->GetDataSize()) { |
311 decryptor_->Decrypt(buffer, | 318 decryptor_->Decrypt(buffer, |
312 base::Bind(&FFmpegVideoDecoder::BufferDecrypted, this)); | 319 base::Bind(&FFmpegVideoDecoder::BufferDecrypted, this)); |
313 return; | 320 return; |
314 } | 321 } |
315 | 322 |
316 DecodeBuffer(buffer); | 323 DecodeBuffer(buffer); |
317 } | 324 } |
318 | 325 |
319 void FFmpegVideoDecoder::BufferDecrypted( | 326 void FFmpegVideoDecoder::BufferDecrypted( |
320 Decryptor::DecryptStatus decrypt_status, | 327 Decryptor::DecryptStatus decrypt_status, |
321 const scoped_refptr<DecoderBuffer>& buffer) { | 328 const scoped_refptr<DecoderBuffer>& buffer) { |
322 message_loop_->PostTask(FROM_HERE, base::Bind( | 329 message_loop_->PostTask(FROM_HERE, base::Bind( |
323 &FFmpegVideoDecoder::DoBufferDecrypted, this, decrypt_status, buffer)); | 330 &FFmpegVideoDecoder::DoBufferDecrypted, this, decrypt_status, buffer)); |
324 } | 331 } |
325 | 332 |
326 void FFmpegVideoDecoder::DoBufferDecrypted( | 333 void FFmpegVideoDecoder::DoBufferDecrypted( |
327 Decryptor::DecryptStatus decrypt_status, | 334 Decryptor::DecryptStatus decrypt_status, |
328 const scoped_refptr<DecoderBuffer>& buffer) { | 335 const scoped_refptr<DecoderBuffer>& buffer) { |
329 DCHECK_EQ(MessageLoop::current(), message_loop_); | 336 DCHECK_EQ(MessageLoop::current(), message_loop_); |
330 DCHECK_NE(state_, kUninitialized); | 337 DCHECK_NE(state_, kUninitialized); |
331 DCHECK_NE(state_, kDecodeFinished); | 338 DCHECK_NE(state_, kDecodeFinished); |
332 DCHECK(!read_cb_.is_null()); | 339 DCHECK(!read_cb_.is_null()); |
333 | 340 |
334 if (!reset_cb_.is_null()) { | 341 if (!reset_cb_.is_null()) { |
335 DeliverFrame(NULL); | 342 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
336 DoReset(); | 343 DoReset(); |
337 return; | 344 return; |
338 } | 345 } |
339 | 346 |
340 if (decrypt_status == Decryptor::kError) { | 347 if (decrypt_status == Decryptor::kError) { |
341 state_ = kDecodeFinished; | 348 state_ = kDecodeFinished; |
342 base::ResetAndReturn(&read_cb_).Run(kDecryptError, NULL); | 349 base::ResetAndReturn(&read_cb_).Run(kDecryptError, NULL); |
343 return; | 350 return; |
344 } | 351 } |
345 | 352 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 PipelineStatistics statistics; | 408 PipelineStatistics statistics; |
402 statistics.video_bytes_decoded = buffer->GetDataSize(); | 409 statistics.video_bytes_decoded = buffer->GetDataSize(); |
403 statistics_cb_.Run(statistics); | 410 statistics_cb_.Run(statistics); |
404 } | 411 } |
405 | 412 |
406 // If we didn't get a frame then we've either completely finished decoding or | 413 // If we didn't get a frame then we've either completely finished decoding or |
407 // we need more data. | 414 // we need more data. |
408 if (!video_frame) { | 415 if (!video_frame) { |
409 if (state_ == kFlushCodec) { | 416 if (state_ == kFlushCodec) { |
410 state_ = kDecodeFinished; | 417 state_ = kDecodeFinished; |
411 DeliverFrame(VideoFrame::CreateEmptyFrame()); | 418 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); |
412 return; | 419 return; |
413 } | 420 } |
414 | 421 |
415 ReadFromDemuxerStream(); | 422 ReadFromDemuxerStream(); |
416 return; | 423 return; |
417 } | 424 } |
418 | 425 |
419 DeliverFrame(video_frame); | 426 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); |
420 } | 427 } |
421 | 428 |
422 bool FFmpegVideoDecoder::Decode( | 429 bool FFmpegVideoDecoder::Decode( |
423 const scoped_refptr<DecoderBuffer>& buffer, | 430 const scoped_refptr<DecoderBuffer>& buffer, |
424 scoped_refptr<VideoFrame>* video_frame) { | 431 scoped_refptr<VideoFrame>* video_frame) { |
425 DCHECK(video_frame); | 432 DCHECK(video_frame); |
426 | 433 |
427 // Create a packet for input data. | 434 // Create a packet for input data. |
428 // Due to FFmpeg API changes we no longer have const read-only pointers. | 435 // Due to FFmpeg API changes we no longer have const read-only pointers. |
429 AVPacket packet; | 436 AVPacket packet; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 doubled_time_base.den = frame_rate_numerator_ * 2; | 511 doubled_time_base.den = frame_rate_numerator_ * 2; |
505 | 512 |
506 (*video_frame)->SetTimestamp( | 513 (*video_frame)->SetTimestamp( |
507 base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque)); | 514 base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque)); |
508 (*video_frame)->SetDuration( | 515 (*video_frame)->SetDuration( |
509 ConvertFromTimeBase(doubled_time_base, 2 + av_frame_->repeat_pict)); | 516 ConvertFromTimeBase(doubled_time_base, 2 + av_frame_->repeat_pict)); |
510 | 517 |
511 return true; | 518 return true; |
512 } | 519 } |
513 | 520 |
514 void FFmpegVideoDecoder::DeliverFrame( | |
515 const scoped_refptr<VideoFrame>& video_frame) { | |
516 // Reset the callback before running to protect against reentrancy. | |
517 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); | |
518 } | |
519 | |
520 void FFmpegVideoDecoder::ReleaseFFmpegResources() { | 521 void FFmpegVideoDecoder::ReleaseFFmpegResources() { |
521 if (codec_context_) { | 522 if (codec_context_) { |
522 av_free(codec_context_->extradata); | 523 av_free(codec_context_->extradata); |
523 avcodec_close(codec_context_); | 524 avcodec_close(codec_context_); |
524 av_free(codec_context_); | 525 av_free(codec_context_); |
525 codec_context_ = NULL; | 526 codec_context_ = NULL; |
526 } | 527 } |
527 if (av_frame_) { | 528 if (av_frame_) { |
528 av_free(av_frame_); | 529 av_free(av_frame_); |
529 av_frame_ = NULL; | 530 av_frame_ = NULL; |
530 } | 531 } |
531 } | 532 } |
532 | 533 |
533 } // namespace media | 534 } // namespace media |
OLD | NEW |