ffmpeg_video_decoder.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/ffmpeg_video_decoder.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_helpers.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/bind_to_loop.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/decoder_buffer.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_switches.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/pipeline.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_decoder_config.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/ffmpeg/ffmpeg_common.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/ffmpeg_glue.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Always try to use three threads for video decoding.  There is little reason
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not to since current day CPUs tend to be multi-core and we measured
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// performance benefits on older machines such as P4s with hyperthreading.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handling decoding on separate threads also frees up the pipeline thread to
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// continue processing. Although it'd be nice to have the option of a single
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// decoding thread, FFmpeg treats having one thread the same as having zero
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads (i.e., avcodec_decode_video() will execute on the calling thread).
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Yet another reason for having two threads :)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDecodeThreads = 2;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kMaxDecodeThreads = 16;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the number of threads given the FFmpeg CodecID. Also inspects the
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// command line for a valid --video-threads flag.
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static int GetThreadCount(AVCodecID codec_id) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Refer to http://crbug.com/93932 for tsan suppressions on decoding.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int decode_threads = kDecodeThreads;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (threads.empty() || !base::StringToInt(threads, &decode_threads))
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return decode_threads;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decode_threads = std::max(decode_threads, 0);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decode_threads = std::min(decode_threads, kMaxDecodeThreads);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return decode_threads;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFmpegVideoDecoder::FFmpegVideoDecoder(
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const scoped_refptr<base::MessageLoopProxy>& message_loop)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : message_loop_(message_loop),
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      state_(kUninitialized) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       AVFrame* frame) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't use |codec_context_| here! With threaded decoding,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it will contain unsynchronized width/height/pix_fmt values,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // whereas |codec_context| contains the current threads's
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // updated width/height/pix_fmt, which can change for adaptive
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt);
720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (format == VideoFrame::UNKNOWN)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AVERROR(EINVAL);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size size(codec_context->width, codec_context->height);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((ret = av_image_check_size(size.width(), size.height(), 0, NULL)) < 0)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size natural_size;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (codec_context->sample_aspect_ratio.num > 0) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    natural_size = GetNaturalSize(size,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  codec_context->sample_aspect_ratio.num,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  codec_context->sample_aspect_ratio.den);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    natural_size = config_.natural_size();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!VideoFrame::IsValidConfig(format, size, gfx::Rect(size), natural_size))
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AVERROR(EINVAL);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> video_frame =
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VideoFrame::CreateFrame(format, size, gfx::Rect(size), natural_size,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              kNoTimestamp());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 3; i++) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->base[i] = video_frame->data(i);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->data[i] = video_frame->data(i);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->linesize[i] = video_frame->stride(i);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->opaque = NULL;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_frame.swap(reinterpret_cast<VideoFrame**>(&frame->opaque));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->type = FF_BUFFER_TYPE_USER;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->pkt_pts = codec_context->pkt ? codec_context->pkt->pts :
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        AV_NOPTS_VALUE;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->width = codec_context->width;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->height = codec_context->height;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->format = codec_context->pix_fmt;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int GetVideoBufferImpl(AVCodecContext* s, AVFrame* frame) {
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque);
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return decoder->GetVideoBuffer(s, frame);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ReleaseVideoBufferImpl(AVCodecContext* s, AVFrame* frame) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> video_frame;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_frame.swap(reinterpret_cast<VideoFrame**>(&frame->opaque));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The FFmpeg API expects us to zero the data pointers in
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this callback
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(frame->data, 0, sizeof(frame->data));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->opaque = NULL;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                    const PipelineStatusCB& status_cb) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
133558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.is_null());
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(reset_cb_.is_null());
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!config.is_encrypted());
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FFmpegGlue::InitializeFFmpeg();
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  weak_this_ = weak_factory_.GetWeakPtr();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  config_ = config;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!config.IsValidConfig() || !ConfigureDecoder()) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Success!
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kNormal;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  initialize_cb.Run(PIPELINE_OK);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                const DecodeCB& decode_cb) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!decode_cb.is_null());
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_NE(state_, kUninitialized);
158558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  decode_cb_ = BindToCurrentLoop(decode_cb);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ == kError) {
162558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL);
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Return empty frames if decoding has finished.
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (state_ == kDecodeFinished) {
168558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    base::ResetAndReturn(&decode_cb_).Run(kOk, VideoFrame::CreateEmptyFrame());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DecodeBuffer(buffer);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(reset_cb_.is_null());
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  reset_cb_ = BindToCurrentLoop(closure);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Defer the reset if a decode is pending.
181558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!decode_cb_.is_null())
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoReset();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FFmpegVideoDecoder::DoReset() {
188558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(decode_cb_.is_null());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  avcodec_flush_buffers(codec_context_.get());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kNormal;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ResetAndReturn(&reset_cb_).Run();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FFmpegVideoDecoder::Stop(const base::Closure& closure) {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedClosureRunner runner(BindToCurrentLoop(closure));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (state_ == kUninitialized)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!decode_cb_.is_null()) {
203558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    base::ResetAndReturn(&decode_cb_).Run(kOk, NULL);
204558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    // Reset is pending only when decode is pending.
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!reset_cb_.is_null())
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::ResetAndReturn(&reset_cb_).Run();
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseFFmpegResources();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kUninitialized;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFmpegVideoDecoder::~FFmpegVideoDecoder() {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kUninitialized, state_);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!codec_context_);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!av_frame_);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FFmpegVideoDecoder::DecodeBuffer(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<DecoderBuffer>& buffer) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(state_, kUninitialized);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(state_, kDecodeFinished);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_NE(state_, kError);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(reset_cb_.is_null());
226558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!decode_cb_.is_null());
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(buffer);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // During decode, because reads are issued asynchronously, it is possible to
230558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // receive multiple end of stream buffers since each decode is acked. When the
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // first end of stream buffer is read, FFmpeg may still have frames queued
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up in the decoder so we need to go through the decode loop until it stops
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // giving sensible data.  After that, the decoder should output empty
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frames.  There are three states the decoder can be in:
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   kNormal: This is the starting state. Buffers are decoded. Decode errors
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //            are discarded.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   kFlushCodec: There isn't any more input data. Call avcodec_decode_video2
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                until no more data is returned to flush out remaining
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                frames. The input buffer is ignored at this point.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   kDecodeFinished: All calls return empty frames.
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   kError: Unexpected error happened.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These are the possible state transitions.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kNormal -> kFlushCodec:
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  //     When buffer->end_of_stream() is first true.
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // kNormal -> kError:
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     A decoding error occurs and decoding needs to stop.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kFlushCodec -> kDecodeFinished:
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //     When avcodec_decode_video2() returns 0 data.
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // kFlushCodec -> kError:
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //     When avcodec_decode_video2() errors out.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (any state) -> kNormal:
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     Any time Reset() is called.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transition to kFlushCodec on the first end of stream buffer.
258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (state_ == kNormal && buffer->end_of_stream()) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = kFlushCodec;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<VideoFrame> video_frame;
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!FFmpegDecode(buffer, &video_frame)) {
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    state_ = kError;
265558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!video_frame.get()) {
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (state_ == kFlushCodec) {
271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      DCHECK(buffer->end_of_stream());
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      state_ = kDecodeFinished;
273558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      base::ResetAndReturn(&decode_cb_)
274558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch          .Run(kOk, VideoFrame::CreateEmptyFrame());
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
278558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL);
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
282558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  base::ResetAndReturn(&decode_cb_).Run(kOk, video_frame);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool FFmpegVideoDecoder::FFmpegDecode(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<DecoderBuffer>& buffer,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<VideoFrame>* video_frame) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(video_frame);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Reset frame to default values.
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  avcodec_get_frame_defaults(av_frame_.get());
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a packet for input data.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Due to FFmpeg API changes we no longer have const read-only pointers.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVPacket packet;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  av_init_packet(&packet);
297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (buffer->end_of_stream()) {
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    packet.data = NULL;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    packet.size = 0;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    packet.data = const_cast<uint8*>(buffer->data());
302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    packet.size = buffer->data_size();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Let FFmpeg handle presentation timestamp reordering.
305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    codec_context_->reordered_opaque = buffer->timestamp().InMicroseconds();
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This is for codecs not using get_buffer to initialize
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |av_frame_->reordered_opaque|
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    av_frame_->reordered_opaque = codec_context_->reordered_opaque;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frame_decoded = 0;
31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = avcodec_decode_video2(codec_context_.get(),
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     av_frame_.get(),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &frame_decoded,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &packet);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log the problem if we can't decode a video frame and exit early.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Error decoding video: " << buffer->AsHumanReadableString();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *video_frame = NULL;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no frame was produced then signal that more data is required to
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // produce more frames. This can happen under two circumstances:
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   1) Decoder was recently initialized/flushed
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   2) End of stream was reached and all internal frames have been output
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_decoded == 0) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *video_frame = NULL;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The decoder is in a bad state and not decoding correctly.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checking for NULL avoids a crash in CopyPlane().
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!av_frame_->data[VideoFrame::kYPlane] ||
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !av_frame_->data[VideoFrame::kUPlane] ||
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !av_frame_->data[VideoFrame::kVPlane]) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Video frame was produced yet has invalid frame data.";
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *video_frame = NULL;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!av_frame_->opaque) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "VideoFrame object associated with frame data not set.";
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *video_frame = static_cast<VideoFrame*>(av_frame_->opaque);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (*video_frame)->SetTimestamp(
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FFmpegVideoDecoder::ReleaseFFmpegResources() {
35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  codec_context_.reset();
35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  av_frame_.reset();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FFmpegVideoDecoder::ConfigureDecoder() {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release existing decoder resources if necessary.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseFFmpegResources();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize AVCodecContext structure.
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  codec_context_.reset(avcodec_alloc_context3(NULL));
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  VideoDecoderConfigToAVCodecContext(config_, codec_context_.get());
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enable motion vector search (potentially slow), strong deblocking filter
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for damaged macroblocks, and set our error detection sensitivity.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->thread_count = GetThreadCount(codec_context_->codec_id);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->opaque = this;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->get_buffer = GetVideoBufferImpl;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->release_buffer = ReleaseVideoBufferImpl;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseFFmpegResources();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  av_frame_.reset(avcodec_alloc_frame());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
389