Chromium Code Reviews| Index: media/filters/ffmpeg_video_decoder.cc |
| diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc |
| index 7fc80885d474546d33ad5a0676906a02b2d546df..6bcbdabc8b8b5911b12f1e2b192affabb494dee5 100644 |
| --- a/media/filters/ffmpeg_video_decoder.cc |
| +++ b/media/filters/ffmpeg_video_decoder.cc |
| @@ -83,6 +83,8 @@ int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, |
| scoped_refptr<VideoFrame> video_frame = |
| VideoFrame::CreateFrame(format, width, height, |
| + natural_size_.width(), |
| + natural_size_.height(), |
| kNoTimestamp(), kNoTimestamp()); |
| for (int i = 0; i < 3; i++) { |
| @@ -158,34 +160,13 @@ void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, |
| return; |
| } |
| - // Initialize AVCodecContext structure. |
| - codec_context_ = avcodec_alloc_context3(NULL); |
| - VideoDecoderConfigToAVCodecContext(config, codec_context_); |
| - |
| - // Enable motion vector search (potentially slow), strong deblocking filter |
| - // for damaged macroblocks, and set our error detection sensitivity. |
| - codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; |
| - codec_context_->err_recognition = AV_EF_CAREFUL; |
| - codec_context_->thread_count = GetThreadCount(codec_context_->codec_id); |
| - codec_context_->opaque = this; |
| - codec_context_->flags |= CODEC_FLAG_EMU_EDGE; |
| - codec_context_->get_buffer = GetVideoBufferImpl; |
| - codec_context_->release_buffer = ReleaseVideoBufferImpl; |
| - |
| - AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
| - if (!codec) { |
| - status_cb.Run(PIPELINE_ERROR_DECODE); |
| - return; |
| - } |
| - |
| - if (avcodec_open2(codec_context_, codec, NULL) < 0) { |
| + if (!AllocateFFmpegResources(config)) { |
|
Ami GONE FROM CHROMIUM
2012/07/13 00:59:05
I wonder if it doesn't make sense to inline AFFMR(
|
| status_cb.Run(PIPELINE_ERROR_DECODE); |
| return; |
| } |
| // Success! |
| state_ = kNormal; |
| - av_frame_ = avcodec_alloc_frame(); |
| natural_size_ = config.natural_size(); |
| frame_rate_numerator_ = config.frame_rate_numerator(); |
| frame_rate_denominator_ = config.frame_rate_denominator(); |
|
Ami GONE FROM CHROMIUM
2012/07/13 00:59:05
...in which case these can go away
|
| @@ -301,10 +282,18 @@ void FFmpegVideoDecoder::DoDecodeBuffer( |
| return; |
| } |
| - if (status != DemuxerStream::kOk) { |
| - DecoderStatus decoder_status = |
| - (status == DemuxerStream::kAborted) ? kOk : kDecodeError; |
| - base::ResetAndReturn(&read_cb_).Run(decoder_status, NULL); |
| + if (status == DemuxerStream::kAborted) { |
| + base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| + return; |
| + } |
| + |
| + if (status == DemuxerStream::kConfigChanged) { |
| + if (!HandleConfigChange()) { |
| + base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| + return; |
| + } |
| + |
| + ReadFromDemuxerStream(); |
| return; |
| } |
| @@ -477,6 +466,36 @@ void FFmpegVideoDecoder::DeliverFrame( |
| base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); |
| } |
| +bool FFmpegVideoDecoder::AllocateFFmpegResources( |
| + const VideoDecoderConfig& config) { |
| + DCHECK(!codec_context_); |
| + DCHECK(!av_frame_); |
| + |
| + // Initialize AVCodecContext structure. |
| + codec_context_ = avcodec_alloc_context3(NULL); |
| + VideoDecoderConfigToAVCodecContext(config, codec_context_); |
| + |
| + // Enable motion vector search (potentially slow), strong deblocking filter |
| + // for damaged macroblocks, and set our error detection sensitivity. |
| + codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; |
| + codec_context_->err_recognition = AV_EF_CAREFUL; |
| + codec_context_->thread_count = GetThreadCount(codec_context_->codec_id); |
| + codec_context_->opaque = this; |
| + codec_context_->flags |= CODEC_FLAG_EMU_EDGE; |
| + codec_context_->get_buffer = GetVideoBufferImpl; |
| + codec_context_->release_buffer = ReleaseVideoBufferImpl; |
| + |
| + AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
| + if (!codec) |
| + return false; |
| + |
| + if (avcodec_open2(codec_context_, codec, NULL) < 0) |
| + return false; |
| + |
| + av_frame_ = avcodec_alloc_frame(); |
| + return true; |
| +} |
| + |
| void FFmpegVideoDecoder::ReleaseFFmpegResources() { |
| if (codec_context_) { |
| av_free(codec_context_->extradata); |
| @@ -490,4 +509,20 @@ void FFmpegVideoDecoder::ReleaseFFmpegResources() { |
| } |
| } |
| +bool FFmpegVideoDecoder::HandleConfigChange() { |
| + const VideoDecoderConfig& config = demuxer_stream_->video_decoder_config(); |
| + |
| + if (!config.IsValidConfig()) |
| + return false; |
| + |
| + ReleaseFFmpegResources(); |
| + if (!AllocateFFmpegResources(config)) |
| + return false; |
| + |
| + natural_size_ = config.natural_size(); |
| + frame_rate_numerator_ = config.frame_rate_numerator(); |
| + frame_rate_denominator_ = config.frame_rate_denominator(); |
| + return true; |
| +} |
| + |
| } // namespace media |