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