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