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.
5 #include "media/filters/ffmpeg_video_decoder.h"
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_frame.h"
22 #include "media/base/video_util.h"
23 #include "media/ffmpeg/ffmpeg_common.h"
24 #include "media/filters/ffmpeg_glue.h"
28 // Always try to use three threads for video decoding. There is little reason
29 // not to since current day CPUs tend to be multi-core and we measured
30 // performance benefits on older machines such as P4s with hyperthreading.
32 // Handling decoding on separate threads also frees up the pipeline thread to
33 // continue processing. Although it'd be nice to have the option of a single
34 // decoding thread, FFmpeg treats having one thread the same as having zero
35 // threads (i.e., avcodec_decode_video() will execute on the calling thread).
36 // Yet another reason for having two threads :)
37 static const int kDecodeThreads
= 2;
38 static const int kMaxDecodeThreads
= 16;
40 // Returns the number of threads given the FFmpeg CodecID. Also inspects the
41 // command line for a valid --video-threads flag.
42 static int GetThreadCount(AVCodecID codec_id
) {
43 // Refer to http://crbug.com/93932 for tsan suppressions on decoding.
44 int decode_threads
= kDecodeThreads
;
46 const base::CommandLine
* cmd_line
= base::CommandLine::ForCurrentProcess();
47 std::string
threads(cmd_line
->GetSwitchValueASCII(switches::kVideoThreads
));
48 if (threads
.empty() || !base::StringToInt(threads
, &decode_threads
))
49 return decode_threads
;
51 decode_threads
= std::max(decode_threads
, 0);
52 decode_threads
= std::min(decode_threads
, kMaxDecodeThreads
);
53 return decode_threads
;
56 static int GetVideoBufferImpl(struct AVCodecContext
* s
,
59 FFmpegVideoDecoder
* decoder
= static_cast<FFmpegVideoDecoder
*>(s
->opaque
);
60 return decoder
->GetVideoBuffer(s
, frame
, flags
);
63 static void ReleaseVideoBufferImpl(void* opaque
, uint8
* data
) {
64 scoped_refptr
<VideoFrame
> video_frame
;
65 video_frame
.swap(reinterpret_cast<VideoFrame
**>(&opaque
));
68 static size_t RoundUp(size_t value
, size_t alignment
) {
69 // Check that |alignment| is a power of 2.
70 DCHECK((alignment
+ (alignment
- 1)) == (alignment
| (alignment
- 1)));
71 return ((value
+ (alignment
- 1)) & ~(alignment
- 1));
74 FFmpegVideoDecoder::FFmpegVideoDecoder(
75 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
)
76 : task_runner_(task_runner
), state_(kUninitialized
),
77 decode_nalus_(false) {}
79 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext
* codec_context
,
82 // Don't use |codec_context_| here! With threaded decoding,
83 // it will contain unsynchronized width/height/pix_fmt values,
84 // whereas |codec_context| contains the current threads's
85 // updated width/height/pix_fmt, which can change for adaptive
87 const VideoPixelFormat format
=
88 PixelFormatToVideoPixelFormat(codec_context
->pix_fmt
);
90 if (format
== PIXEL_FORMAT_UNKNOWN
)
91 return AVERROR(EINVAL
);
92 DCHECK(format
== PIXEL_FORMAT_YV12
|| format
== PIXEL_FORMAT_YV16
||
93 format
== PIXEL_FORMAT_YV24
);
95 gfx::Size
size(codec_context
->width
, codec_context
->height
);
96 const int ret
= av_image_check_size(size
.width(), size
.height(), 0, NULL
);
100 gfx::Size natural_size
;
101 if (codec_context
->sample_aspect_ratio
.num
> 0) {
102 natural_size
= GetNaturalSize(size
,
103 codec_context
->sample_aspect_ratio
.num
,
104 codec_context
->sample_aspect_ratio
.den
);
106 natural_size
= config_
.natural_size();
109 // FFmpeg has specific requirements on the allocation size of the frame. The
110 // following logic replicates FFmpeg's allocation strategy to ensure buffers
111 // are not overread / overwritten. See ff_init_buffer_info() for details.
113 // When lowres is non-zero, dimensions should be divided by 2^(lowres), but
114 // since we don't use this, just DCHECK that it's zero.
116 // Always round up to a multiple of two to match VideoFrame restrictions on
118 DCHECK_EQ(codec_context
->lowres
, 0);
119 gfx::Size
coded_size(
120 RoundUp(std::max(size
.width(), codec_context
->coded_width
), 2),
121 RoundUp(std::max(size
.height(), codec_context
->coded_height
), 2));
123 if (!VideoFrame::IsValidConfig(format
, VideoFrame::STORAGE_UNKNOWN
,
124 coded_size
, gfx::Rect(size
), natural_size
)) {
125 return AVERROR(EINVAL
);
128 scoped_refptr
<VideoFrame
> video_frame
= frame_pool_
.CreateFrame(
129 format
, coded_size
, gfx::Rect(size
), natural_size
, kNoTimestamp());
130 #if defined(MEMORY_SANITIZER)
131 MSAN_UNPOISON(video_frame
->data(0),
132 VideoFrame::AllocationSize(format
, coded_size
));
135 // Prefer the color space from the codec context. If it's not specified (or is
136 // set to an unsupported value), fall back on the value from the config.
137 ColorSpace color_space
= AVColorSpaceToColorSpace(codec_context
->colorspace
,
138 codec_context
->color_range
);
139 if (color_space
== COLOR_SPACE_UNSPECIFIED
)
140 color_space
= config_
.color_space();
141 video_frame
->metadata()->SetInteger(VideoFrameMetadata::COLOR_SPACE
,
144 for (int i
= 0; i
< 3; i
++) {
145 frame
->data
[i
] = video_frame
->data(i
);
146 frame
->linesize
[i
] = video_frame
->stride(i
);
149 frame
->width
= coded_size
.width();
150 frame
->height
= coded_size
.height();
151 frame
->format
= codec_context
->pix_fmt
;
152 frame
->reordered_opaque
= codec_context
->reordered_opaque
;
154 // Now create an AVBufferRef for the data just allocated. It will own the
155 // reference to the VideoFrame object.
157 video_frame
.swap(reinterpret_cast<VideoFrame
**>(&opaque
));
159 av_buffer_create(frame
->data
[0],
160 VideoFrame::AllocationSize(format
, coded_size
),
161 ReleaseVideoBufferImpl
,
167 std::string
FFmpegVideoDecoder::GetDisplayName() const {
168 return "FFmpegVideoDecoder";
171 void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig
& config
,
173 const InitCB
& init_cb
,
174 const OutputCB
& output_cb
) {
175 DCHECK(task_runner_
->BelongsToCurrentThread());
176 DCHECK(!config
.is_encrypted());
177 DCHECK(!output_cb
.is_null());
179 FFmpegGlue::InitializeFFmpeg();
182 InitCB bound_init_cb
= BindToCurrentLoop(init_cb
);
184 if (!config
.IsValidConfig() || !ConfigureDecoder(low_delay
)) {
185 bound_init_cb
.Run(false);
189 output_cb_
= BindToCurrentLoop(output_cb
);
193 bound_init_cb
.Run(true);
196 void FFmpegVideoDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
197 const DecodeCB
& decode_cb
) {
198 DCHECK(task_runner_
->BelongsToCurrentThread());
199 DCHECK(buffer
.get());
200 DCHECK(!decode_cb
.is_null());
201 CHECK_NE(state_
, kUninitialized
);
203 DecodeCB decode_cb_bound
= BindToCurrentLoop(decode_cb
);
205 if (state_
== kError
) {
206 decode_cb_bound
.Run(kDecodeError
);
210 if (state_
== kDecodeFinished
) {
211 decode_cb_bound
.Run(kOk
);
215 DCHECK_EQ(state_
, kNormal
);
217 // During decode, because reads are issued asynchronously, it is possible to
218 // receive multiple end of stream buffers since each decode is acked. When the
219 // first end of stream buffer is read, FFmpeg may still have frames queued
220 // up in the decoder so we need to go through the decode loop until it stops
221 // giving sensible data. After that, the decoder should output empty
222 // frames. There are three states the decoder can be in:
224 // kNormal: This is the starting state. Buffers are decoded. Decode errors
226 // kDecodeFinished: All calls return empty frames.
227 // kError: Unexpected error happened.
229 // These are the possible state transitions.
231 // kNormal -> kDecodeFinished:
232 // When EOS buffer is received and the codec has been flushed.
233 // kNormal -> kError:
234 // A decoding error occurs and decoding needs to stop.
235 // (any state) -> kNormal:
236 // Any time Reset() is called.
238 bool has_produced_frame
;
240 has_produced_frame
= false;
241 if (!FFmpegDecode(buffer
, &has_produced_frame
)) {
243 decode_cb_bound
.Run(kDecodeError
);
246 // Repeat to flush the decoder after receiving EOS buffer.
247 } while (buffer
->end_of_stream() && has_produced_frame
);
249 if (buffer
->end_of_stream())
250 state_
= kDecodeFinished
;
252 // VideoDecoderShim expects that |decode_cb| is called only after
254 decode_cb_bound
.Run(kOk
);
257 void FFmpegVideoDecoder::Reset(const base::Closure
& closure
) {
258 DCHECK(task_runner_
->BelongsToCurrentThread());
260 avcodec_flush_buffers(codec_context_
.get());
262 task_runner_
->PostTask(FROM_HERE
, closure
);
265 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
266 DCHECK(task_runner_
->BelongsToCurrentThread());
268 if (state_
!= kUninitialized
)
269 ReleaseFFmpegResources();
272 bool FFmpegVideoDecoder::FFmpegDecode(
273 const scoped_refptr
<DecoderBuffer
>& buffer
,
274 bool* has_produced_frame
) {
275 DCHECK(!*has_produced_frame
);
277 // Create a packet for input data.
278 // Due to FFmpeg API changes we no longer have const read-only pointers.
280 av_init_packet(&packet
);
281 if (buffer
->end_of_stream()) {
285 packet
.data
= const_cast<uint8
*>(buffer
->data());
286 packet
.size
= buffer
->data_size();
288 // Let FFmpeg handle presentation timestamp reordering.
289 codec_context_
->reordered_opaque
= buffer
->timestamp().InMicroseconds();
292 int frame_decoded
= 0;
293 int result
= avcodec_decode_video2(codec_context_
.get(),
297 // Log the problem if we can't decode a video frame and exit early.
299 LOG(ERROR
) << "Error decoding video: " << buffer
->AsHumanReadableString();
303 // FFmpeg says some codecs might have multiple frames per packet. Previous
304 // discussions with rbultje@ indicate this shouldn't be true for the codecs
306 DCHECK_EQ(result
, packet
.size
);
308 // If no frame was produced then signal that more data is required to
309 // produce more frames. This can happen under two circumstances:
310 // 1) Decoder was recently initialized/flushed
311 // 2) End of stream was reached and all internal frames have been output
312 if (frame_decoded
== 0) {
316 // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
317 // The decoder is in a bad state and not decoding correctly.
318 // Checking for NULL avoids a crash in CopyPlane().
319 if (!av_frame_
->data
[VideoFrame::kYPlane
] ||
320 !av_frame_
->data
[VideoFrame::kUPlane
] ||
321 !av_frame_
->data
[VideoFrame::kVPlane
]) {
322 LOG(ERROR
) << "Video frame was produced yet has invalid frame data.";
323 av_frame_unref(av_frame_
.get());
327 scoped_refptr
<VideoFrame
> frame
=
328 reinterpret_cast<VideoFrame
*>(av_buffer_get_opaque(av_frame_
->buf
[0]));
329 frame
->set_timestamp(
330 base::TimeDelta::FromMicroseconds(av_frame_
->reordered_opaque
));
331 *has_produced_frame
= true;
332 output_cb_
.Run(frame
);
334 av_frame_unref(av_frame_
.get());
338 void FFmpegVideoDecoder::ReleaseFFmpegResources() {
339 codec_context_
.reset();
343 bool FFmpegVideoDecoder::ConfigureDecoder(bool low_delay
) {
344 // Release existing decoder resources if necessary.
345 ReleaseFFmpegResources();
347 // Initialize AVCodecContext structure.
348 codec_context_
.reset(avcodec_alloc_context3(NULL
));
349 VideoDecoderConfigToAVCodecContext(config_
, codec_context_
.get());
351 codec_context_
->thread_count
= GetThreadCount(codec_context_
->codec_id
);
352 codec_context_
->thread_type
= low_delay
? FF_THREAD_SLICE
: FF_THREAD_FRAME
;
353 codec_context_
->opaque
= this;
354 codec_context_
->flags
|= CODEC_FLAG_EMU_EDGE
;
355 codec_context_
->get_buffer2
= GetVideoBufferImpl
;
356 codec_context_
->refcounted_frames
= 1;
359 codec_context_
->flags2
|= CODEC_FLAG2_CHUNKS
;
361 AVCodec
* codec
= avcodec_find_decoder(codec_context_
->codec_id
);
362 if (!codec
|| avcodec_open2(codec_context_
.get(), codec
, NULL
) < 0) {
363 ReleaseFFmpegResources();
367 av_frame_
.reset(av_frame_alloc());