ffmpeg_video_decoder.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 27namespace 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 :) 38static const int kDecodeThreads = 2; 39static 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. 43static 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 57static 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 64static void ReleaseVideoBufferImpl(void* opaque, uint8* data) { 65 scoped_refptr<VideoFrame> video_frame; 66 video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque)); 67} 68 69FFmpegVideoDecoder::FFmpegVideoDecoder( 70 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) 71 : task_runner_(task_runner), state_(kUninitialized) {} 72 73int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context, 74 AVFrame* frame, 75 int flags) { 76 // Don't use |codec_context_| here! With threaded decoding, 77 // it will contain unsynchronized width/height/pix_fmt values, 78 // whereas |codec_context| contains the current threads's 79 // updated width/height/pix_fmt, which can change for adaptive 80 // content. 81 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt); 82 if (format == VideoFrame::UNKNOWN) 83 return AVERROR(EINVAL); 84 DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16 || 85 format == VideoFrame::YV12J); 86 87 gfx::Size size(codec_context->width, codec_context->height); 88 const int ret = av_image_check_size(size.width(), size.height(), 0, NULL); 89 if (ret < 0) 90 return ret; 91 92 gfx::Size natural_size; 93 if (codec_context->sample_aspect_ratio.num > 0) { 94 natural_size = GetNaturalSize(size, 95 codec_context->sample_aspect_ratio.num, 96 codec_context->sample_aspect_ratio.den); 97 } else { 98 natural_size = config_.natural_size(); 99 } 100 101 // FFmpeg has specific requirements on the allocation size of the frame. The 102 // following logic replicates FFmpeg's allocation strategy to ensure buffers 103 // are not overread / overwritten. See ff_init_buffer_info() for details. 104 // 105 // When lowres is non-zero, dimensions should be divided by 2^(lowres), but 106 // since we don't use this, just DCHECK that it's zero. 107 DCHECK_EQ(codec_context->lowres, 0); 108 gfx::Size coded_size(std::max(size.width(), codec_context->coded_width), 109 std::max(size.height(), codec_context->coded_height)); 110 111 if (!VideoFrame::IsValidConfig( 112 format, coded_size, gfx::Rect(size), natural_size)) 113 return AVERROR(EINVAL); 114 115 scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame( 116 format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp()); 117 118 for (int i = 0; i < 3; i++) { 119 frame->data[i] = video_frame->data(i); 120 frame->linesize[i] = video_frame->stride(i); 121 } 122 123 frame->width = coded_size.width(); 124 frame->height = coded_size.height(); 125 frame->format = codec_context->pix_fmt; 126 frame->reordered_opaque = codec_context->reordered_opaque; 127 128 // Now create an AVBufferRef for the data just allocated. It will own the 129 // reference to the VideoFrame object. 130 void* opaque = NULL; 131 video_frame.swap(reinterpret_cast<VideoFrame**>(&opaque)); 132 frame->buf[0] = 133 av_buffer_create(frame->data[0], 134 VideoFrame::AllocationSize(format, coded_size), 135 ReleaseVideoBufferImpl, 136 opaque, 137 0); 138 return 0; 139} 140 141void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config, 142 bool low_delay, 143 const PipelineStatusCB& status_cb) { 144 DCHECK(task_runner_->BelongsToCurrentThread()); 145 DCHECK(decode_cb_.is_null()); 146 DCHECK(!config.is_encrypted()); 147 148 FFmpegGlue::InitializeFFmpeg(); 149 150 config_ = config; 151 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); 152 153 if (!config.IsValidConfig() || !ConfigureDecoder(low_delay)) { 154 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 155 return; 156 } 157 158 // Success! 159 state_ = kNormal; 160 initialize_cb.Run(PIPELINE_OK); 161} 162 163void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, 164 const DecodeCB& decode_cb) { 165 DCHECK(task_runner_->BelongsToCurrentThread()); 166 DCHECK(!decode_cb.is_null()); 167 CHECK_NE(state_, kUninitialized); 168 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; 169 decode_cb_ = BindToCurrentLoop(decode_cb); 170 171 if (state_ == kError) { 172 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); 173 return; 174 } 175 176 // Return empty frames if decoding has finished. 177 if (state_ == kDecodeFinished) { 178 base::ResetAndReturn(&decode_cb_).Run(kOk, VideoFrame::CreateEOSFrame()); 179 return; 180 } 181 182 DecodeBuffer(buffer); 183} 184 185void FFmpegVideoDecoder::Reset(const base::Closure& closure) { 186 DCHECK(task_runner_->BelongsToCurrentThread()); 187 DCHECK(decode_cb_.is_null()); 188 189 avcodec_flush_buffers(codec_context_.get()); 190 state_ = kNormal; 191 task_runner_->PostTask(FROM_HERE, closure); 192} 193 194void FFmpegVideoDecoder::Stop() { 195 DCHECK(task_runner_->BelongsToCurrentThread()); 196 197 if (state_ == kUninitialized) 198 return; 199 200 ReleaseFFmpegResources(); 201 state_ = kUninitialized; 202} 203 204FFmpegVideoDecoder::~FFmpegVideoDecoder() { 205 DCHECK_EQ(kUninitialized, state_); 206 DCHECK(!codec_context_); 207 DCHECK(!av_frame_); 208} 209 210void FFmpegVideoDecoder::DecodeBuffer( 211 const scoped_refptr<DecoderBuffer>& buffer) { 212 DCHECK(task_runner_->BelongsToCurrentThread()); 213 DCHECK_NE(state_, kUninitialized); 214 DCHECK_NE(state_, kDecodeFinished); 215 DCHECK_NE(state_, kError); 216 DCHECK(!decode_cb_.is_null()); 217 DCHECK(buffer); 218 219 // During decode, because reads are issued asynchronously, it is possible to 220 // receive multiple end of stream buffers since each decode is acked. When the 221 // first end of stream buffer is read, FFmpeg may still have frames queued 222 // up in the decoder so we need to go through the decode loop until it stops 223 // giving sensible data. After that, the decoder should output empty 224 // frames. There are three states the decoder can be in: 225 // 226 // kNormal: This is the starting state. Buffers are decoded. Decode errors 227 // are discarded. 228 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 229 // until no more data is returned to flush out remaining 230 // frames. The input buffer is ignored at this point. 231 // kDecodeFinished: All calls return empty frames. 232 // kError: Unexpected error happened. 233 // 234 // These are the possible state transitions. 235 // 236 // kNormal -> kFlushCodec: 237 // When buffer->end_of_stream() is first true. 238 // kNormal -> kError: 239 // A decoding error occurs and decoding needs to stop. 240 // kFlushCodec -> kDecodeFinished: 241 // When avcodec_decode_video2() returns 0 data. 242 // kFlushCodec -> kError: 243 // When avcodec_decode_video2() errors out. 244 // (any state) -> kNormal: 245 // Any time Reset() is called. 246 247 // Transition to kFlushCodec on the first end of stream buffer. 248 if (state_ == kNormal && buffer->end_of_stream()) { 249 state_ = kFlushCodec; 250 } 251 252 scoped_refptr<VideoFrame> video_frame; 253 if (!FFmpegDecode(buffer, &video_frame)) { 254 state_ = kError; 255 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); 256 return; 257 } 258 259 if (!video_frame.get()) { 260 if (state_ == kFlushCodec) { 261 DCHECK(buffer->end_of_stream()); 262 state_ = kDecodeFinished; 263 base::ResetAndReturn(&decode_cb_) 264 .Run(kOk, VideoFrame::CreateEOSFrame()); 265 return; 266 } 267 268 base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL); 269 return; 270 } 271 272 base::ResetAndReturn(&decode_cb_).Run(kOk, video_frame); 273} 274 275bool FFmpegVideoDecoder::FFmpegDecode( 276 const scoped_refptr<DecoderBuffer>& buffer, 277 scoped_refptr<VideoFrame>* video_frame) { 278 DCHECK(video_frame); 279 280 // Create a packet for input data. 281 // Due to FFmpeg API changes we no longer have const read-only pointers. 282 AVPacket packet; 283 av_init_packet(&packet); 284 if (buffer->end_of_stream()) { 285 packet.data = NULL; 286 packet.size = 0; 287 } else { 288 packet.data = const_cast<uint8*>(buffer->data()); 289 packet.size = buffer->data_size(); 290 291 // Let FFmpeg handle presentation timestamp reordering. 292 codec_context_->reordered_opaque = buffer->timestamp().InMicroseconds(); 293 } 294 295 int frame_decoded = 0; 296 int result = avcodec_decode_video2(codec_context_.get(), 297 av_frame_.get(), 298 &frame_decoded, 299 &packet); 300 // Log the problem if we can't decode a video frame and exit early. 301 if (result < 0) { 302 LOG(ERROR) << "Error decoding video: " << buffer->AsHumanReadableString(); 303 *video_frame = NULL; 304 return false; 305 } 306 307 // FFmpeg says some codecs might have multiple frames per packet. Previous 308 // discussions with rbultje@ indicate this shouldn't be true for the codecs 309 // we use. 310 DCHECK_EQ(result, packet.size); 311 312 // If no frame was produced then signal that more data is required to 313 // produce more frames. This can happen under two circumstances: 314 // 1) Decoder was recently initialized/flushed 315 // 2) End of stream was reached and all internal frames have been output 316 if (frame_decoded == 0) { 317 *video_frame = NULL; 318 return true; 319 } 320 321 // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675 322 // The decoder is in a bad state and not decoding correctly. 323 // Checking for NULL avoids a crash in CopyPlane(). 324 if (!av_frame_->data[VideoFrame::kYPlane] || 325 !av_frame_->data[VideoFrame::kUPlane] || 326 !av_frame_->data[VideoFrame::kVPlane]) { 327 LOG(ERROR) << "Video frame was produced yet has invalid frame data."; 328 *video_frame = NULL; 329 av_frame_unref(av_frame_.get()); 330 return false; 331 } 332 333 *video_frame = 334 reinterpret_cast<VideoFrame*>(av_buffer_get_opaque(av_frame_->buf[0])); 335 336 (*video_frame)->set_timestamp( 337 base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque)); 338 339 av_frame_unref(av_frame_.get()); 340 return true; 341} 342 343void FFmpegVideoDecoder::ReleaseFFmpegResources() { 344 codec_context_.reset(); 345 av_frame_.reset(); 346} 347 348bool FFmpegVideoDecoder::ConfigureDecoder(bool low_delay) { 349 // Release existing decoder resources if necessary. 350 ReleaseFFmpegResources(); 351 352 // Initialize AVCodecContext structure. 353 codec_context_.reset(avcodec_alloc_context3(NULL)); 354 VideoDecoderConfigToAVCodecContext(config_, codec_context_.get()); 355 356 codec_context_->thread_count = GetThreadCount(codec_context_->codec_id); 357 codec_context_->thread_type = low_delay ? FF_THREAD_SLICE : FF_THREAD_FRAME; 358 codec_context_->opaque = this; 359 codec_context_->flags |= CODEC_FLAG_EMU_EDGE; 360 codec_context_->get_buffer2 = GetVideoBufferImpl; 361 codec_context_->refcounted_frames = 1; 362 363 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); 364 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { 365 ReleaseFFmpegResources(); 366 return false; 367 } 368 369 av_frame_.reset(av_frame_alloc()); 370 return true; 371} 372 373} // namespace media 374