Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1024)

Unified Diff: media/filters/ffmpeg_video_decoder.cc

Issue 297553002: Add callback in VideoDecoder and AudioDecoder to return decoded frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/filters/ffmpeg_video_decoder.cc
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc
index bc2346ddf8843526fde8ae980e847488e7ba0b13..d55d82eed591d67e6e01f1bcce394fb5eb9ff3ad 100644
--- a/media/filters/ffmpeg_video_decoder.cc
+++ b/media/filters/ffmpeg_video_decoder.cc
@@ -135,10 +135,11 @@ static void ReleaseVideoBufferImpl(AVCodecContext* s, AVFrame* frame) {
void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
bool low_delay,
- const PipelineStatusCB& status_cb) {
+ const PipelineStatusCB& status_cb,
+ const OutputCB& output_cb) {
DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(decode_cb_.is_null());
DCHECK(!config.is_encrypted());
+ DCHECK(!output_cb.is_null());
FFmpegGlue::InitializeFFmpeg();
@@ -150,6 +151,8 @@ void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
return;
}
+ output_cb_ = BindToCurrentLoop(output_cb);
+
// Success!
state_ = kNormal;
initialize_cb.Run(PIPELINE_OK);
@@ -158,58 +161,25 @@ void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
const DecodeCB& decode_cb) {
DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(buffer);
DCHECK(!decode_cb.is_null());
CHECK_NE(state_, kUninitialized);
- CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
- decode_cb_ = BindToCurrentLoop(decode_cb);
+
+ DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb);
if (state_ == kError) {
- base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL);
+ decode_cb_bound.Run(kDecodeError);
return;
}
// Return empty frames if decoding has finished.
if (state_ == kDecodeFinished) {
- base::ResetAndReturn(&decode_cb_).Run(kOk, VideoFrame::CreateEOSFrame());
+ output_cb_.Run(VideoFrame::CreateEOSFrame());
+ decode_cb_bound.Run(kOk);
return;
}
- DecodeBuffer(buffer);
-}
-
-void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(decode_cb_.is_null());
-
- avcodec_flush_buffers(codec_context_.get());
- state_ = kNormal;
- task_runner_->PostTask(FROM_HERE, closure);
-}
-
-void FFmpegVideoDecoder::Stop() {
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- if (state_ == kUninitialized)
- return;
-
- ReleaseFFmpegResources();
- state_ = kUninitialized;
-}
-
-FFmpegVideoDecoder::~FFmpegVideoDecoder() {
- DCHECK_EQ(kUninitialized, state_);
- DCHECK(!codec_context_);
- DCHECK(!av_frame_);
-}
-
-void FFmpegVideoDecoder::DecodeBuffer(
- const scoped_refptr<DecoderBuffer>& buffer) {
- DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK_NE(state_, kUninitialized);
- DCHECK_NE(state_, kDecodeFinished);
- DCHECK_NE(state_, kError);
- DCHECK(!decode_cb_.is_null());
- DCHECK(buffer);
+ DCHECK_EQ(state_, kNormal);
// During decode, because reads are issued asynchronously, it is possible to
// receive multiple end of stream buffers since each decode is acked. When the
@@ -228,43 +198,63 @@ void FFmpegVideoDecoder::DecodeBuffer(
//
// These are the possible state transitions.
//
- // kNormal -> kFlushCodec:
- // When buffer->end_of_stream() is first true.
+ // kNormal -> kDecodeFinished:
+ // When EOS buffer is received.
// kNormal -> kError:
// A decoding error occurs and decoding needs to stop.
- // kFlushCodec -> kDecodeFinished:
- // When avcodec_decode_video2() returns 0 data.
- // kFlushCodec -> kError:
- // When avcodec_decode_video2() errors out.
// (any state) -> kNormal:
// Any time Reset() is called.
- // Transition to kFlushCodec on the first end of stream buffer.
- if (state_ == kNormal && buffer->end_of_stream()) {
- state_ = kFlushCodec;
+ // Flush the decoder after receiving EOS buffer.
+ if (buffer->end_of_stream()) {
+ scoped_refptr<VideoFrame> video_frame;
+ do {
+ if (!FFmpegDecode(buffer, &video_frame)) {
+ state_ = kError;
+ decode_cb_bound.Run(kDecodeError);
+ return;
+ }
+ if (video_frame)
+ output_cb_.Run(video_frame);
+ } while (video_frame);
+ output_cb_.Run(VideoFrame::CreateEOSFrame());
+ state_ = kDecodeFinished;
+ } else {
+ scoped_refptr<VideoFrame> video_frame;
+ if (!FFmpegDecode(buffer, &video_frame)) {
+ state_ = kError;
+ decode_cb_bound.Run(kDecodeError);
+ return;
+ }
+ if (video_frame)
+ output_cb_.Run(video_frame);
xhwang 2014/05/29 22:15:14 You can probably wrap l.223-230 into a helper func
Sergey Ulanov 2014/06/03 00:08:11 Formatted this code to avoid duplication.
}
- scoped_refptr<VideoFrame> video_frame;
- if (!FFmpegDecode(buffer, &video_frame)) {
- state_ = kError;
- base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL);
- return;
- }
+ decode_cb_bound.Run(kOk);
+}
- if (!video_frame.get()) {
- if (state_ == kFlushCodec) {
- DCHECK(buffer->end_of_stream());
- state_ = kDecodeFinished;
- base::ResetAndReturn(&decode_cb_)
- .Run(kOk, VideoFrame::CreateEOSFrame());
- return;
- }
+void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ avcodec_flush_buffers(codec_context_.get());
+ state_ = kNormal;
+ task_runner_->PostTask(FROM_HERE, closure);
+}
+
+void FFmpegVideoDecoder::Stop() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
- base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL);
+ if (state_ == kUninitialized)
return;
- }
- base::ResetAndReturn(&decode_cb_).Run(kOk, video_frame);
+ ReleaseFFmpegResources();
+ state_ = kUninitialized;
+}
+
+FFmpegVideoDecoder::~FFmpegVideoDecoder() {
+ DCHECK_EQ(kUninitialized, state_);
+ DCHECK(!codec_context_);
+ DCHECK(!av_frame_);
}
bool FFmpegVideoDecoder::FFmpegDecode(

Powered by Google App Engine
This is Rietveld 408576698