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"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/single_thread_task_runner.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/base/bind_to_current_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)
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static int GetVideoBufferImpl(struct AVCodecContext* s,
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              AVFrame* frame,
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              int flags) {
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque);
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return decoder->GetVideoBuffer(s, frame, flags);
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static void ReleaseVideoBufferImpl(void* opaque, uint8* data) {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<VideoFrame> video_frame;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque));
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)static size_t RoundUp(size_t value, size_t alignment) {
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Check that |alignment| is a power of 2.
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ((value + (alignment - 1)) & ~(alignment - 1));
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFmpegVideoDecoder::FFmpegVideoDecoder(
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : task_runner_(task_runner), state_(kUninitialized),
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      decode_nalus_(false) {}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context,
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       AVFrame* frame,
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                       int flags) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't use |codec_context_| here! With threaded decoding,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it will contain unsynchronized width/height/pix_fmt values,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // whereas |codec_context| contains the current threads's
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // updated width/height/pix_fmt, which can change for adaptive
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt);
890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (format == VideoFrame::UNKNOWN)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AVERROR(EINVAL);
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16 ||
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         format == VideoFrame::YV12J || format == VideoFrame::YV24);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size size(codec_context->width, codec_context->height);
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const int ret = av_image_check_size(size.width(), size.height(), 0, NULL);
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (ret < 0)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size natural_size;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (codec_context->sample_aspect_ratio.num > 0) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    natural_size = GetNaturalSize(size,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  codec_context->sample_aspect_ratio.num,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  codec_context->sample_aspect_ratio.den);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    natural_size = config_.natural_size();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // FFmpeg has specific requirements on the allocation size of the frame.  The
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // following logic replicates FFmpeg's allocation strategy to ensure buffers
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // are not overread / overwritten.  See ff_init_buffer_info() for details.
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // When lowres is non-zero, dimensions should be divided by 2^(lowres), but
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // since we don't use this, just DCHECK that it's zero.
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  //
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Always round up to a multiple of two to match VideoFrame restrictions on
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // frame alignment.
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_EQ(codec_context->lowres, 0);
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  gfx::Size coded_size(
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      RoundUp(std::max(size.width(), codec_context->coded_width), 2),
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      RoundUp(std::max(size.height(), codec_context->coded_height), 2));
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!VideoFrame::IsValidConfig(
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          format, coded_size, gfx::Rect(size), natural_size))
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return AVERROR(EINVAL);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame(
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 3; i++) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->data[i] = video_frame->data(i);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frame->linesize[i] = video_frame->stride(i);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame->width = coded_size.width();
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame->height = coded_size.height();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame->format = codec_context->pix_fmt;
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  frame->reordered_opaque = codec_context->reordered_opaque;
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Now create an AVBufferRef for the data just allocated. It will own the
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // reference to the VideoFrame object.
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void* opaque = NULL;
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque));
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  frame->buf[0] =
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      av_buffer_create(frame->data[0],
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       VideoFrame::AllocationSize(format, coded_size),
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       ReleaseVideoBufferImpl,
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       opaque,
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       0);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::string FFmpegVideoDecoder::GetDisplayName() const {
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return "FFmpegVideoDecoder";
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                    bool low_delay,
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                    const PipelineStatusCB& status_cb,
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                    const OutputCB& output_cb) {
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!config.is_encrypted());
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!output_cb.is_null());
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FFmpegGlue::InitializeFFmpeg();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  config_ = config;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!config.IsValidConfig() || !ConfigureDecoder(low_delay)) {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  output_cb_ = BindToCurrentLoop(output_cb);
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Success!
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = kNormal;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  initialize_cb.Run(PIPELINE_OK);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
182558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                                const DecodeCB& decode_cb) {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(buffer.get());
185558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  DCHECK(!decode_cb.is_null());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_NE(state_, kUninitialized);
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (state_ == kError) {
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    decode_cb_bound.Run(kDecodeError);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (state_ == kDecodeFinished) {
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    decode_cb_bound.Run(kOk);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK_EQ(state_, kNormal);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // During decode, because reads are issued asynchronously, it is possible to
203558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // receive multiple end of stream buffers since each decode is acked. When the
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // first end of stream buffer is read, FFmpeg may still have frames queued
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up in the decoder so we need to go through the decode loop until it stops
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // giving sensible data.  After that, the decoder should output empty
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frames.  There are three states the decoder can be in:
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   kNormal: This is the starting state. Buffers are decoded. Decode errors
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //            are discarded.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   kDecodeFinished: All calls return empty frames.
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   kError: Unexpected error happened.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These are the possible state transitions.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // kNormal -> kDecodeFinished:
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  //     When EOS buffer is received and the codec has been flushed.
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // kNormal -> kError:
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     A decoding error occurs and decoding needs to stop.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (any state) -> kNormal:
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     Any time Reset() is called.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool has_produced_frame;
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  do {
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    has_produced_frame = false;
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!FFmpegDecode(buffer, &has_produced_frame)) {
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      state_ = kError;
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      decode_cb_bound.Run(kDecodeError);
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return;
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Repeat to flush the decoder after receiving EOS buffer.
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } while (buffer->end_of_stream() && has_produced_frame);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (buffer->end_of_stream())
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    state_ = kDecodeFinished;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  decode_cb_bound.Run(kOk);
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  avcodec_flush_buffers(codec_context_.get());
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  state_ = kNormal;
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  task_runner_->PostTask(FROM_HERE, closure);
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
248116680a4aac90f2aa7413d9095a592090648e557Ben MurdochFFmpegVideoDecoder::~FFmpegVideoDecoder() {
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(task_runner_->BelongsToCurrentThread());
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (state_ != kUninitialized)
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ReleaseFFmpegResources();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool FFmpegVideoDecoder::FFmpegDecode(
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<DecoderBuffer>& buffer,
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool* has_produced_frame) {
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!*has_produced_frame);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a packet for input data.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Due to FFmpeg API changes we no longer have const read-only pointers.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVPacket packet;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  av_init_packet(&packet);
264ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (buffer->end_of_stream()) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    packet.data = NULL;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    packet.size = 0;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    packet.data = const_cast<uint8*>(buffer->data());
269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    packet.size = buffer->data_size();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Let FFmpeg handle presentation timestamp reordering.
272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    codec_context_->reordered_opaque = buffer->timestamp().InMicroseconds();
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frame_decoded = 0;
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int result = avcodec_decode_video2(codec_context_.get(),
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                     av_frame_.get(),
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &frame_decoded,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &packet);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log the problem if we can't decode a video frame and exit early.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Error decoding video: " << buffer->AsHumanReadableString();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // FFmpeg says some codecs might have multiple frames per packet.  Previous
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // discussions with rbultje@ indicate this shouldn't be true for the codecs
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we use.
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(result, packet.size);
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no frame was produced then signal that more data is required to
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // produce more frames. This can happen under two circumstances:
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   1) Decoder was recently initialized/flushed
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   2) End of stream was reached and all internal frames have been output
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frame_decoded == 0) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The decoder is in a bad state and not decoding correctly.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checking for NULL avoids a crash in CopyPlane().
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!av_frame_->data[VideoFrame::kYPlane] ||
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !av_frame_->data[VideoFrame::kUPlane] ||
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !av_frame_->data[VideoFrame::kVPlane]) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Video frame was produced yet has invalid frame data.";
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    av_frame_unref(av_frame_.get());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_refptr<VideoFrame> frame =
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reinterpret_cast<VideoFrame*>(av_buffer_get_opaque(av_frame_->buf[0]));
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  frame->set_timestamp(
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque));
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *has_produced_frame = true;
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  output_cb_.Run(frame);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  av_frame_unref(av_frame_.get());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FFmpegVideoDecoder::ReleaseFFmpegResources() {
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  codec_context_.reset();
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  av_frame_.reset();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool FFmpegVideoDecoder::ConfigureDecoder(bool low_delay) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release existing decoder resources if necessary.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReleaseFFmpegResources();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize AVCodecContext structure.
33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  codec_context_.reset(avcodec_alloc_context3(NULL));
33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  VideoDecoderConfigToAVCodecContext(config_, codec_context_.get());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->thread_count = GetThreadCount(codec_context_->codec_id);
3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  codec_context_->thread_type = low_delay ? FF_THREAD_SLICE : FF_THREAD_FRAME;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->opaque = this;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  codec_context_->get_buffer2 = GetVideoBufferImpl;
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  codec_context_->refcounted_frames = 1;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (decode_nalus_)
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    codec_context_->flags2 |= CODEC_FLAG2_CHUNKS;
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseFFmpegResources();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  av_frame_.reset(av_frame_alloc());
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
355