| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 return decode_threads; | 51 return decode_threads; |
| 52 | 52 |
| 53 decode_threads = std::max(decode_threads, 0); | 53 decode_threads = std::max(decode_threads, 0); |
| 54 decode_threads = std::min(decode_threads, kMaxDecodeThreads); | 54 decode_threads = std::min(decode_threads, kMaxDecodeThreads); |
| 55 return decode_threads; | 55 return decode_threads; |
| 56 } | 56 } |
| 57 | 57 |
| 58 FFmpegVideoDecoder::FFmpegVideoDecoder( | 58 FFmpegVideoDecoder::FFmpegVideoDecoder( |
| 59 const scoped_refptr<base::MessageLoopProxy>& message_loop) | 59 const scoped_refptr<base::MessageLoopProxy>& message_loop) |
| 60 : message_loop_(message_loop), | 60 : message_loop_(message_loop), |
| 61 weak_factory_(this), |
| 61 state_(kUninitialized), | 62 state_(kUninitialized), |
| 62 codec_context_(NULL), | 63 codec_context_(NULL), |
| 63 av_frame_(NULL) { | 64 av_frame_(NULL) { |
| 64 } | 65 } |
| 65 | 66 |
| 66 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, | 67 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, |
| 67 AVFrame* frame) { | 68 AVFrame* frame) { |
| 68 // Don't use |codec_context_| here! With threaded decoding, | 69 // Don't use |codec_context_| here! With threaded decoding, |
| 69 // it will contain unsynchronized width/height/pix_fmt values, | 70 // it will contain unsynchronized width/height/pix_fmt values, |
| 70 // whereas |codec_context| contains the current threads's | 71 // whereas |codec_context| contains the current threads's |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 // this callback | 128 // this callback |
| 128 memset(frame->data, 0, sizeof(frame->data)); | 129 memset(frame->data, 0, sizeof(frame->data)); |
| 129 frame->opaque = NULL; | 130 frame->opaque = NULL; |
| 130 } | 131 } |
| 131 | 132 |
| 132 void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, | 133 void FFmpegVideoDecoder::Initialize(const scoped_refptr<DemuxerStream>& stream, |
| 133 const PipelineStatusCB& status_cb, | 134 const PipelineStatusCB& status_cb, |
| 134 const StatisticsCB& statistics_cb) { | 135 const StatisticsCB& statistics_cb) { |
| 135 DCHECK(message_loop_->BelongsToCurrentThread()); | 136 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 136 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 137 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
| 138 weak_this_ = weak_factory_.GetWeakPtr(); |
| 137 | 139 |
| 138 FFmpegGlue::InitializeFFmpeg(); | 140 FFmpegGlue::InitializeFFmpeg(); |
| 139 DCHECK(!demuxer_stream_) << "Already initialized."; | 141 DCHECK(!demuxer_stream_) << "Already initialized."; |
| 140 | 142 |
| 141 if (!stream) { | 143 if (!stream) { |
| 142 initialize_cb.Run(PIPELINE_ERROR_DECODE); | 144 initialize_cb.Run(PIPELINE_ERROR_DECODE); |
| 143 return; | 145 return; |
| 144 } | 146 } |
| 145 | 147 |
| 146 demuxer_stream_ = stream; | 148 demuxer_stream_ = stream; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 if (!decoded_frames_.empty()) { | 219 if (!decoded_frames_.empty()) { |
| 218 scoped_refptr<VideoFrame> frame = decoded_frames_.front(); | 220 scoped_refptr<VideoFrame> frame = decoded_frames_.front(); |
| 219 decoded_frames_.pop_front(); | 221 decoded_frames_.pop_front(); |
| 220 base::ResetAndReturn(&read_cb_).Run(kOk, frame); | 222 base::ResetAndReturn(&read_cb_).Run(kOk, frame); |
| 221 return; | 223 return; |
| 222 } | 224 } |
| 223 | 225 |
| 224 DCHECK_NE(state_, kUninitialized); | 226 DCHECK_NE(state_, kUninitialized); |
| 225 DCHECK_NE(state_, kDecodeFinished); | 227 DCHECK_NE(state_, kDecodeFinished); |
| 226 DCHECK(!read_cb_.is_null()); | 228 DCHECK(!read_cb_.is_null()); |
| 227 demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::BufferReady, this)); | 229 demuxer_stream_->Read(base::Bind( |
| 230 &FFmpegVideoDecoder::BufferReady, weak_this_)); |
| 228 } | 231 } |
| 229 | 232 |
| 230 void FFmpegVideoDecoder::BufferReady( | 233 void FFmpegVideoDecoder::BufferReady( |
| 231 DemuxerStream::Status status, | 234 DemuxerStream::Status status, |
| 232 const scoped_refptr<DecoderBuffer>& buffer) { | 235 const scoped_refptr<DecoderBuffer>& buffer) { |
| 233 DCHECK(message_loop_->BelongsToCurrentThread()); | 236 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 234 DCHECK_NE(state_, kDecodeFinished); | 237 DCHECK_NE(state_, kDecodeFinished); |
| 235 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; | 238 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; |
| 236 | 239 |
| 237 if (state_ == kUninitialized) | 240 if (state_ == kUninitialized) |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { | 476 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { |
| 474 ReleaseFFmpegResources(); | 477 ReleaseFFmpegResources(); |
| 475 return false; | 478 return false; |
| 476 } | 479 } |
| 477 | 480 |
| 478 av_frame_ = avcodec_alloc_frame(); | 481 av_frame_ = avcodec_alloc_frame(); |
| 479 return true; | 482 return true; |
| 480 } | 483 } |
| 481 | 484 |
| 482 } // namespace media | 485 } // namespace media |
| OLD | NEW |