1 // Copyright 2012 The Chromium Authors
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"
13 #include "base/bind.h"
14 #include "base/callback_helpers.h"
15 #include "base/location.h"
16 #include "base/task/sequenced_task_runner.h"
17 #include "base/threading/sequenced_task_runner_handle.h"
18 #include "media/base/bind_to_current_loop.h"
19 #include "media/base/decoder_buffer.h"
20 #include "media/base/limits.h"
21 #include "media/base/media_log.h"
22 #include "media/base/timestamp_constants.h"
23 #include "media/base/video_aspect_ratio.h"
24 #include "media/base/video_frame.h"
25 #include "media/base/video_util.h"
26 #include "media/ffmpeg/ffmpeg_common.h"
27 #include "media/ffmpeg/ffmpeg_decoding_loop.h"
31 // Returns the number of threads given the FFmpeg CodecID. Also inspects the
32 // command line for a valid --video-threads flag.
33 static int GetFFmpegVideoDecoderThreadCount(const VideoDecoderConfig& config) {
34 // Most codecs are so old that more threads aren't really needed.
35 int desired_threads = limits::kMinVideoDecodeThreads;
37 // Some ffmpeg codecs don't actually benefit from using more threads.
38 // Only add more threads for those codecs that we know will benefit.
39 switch (config.codec()) {
40 case VideoCodec::kUnknown:
41 case VideoCodec::kVC1:
42 case VideoCodec::kMPEG2:
43 case VideoCodec::kHEVC:
44 case VideoCodec::kVP9:
45 case VideoCodec::kAV1:
46 case VideoCodec::kDolbyVision:
47 // We do not compile ffmpeg with support for any of these codecs.
50 case VideoCodec::kTheora:
51 case VideoCodec::kMPEG4:
52 // No extra threads for these codecs.
55 case VideoCodec::kH264:
56 case VideoCodec::kVP8:
57 // Normalize to three threads for 1080p content, then scale linearly
58 // with number of pixels.
63 // anything lower than 1080p: 2 threads
64 desired_threads = config.coded_size().width() *
65 config.coded_size().height() * 3 / 1920 / 1080;
68 return VideoDecoder::GetRecommendedThreadCount(desired_threads);
71 static int GetVideoBufferImpl(struct AVCodecContext* s,
74 FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque);
75 return decoder->GetVideoBuffer(s, frame, flags);
78 static void ReleaseVideoBufferImpl(void* opaque, uint8_t* data) {
80 static_cast<VideoFrame*>(opaque)->Release();
84 bool FFmpegVideoDecoder::IsCodecSupported(VideoCodec codec) {
85 return avcodec_find_decoder(VideoCodecToCodecID(codec)) != nullptr;
89 SupportedVideoDecoderConfigs FFmpegVideoDecoder::SupportedConfigsForWebRTC() {
90 SupportedVideoDecoderConfigs supported_configs;
92 if (IsCodecSupported(VideoCodec::kH264)) {
93 supported_configs.emplace_back(/*profile_min=*/H264PROFILE_BASELINE,
94 /*profile_max=*/H264PROFILE_HIGH,
95 /*coded_size_min=*/kDefaultSwDecodeSizeMin,
96 /*coded_size_max=*/kDefaultSwDecodeSizeMax,
97 /*allow_encrypted=*/false,
98 /*require_encrypted=*/false);
100 if (IsCodecSupported(VideoCodec::kVP8)) {
101 supported_configs.emplace_back(/*profile_min=*/VP8PROFILE_ANY,
102 /*profile_max=*/VP8PROFILE_ANY,
103 /*coded_size_min=*/kDefaultSwDecodeSizeMin,
104 /*coded_size_max=*/kDefaultSwDecodeSizeMax,
105 /*allow_encrypted=*/false,
106 /*require_encrypted=*/false);
109 return supported_configs;
112 FFmpegVideoDecoder::FFmpegVideoDecoder(MediaLog* media_log)
113 : media_log_(media_log) {
114 DVLOG(1) << __func__;
115 DETACH_FROM_SEQUENCE(sequence_checker_);
118 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context,
121 // Don't use |codec_context_| here! With threaded decoding,
122 // it will contain unsynchronized width/height/pix_fmt values,
123 // whereas |codec_context| contains the current threads's
124 // updated width/height/pix_fmt, which can change for adaptive
126 const VideoPixelFormat format =
127 AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt);
129 if (format == PIXEL_FORMAT_UNKNOWN)
130 return AVERROR(EINVAL);
131 DCHECK(format == PIXEL_FORMAT_I420 || format == PIXEL_FORMAT_I422 ||
132 format == PIXEL_FORMAT_I444 || format == PIXEL_FORMAT_YUV420P9 ||
133 format == PIXEL_FORMAT_YUV420P10 || format == PIXEL_FORMAT_YUV422P9 ||
134 format == PIXEL_FORMAT_YUV422P10 || format == PIXEL_FORMAT_YUV444P9 ||
135 format == PIXEL_FORMAT_YUV444P10 || format == PIXEL_FORMAT_YUV420P12 ||
136 format == PIXEL_FORMAT_YUV422P12 || format == PIXEL_FORMAT_YUV444P12);
138 gfx::Size size(codec_context->width, codec_context->height);
139 const int ret = av_image_check_size(size.width(), size.height(), 0, NULL);
143 VideoAspectRatio aspect_ratio = config_.aspect_ratio();
144 if (!aspect_ratio.IsValid() && codec_context->sample_aspect_ratio.num > 0) {
146 VideoAspectRatio::PAR(codec_context->sample_aspect_ratio.num,
147 codec_context->sample_aspect_ratio.den);
149 gfx::Size natural_size = aspect_ratio.GetNaturalSize(gfx::Rect(size));
151 // FFmpeg has specific requirements on the allocation size of the frame. The
152 // following logic replicates FFmpeg's allocation strategy to ensure buffers
153 // are not overread / overwritten. See ff_init_buffer_info() for details.
155 // When lowres is non-zero, dimensions should be divided by 2^(lowres), but
156 // since we don't use this, just DCHECK that it's zero.
157 DCHECK_EQ(codec_context->lowres, 0);
158 gfx::Size coded_size(std::max(size.width(), codec_context->coded_width),
159 std::max(size.height(), codec_context->coded_height));
161 if (force_allocation_error_)
162 return AVERROR(EINVAL);
164 // FFmpeg expects the initial allocation to be zero-initialized. Failure to
165 // do so can lead to uninitialized value usage. See http://crbug.com/390941
166 scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame(
167 format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp);
170 return AVERROR(EINVAL);
172 // Prefer the color space from the codec context. If it's not specified (or is
173 // set to an unsupported value), fall back on the value from the config.
174 VideoColorSpace color_space = AVColorSpaceToColorSpace(
175 codec_context->colorspace, codec_context->color_range);
176 if (!color_space.IsSpecified())
177 color_space = config_.color_space_info();
178 video_frame->set_color_space(color_space.ToGfxColorSpace());
180 if (codec_context->codec_id == AV_CODEC_ID_VP8 &&
181 codec_context->color_primaries == AVCOL_PRI_UNSPECIFIED &&
182 codec_context->color_trc == AVCOL_TRC_UNSPECIFIED &&
183 codec_context->colorspace == AVCOL_SPC_BT470BG) {
184 // vp8 has no colorspace information, except for the color range.
185 // However, because of a comment in the vp8 spec, ffmpeg sets the
186 // colorspace to BT470BG. We detect this and treat it as unset.
187 // If the color range is set to full range, we use the jpeg color space.
188 if (codec_context->color_range == AVCOL_RANGE_JPEG) {
189 video_frame->set_color_space(gfx::ColorSpace::CreateJpeg());
191 } else if (codec_context->codec_id == AV_CODEC_ID_H264 &&
192 codec_context->colorspace == AVCOL_SPC_RGB &&
193 format == PIXEL_FORMAT_I420) {
194 // Some H.264 videos contain a VUI that specifies a color matrix of GBR,
195 // when they are actually ordinary YUV. Only 4:2:0 formats are checked,
196 // because GBR is reasonable for 4:4:4 content. See crbug.com/1067377.
197 video_frame->set_color_space(gfx::ColorSpace::CreateREC709());
198 } else if (codec_context->color_primaries != AVCOL_PRI_UNSPECIFIED ||
199 codec_context->color_trc != AVCOL_TRC_UNSPECIFIED ||
200 codec_context->colorspace != AVCOL_SPC_UNSPECIFIED) {
201 media::VideoColorSpace video_color_space = media::VideoColorSpace(
202 codec_context->color_primaries, codec_context->color_trc,
203 codec_context->colorspace,
204 codec_context->color_range != AVCOL_RANGE_MPEG
205 ? gfx::ColorSpace::RangeID::FULL
206 : gfx::ColorSpace::RangeID::LIMITED);
207 video_frame->set_color_space(video_color_space.ToGfxColorSpace());
210 for (size_t i = 0; i < VideoFrame::NumPlanes(video_frame->format()); i++) {
211 frame->data[i] = video_frame->writable_data(i);
212 frame->linesize[i] = video_frame->stride(i);
215 frame->width = coded_size.width();
216 frame->height = coded_size.height();
217 frame->format = codec_context->pix_fmt;
218 frame->reordered_opaque = codec_context->reordered_opaque;
220 // Now create an AVBufferRef for the data just allocated. It will own the
221 // reference to the VideoFrame object.
222 VideoFrame* opaque = video_frame.get();
225 av_buffer_create(frame->data[0],
226 VideoFrame::AllocationSize(format, coded_size),
227 ReleaseVideoBufferImpl,
233 VideoDecoderType FFmpegVideoDecoder::GetDecoderType() const {
234 return VideoDecoderType::kFFmpeg;
237 void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
239 CdmContext* /* cdm_context */,
241 const OutputCB& output_cb,
242 const WaitingCB& /* waiting_cb */) {
243 DVLOG(1) << __func__ << ": " << config.AsHumanReadableString();
244 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
245 DCHECK(config.IsValidConfig());
248 InitCB bound_init_cb = BindToCurrentLoop(std::move(init_cb));
250 if (config.is_encrypted()) {
251 std::move(bound_init_cb)
252 .Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
256 if (!ConfigureDecoder(config, low_delay)) {
257 std::move(bound_init_cb).Run(DecoderStatus::Codes::kUnsupportedConfig);
263 output_cb_ = output_cb;
264 state_ = DecoderState::kNormal;
265 std::move(bound_init_cb).Run(DecoderStatus::Codes::kOk);
268 void FFmpegVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
269 DecodeCB decode_cb) {
270 DVLOG(3) << __func__;
271 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
272 DCHECK(buffer.get());
274 CHECK_NE(state_, DecoderState::kUninitialized);
276 DecodeCB decode_cb_bound = BindToCurrentLoop(std::move(decode_cb));
278 if (state_ == DecoderState::kError) {
279 std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
283 if (state_ == DecoderState::kDecodeFinished) {
284 std::move(decode_cb_bound).Run(DecoderStatus::Codes::kOk);
288 DCHECK_EQ(state_, DecoderState::kNormal);
290 // During decode, because reads are issued asynchronously, it is possible to
291 // receive multiple end of stream buffers since each decode is acked. There
292 // are three states the decoder can be in:
294 // DecoderState::kNormal: This is the starting state. Buffers are decoded.
295 // Decode errors are discarded.
296 // DecoderState::kDecodeFinished: All calls return empty frames.
297 // DecoderState::kError: Unexpected error happened.
299 // These are the possible state transitions.
301 // DecoderState::kNormal -> DecoderState::kDecodeFinished:
302 // When EOS buffer is received and the codec has been flushed.
303 // DecoderState::kNormal -> DecoderState::kError:
304 // A decoding error occurs and decoding needs to stop.
305 // (any state) -> DecoderState::kNormal:
306 // Any time Reset() is called.
308 if (!FFmpegDecode(*buffer)) {
309 state_ = DecoderState::kError;
310 std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
314 if (buffer->end_of_stream())
315 state_ = DecoderState::kDecodeFinished;
317 // VideoDecoderShim expects that |decode_cb| is called only after
319 std::move(decode_cb_bound).Run(DecoderStatus::Codes::kOk);
322 void FFmpegVideoDecoder::Reset(base::OnceClosure closure) {
323 DVLOG(2) << __func__;
324 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
326 avcodec_flush_buffers(codec_context_.get());
327 state_ = DecoderState::kNormal;
328 // PostTask() to avoid calling |closure| immediately.
329 base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
333 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
334 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
336 if (state_ != DecoderState::kUninitialized)
337 ReleaseFFmpegResources();
340 bool FFmpegVideoDecoder::FFmpegDecode(const DecoderBuffer& buffer) {
341 // Create a packet for input data.
342 // Due to FFmpeg API changes we no longer have const read-only pointers.
343 // av_init_packet is deprecated and being removed, and ffmpeg clearly does
344 // not want to allow on-stack allocation of AVPackets.
345 AVPacket* packet = av_packet_alloc();
346 if (buffer.end_of_stream()) {
350 packet->data = const_cast<uint8_t*>(buffer.data());
351 packet->size = buffer.data_size();
353 DCHECK(packet->data);
354 DCHECK_GT(packet->size, 0);
356 // Let FFmpeg handle presentation timestamp reordering.
357 codec_context_->reordered_opaque = buffer.timestamp().InMicroseconds();
359 FFmpegDecodingLoop::DecodeStatus decode_status = decoding_loop_->DecodePacket(
360 packet, base::BindRepeating(&FFmpegVideoDecoder::OnNewFrame,
361 base::Unretained(this)));
362 av_packet_free(&packet);
363 switch (decode_status) {
364 case FFmpegDecodingLoop::DecodeStatus::kSendPacketFailed:
365 MEDIA_LOG(ERROR, media_log_)
366 << "Failed to send video packet for decoding: "
367 << buffer.AsHumanReadableString();
369 case FFmpegDecodingLoop::DecodeStatus::kFrameProcessingFailed:
370 // OnNewFrame() should have already issued a MEDIA_LOG for this.
372 case FFmpegDecodingLoop::DecodeStatus::kDecodeFrameFailed:
373 MEDIA_LOG(DEBUG, media_log_)
374 << GetDecoderType() << " failed to decode a video frame: "
375 << AVErrorToString(decoding_loop_->last_averror_code()) << ", at "
376 << buffer.AsHumanReadableString();
378 case FFmpegDecodingLoop::DecodeStatus::kOkay:
385 bool FFmpegVideoDecoder::OnNewFrame(AVFrame* frame) {
386 // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
387 // The decoder is in a bad state and not decoding correctly.
388 // Checking for NULL avoids a crash in CopyPlane().
389 if (!frame->data[VideoFrame::kYPlane] || !frame->data[VideoFrame::kUPlane] ||
390 !frame->data[VideoFrame::kVPlane]) {
391 DLOG(ERROR) << "Video frame was produced yet has invalid frame data.";
395 scoped_refptr<VideoFrame> video_frame =
396 reinterpret_cast<VideoFrame*>(av_buffer_get_opaque(frame->buf[0]));
397 video_frame->set_timestamp(base::Microseconds(frame->reordered_opaque));
398 video_frame->metadata().power_efficient = false;
399 output_cb_.Run(video_frame);
403 void FFmpegVideoDecoder::ReleaseFFmpegResources() {
404 decoding_loop_.reset();
405 codec_context_.reset();
408 bool FFmpegVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config,
410 DCHECK(config.IsValidConfig());
411 DCHECK(!config.is_encrypted());
413 // Release existing decoder resources if necessary.
414 ReleaseFFmpegResources();
416 // Initialize AVCodecContext structure.
417 codec_context_.reset(avcodec_alloc_context3(NULL));
418 VideoDecoderConfigToAVCodecContext(config, codec_context_.get());
420 codec_context_->thread_count = GetFFmpegVideoDecoderThreadCount(config);
421 codec_context_->thread_type =
422 FF_THREAD_SLICE | (low_delay ? 0 : FF_THREAD_FRAME);
423 codec_context_->opaque = this;
424 codec_context_->get_buffer2 = GetVideoBufferImpl;
427 codec_context_->flags2 |= AV_CODEC_FLAG2_CHUNKS;
429 const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
430 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
431 ReleaseFFmpegResources();
435 decoding_loop_ = std::make_unique<FFmpegDecodingLoop>(codec_context_.get());