Home | History | Annotate | Download | only in filters
      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
      3 // found in the LICENSE file.
      4 
      5 #include "media/filters/ffmpeg_video_decoder.h"
      6 
      7 #include <algorithm>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "base/callback_helpers.h"
     12 #include "base/command_line.h"
     13 #include "base/location.h"
     14 #include "base/single_thread_task_runner.h"
     15 #include "base/strings/string_number_conversions.h"
     16 #include "media/base/bind_to_current_loop.h"
     17 #include "media/base/decoder_buffer.h"
     18 #include "media/base/limits.h"
     19 #include "media/base/media_switches.h"
     20 #include "media/base/pipeline.h"
     21 #include "media/base/video_decoder_config.h"
     22 #include "media/base/video_frame.h"
     23 #include "media/base/video_util.h"
     24 #include "media/ffmpeg/ffmpeg_common.h"
     25 #include "media/filters/ffmpeg_glue.h"
     26 
     27 namespace media {
     28 
     29 // Always try to use three threads for video decoding.  There is little reason
     30 // not to since current day CPUs tend to be multi-core and we measured
     31 // performance benefits on older machines such as P4s with hyperthreading.
     32 //
     33 // Handling decoding on separate threads also frees up the pipeline thread to
     34 // continue processing. Although it'd be nice to have the option of a single
     35 // decoding thread, FFmpeg treats having one thread the same as having zero
     36 // threads (i.e., avcodec_decode_video() will execute on the calling thread).
     37 // Yet another reason for having two threads :)
     38 static const int kDecodeThreads = 2;
     39 static const int kMaxDecodeThreads = 16;
     40 
     41 // Returns the number of threads given the FFmpeg CodecID. Also inspects the
     42 // command line for a valid --video-threads flag.
     43 static int GetThreadCount(AVCodecID codec_id) {
     44   // Refer to http://crbug.com/93932 for tsan suppressions on decoding.
     45   int decode_threads = kDecodeThreads;
     46 
     47   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
     48   std::string threads(cmd_line->GetSwitchValueASCII(switches::kVideoThreads));
     49   if (threads.empty() || !base::StringToInt(threads, &decode_threads))
     50     return decode_threads;
     51 
     52   decode_threads = std::max(decode_threads, 0);
     53   decode_threads = std::min(decode_threads, kMaxDecodeThreads);
     54   return decode_threads;
     55 }
     56 
     57 static int GetVideoBufferImpl(struct AVCodecContext* s,
     58                               AVFrame* frame,
     59                               int flags) {
     60   FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque);
     61   return decoder->GetVideoBuffer(s, frame, flags);
     62 }
     63 
     64 static void ReleaseVideoBufferImpl(void* opaque, uint8* data) {
     65   scoped_refptr<VideoFrame> video_frame;
     66   video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque));
     67 }
     68 
     69 static size_t RoundUp(size_t value, size_t alignment) {
     70   // Check that |alignment| is a power of 2.
     71   DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
     72   return ((value + (alignment - 1)) & ~(alignment - 1));
     73 }
     74 
     75 FFmpegVideoDecoder::FFmpegVideoDecoder(
     76     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
     77     : task_runner_(task_runner), state_(kUninitialized),
     78       decode_nalus_(false) {}
     79 
     80 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context,
     81                                        AVFrame* frame,
     82                                        int flags) {
     83   // Don't use |codec_context_| here! With threaded decoding,
     84   // it will contain unsynchronized width/height/pix_fmt values,
     85   // whereas |codec_context| contains the current threads's
     86   // updated width/height/pix_fmt, which can change for adaptive
     87   // content.
     88   VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt);
     89   if (format == VideoFrame::UNKNOWN)
     90     return AVERROR(EINVAL);
     91   DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16 ||
     92          format == VideoFrame::YV12J || format == VideoFrame::YV24);
     93 
     94   gfx::Size size(codec_context->width, codec_context->height);
     95   const int ret = av_image_check_size(size.width(), size.height(), 0, NULL);
     96   if (ret < 0)
     97     return ret;
     98 
     99   gfx::Size natural_size;
    100   if (codec_context->sample_aspect_ratio.num > 0) {
    101     natural_size = GetNaturalSize(size,
    102                                   codec_context->sample_aspect_ratio.num,
    103                                   codec_context->sample_aspect_ratio.den);
    104   } else {
    105     natural_size = config_.natural_size();
    106   }
    107 
    108   // FFmpeg has specific requirements on the allocation size of the frame.  The
    109   // following logic replicates FFmpeg's allocation strategy to ensure buffers
    110   // are not overread / overwritten.  See ff_init_buffer_info() for details.
    111   //
    112   // When lowres is non-zero, dimensions should be divided by 2^(lowres), but
    113   // since we don't use this, just DCHECK that it's zero.
    114   //
    115   // Always round up to a multiple of two to match VideoFrame restrictions on
    116   // frame alignment.
    117   DCHECK_EQ(codec_context->lowres, 0);
    118   gfx::Size coded_size(
    119       RoundUp(std::max(size.width(), codec_context->coded_width), 2),
    120       RoundUp(std::max(size.height(), codec_context->coded_height), 2));
    121 
    122   if (!VideoFrame::IsValidConfig(
    123           format, coded_size, gfx::Rect(size), natural_size))
    124     return AVERROR(EINVAL);
    125 
    126   scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame(
    127       format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp());
    128 
    129   for (int i = 0; i < 3; i++) {
    130     frame->data[i] = video_frame->data(i);
    131     frame->linesize[i] = video_frame->stride(i);
    132   }
    133 
    134   frame->width = coded_size.width();
    135   frame->height = coded_size.height();
    136   frame->format = codec_context->pix_fmt;
    137   frame->reordered_opaque = codec_context->reordered_opaque;
    138 
    139   // Now create an AVBufferRef for the data just allocated. It will own the
    140   // reference to the VideoFrame object.
    141   void* opaque = NULL;
    142   video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque));
    143   frame->buf[0] =
    144       av_buffer_create(frame->data[0],
    145                        VideoFrame::AllocationSize(format, coded_size),
    146                        ReleaseVideoBufferImpl,
    147                        opaque,
    148                        0);
    149   return 0;
    150 }
    151 
    152 std::string FFmpegVideoDecoder::GetDisplayName() const {
    153   return "FFmpegVideoDecoder";
    154 }
    155 
    156 void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
    157                                     bool low_delay,
    158                                     const PipelineStatusCB& status_cb,
    159                                     const OutputCB& output_cb) {
    160   DCHECK(task_runner_->BelongsToCurrentThread());
    161   DCHECK(!config.is_encrypted());
    162   DCHECK(!output_cb.is_null());
    163 
    164   FFmpegGlue::InitializeFFmpeg();
    165 
    166   config_ = config;
    167   PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
    168 
    169   if (!config.IsValidConfig() || !ConfigureDecoder(low_delay)) {
    170     initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
    171     return;
    172   }
    173 
    174   output_cb_ = BindToCurrentLoop(output_cb);
    175 
    176   // Success!
    177   state_ = kNormal;
    178   initialize_cb.Run(PIPELINE_OK);
    179 }
    180 
    181 void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
    182                                 const DecodeCB& decode_cb) {
    183   DCHECK(task_runner_->BelongsToCurrentThread());
    184   DCHECK(buffer.get());
    185   DCHECK(!decode_cb.is_null());
    186   CHECK_NE(state_, kUninitialized);
    187 
    188   DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb);
    189 
    190   if (state_ == kError) {
    191     decode_cb_bound.Run(kDecodeError);
    192     return;
    193   }
    194 
    195   if (state_ == kDecodeFinished) {
    196     decode_cb_bound.Run(kOk);
    197     return;
    198   }
    199 
    200   DCHECK_EQ(state_, kNormal);
    201 
    202   // During decode, because reads are issued asynchronously, it is possible to
    203   // receive multiple end of stream buffers since each decode is acked. When the
    204   // first end of stream buffer is read, FFmpeg may still have frames queued
    205   // up in the decoder so we need to go through the decode loop until it stops
    206   // giving sensible data.  After that, the decoder should output empty
    207   // frames.  There are three states the decoder can be in:
    208   //
    209   //   kNormal: This is the starting state. Buffers are decoded. Decode errors
    210   //            are discarded.
    211   //   kDecodeFinished: All calls return empty frames.
    212   //   kError: Unexpected error happened.
    213   //
    214   // These are the possible state transitions.
    215   //
    216   // kNormal -> kDecodeFinished:
    217   //     When EOS buffer is received and the codec has been flushed.
    218   // kNormal -> kError:
    219   //     A decoding error occurs and decoding needs to stop.
    220   // (any state) -> kNormal:
    221   //     Any time Reset() is called.
    222 
    223   bool has_produced_frame;
    224   do {
    225     has_produced_frame = false;
    226     if (!FFmpegDecode(buffer, &has_produced_frame)) {
    227       state_ = kError;
    228       decode_cb_bound.Run(kDecodeError);
    229       return;
    230     }
    231     // Repeat to flush the decoder after receiving EOS buffer.
    232   } while (buffer->end_of_stream() && has_produced_frame);
    233 
    234   if (buffer->end_of_stream())
    235     state_ = kDecodeFinished;
    236 
    237   decode_cb_bound.Run(kOk);
    238 }
    239 
    240 void FFmpegVideoDecoder::Reset(const base::Closure& closure) {
    241   DCHECK(task_runner_->BelongsToCurrentThread());
    242 
    243   avcodec_flush_buffers(codec_context_.get());
    244   state_ = kNormal;
    245   task_runner_->PostTask(FROM_HERE, closure);
    246 }
    247 
    248 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
    249   DCHECK(task_runner_->BelongsToCurrentThread());
    250 
    251   if (state_ != kUninitialized)
    252     ReleaseFFmpegResources();
    253 }
    254 
    255 bool FFmpegVideoDecoder::FFmpegDecode(
    256     const scoped_refptr<DecoderBuffer>& buffer,
    257     bool* has_produced_frame) {
    258   DCHECK(!*has_produced_frame);
    259 
    260   // Create a packet for input data.
    261   // Due to FFmpeg API changes we no longer have const read-only pointers.
    262   AVPacket packet;
    263   av_init_packet(&packet);
    264   if (buffer->end_of_stream()) {
    265     packet.data = NULL;
    266     packet.size = 0;
    267   } else {
    268     packet.data = const_cast<uint8*>(buffer->data());
    269     packet.size = buffer->data_size();
    270 
    271     // Let FFmpeg handle presentation timestamp reordering.
    272     codec_context_->reordered_opaque = buffer->timestamp().InMicroseconds();
    273   }
    274 
    275   int frame_decoded = 0;
    276   int result = avcodec_decode_video2(codec_context_.get(),
    277                                      av_frame_.get(),
    278                                      &frame_decoded,
    279                                      &packet);
    280   // Log the problem if we can't decode a video frame and exit early.
    281   if (result < 0) {
    282     LOG(ERROR) << "Error decoding video: " << buffer->AsHumanReadableString();
    283     return false;
    284   }
    285 
    286   // FFmpeg says some codecs might have multiple frames per packet.  Previous
    287   // discussions with rbultje@ indicate this shouldn't be true for the codecs
    288   // we use.
    289   DCHECK_EQ(result, packet.size);
    290 
    291   // If no frame was produced then signal that more data is required to
    292   // produce more frames. This can happen under two circumstances:
    293   //   1) Decoder was recently initialized/flushed
    294   //   2) End of stream was reached and all internal frames have been output
    295   if (frame_decoded == 0) {
    296     return true;
    297   }
    298 
    299   // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
    300   // The decoder is in a bad state and not decoding correctly.
    301   // Checking for NULL avoids a crash in CopyPlane().
    302   if (!av_frame_->data[VideoFrame::kYPlane] ||
    303       !av_frame_->data[VideoFrame::kUPlane] ||
    304       !av_frame_->data[VideoFrame::kVPlane]) {
    305     LOG(ERROR) << "Video frame was produced yet has invalid frame data.";
    306     av_frame_unref(av_frame_.get());
    307     return false;
    308   }
    309 
    310   scoped_refptr<VideoFrame> frame =
    311       reinterpret_cast<VideoFrame*>(av_buffer_get_opaque(av_frame_->buf[0]));
    312   frame->set_timestamp(
    313       base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque));
    314   *has_produced_frame = true;
    315   output_cb_.Run(frame);
    316 
    317   av_frame_unref(av_frame_.get());
    318   return true;
    319 }
    320 
    321 void FFmpegVideoDecoder::ReleaseFFmpegResources() {
    322   codec_context_.reset();
    323   av_frame_.reset();
    324 }
    325 
    326 bool FFmpegVideoDecoder::ConfigureDecoder(bool low_delay) {
    327   // Release existing decoder resources if necessary.
    328   ReleaseFFmpegResources();
    329 
    330   // Initialize AVCodecContext structure.
    331   codec_context_.reset(avcodec_alloc_context3(NULL));
    332   VideoDecoderConfigToAVCodecContext(config_, codec_context_.get());
    333 
    334   codec_context_->thread_count = GetThreadCount(codec_context_->codec_id);
    335   codec_context_->thread_type = low_delay ? FF_THREAD_SLICE : FF_THREAD_FRAME;
    336   codec_context_->opaque = this;
    337   codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
    338   codec_context_->get_buffer2 = GetVideoBufferImpl;
    339   codec_context_->refcounted_frames = 1;
    340 
    341   if (decode_nalus_)
    342     codec_context_->flags2 |= CODEC_FLAG2_CHUNKS;
    343 
    344   AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
    345   if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
    346     ReleaseFFmpegResources();
    347     return false;
    348   }
    349 
    350   av_frame_.reset(av_frame_alloc());
    351   return true;
    352 }
    353 
    354 }  // namespace media
    355