1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/filters/ffmpeg_video_decoder.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <algorithm>
11 
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/location.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/threading/sequenced_task_runner_handle.h"
17 #include "media/base/bind_to_current_loop.h"
18 #include "media/base/decoder_buffer.h"
19 #include "media/base/limits.h"
20 #include "media/base/media_log.h"
21 #include "media/base/timestamp_constants.h"
22 #include "media/base/video_frame.h"
23 #include "media/base/video_util.h"
24 #include "media/ffmpeg/ffmpeg_common.h"
25 #include "media/ffmpeg/ffmpeg_decoding_loop.h"
26 
27 namespace media {
28 
29 // Returns the number of threads given the FFmpeg CodecID. Also inspects the
30 // command line for a valid --video-threads flag.
GetFFmpegVideoDecoderThreadCount(const VideoDecoderConfig & config)31 static int GetFFmpegVideoDecoderThreadCount(const VideoDecoderConfig& config) {
32   // Most codecs are so old that more threads aren't really needed.
33   int desired_threads = limits::kMinVideoDecodeThreads;
34 
35   // Some ffmpeg codecs don't actually benefit from using more threads.
36   // Only add more threads for those codecs that we know will benefit.
37   switch (config.codec()) {
38     case kUnknownVideoCodec:
39     case kCodecVC1:
40     case kCodecMPEG2:
41     case kCodecHEVC:
42     case kCodecVP9:
43     case kCodecAV1:
44     case kCodecDolbyVision:
45       // We do not compile ffmpeg with support for any of these codecs.
46       break;
47 
48     case kCodecTheora:
49     case kCodecMPEG4:
50       // No extra threads for these codecs.
51       break;
52 
53     case kCodecH264:
54     case kCodecVP8:
55       // Normalize to three threads for 1080p content, then scale linearly
56       // with number of pixels.
57       // Examples:
58       // 4k: 12 threads
59       // 1440p: 5 threads
60       // 1080p: 3 threads
61       // anything lower than 1080p: 2 threads
62       desired_threads = config.coded_size().width() *
63                         config.coded_size().height() * 3 / 1920 / 1080;
64   }
65 
66   return VideoDecoder::GetRecommendedThreadCount(desired_threads);
67 }
68 
GetVideoBufferImpl(struct AVCodecContext * s,AVFrame * frame,int flags)69 static int GetVideoBufferImpl(struct AVCodecContext* s,
70                               AVFrame* frame,
71                               int flags) {
72   FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque);
73   return decoder->GetVideoBuffer(s, frame, flags);
74 }
75 
ReleaseVideoBufferImpl(void * opaque,uint8_t * data)76 static void ReleaseVideoBufferImpl(void* opaque, uint8_t* data) {
77   if (opaque)
78     static_cast<VideoFrame*>(opaque)->Release();
79 }
80 
81 // static
IsCodecSupported(VideoCodec codec)82 bool FFmpegVideoDecoder::IsCodecSupported(VideoCodec codec) {
83   return avcodec_find_decoder(VideoCodecToCodecID(codec)) != nullptr;
84 }
85 
FFmpegVideoDecoder(MediaLog * media_log)86 FFmpegVideoDecoder::FFmpegVideoDecoder(MediaLog* media_log)
87     : media_log_(media_log), state_(kUninitialized), decode_nalus_(false) {
88   DVLOG(1) << __func__;
89   DETACH_FROM_SEQUENCE(sequence_checker_);
90 }
91 
GetVideoBuffer(struct AVCodecContext * codec_context,AVFrame * frame,int flags)92 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context,
93                                        AVFrame* frame,
94                                        int flags) {
95   // Don't use |codec_context_| here! With threaded decoding,
96   // it will contain unsynchronized width/height/pix_fmt values,
97   // whereas |codec_context| contains the current threads's
98   // updated width/height/pix_fmt, which can change for adaptive
99   // content.
100   const VideoPixelFormat format =
101       AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt);
102 
103   if (format == PIXEL_FORMAT_UNKNOWN)
104     return AVERROR(EINVAL);
105   DCHECK(format == PIXEL_FORMAT_I420 || format == PIXEL_FORMAT_I422 ||
106          format == PIXEL_FORMAT_I444 || format == PIXEL_FORMAT_YUV420P9 ||
107          format == PIXEL_FORMAT_YUV420P10 || format == PIXEL_FORMAT_YUV422P9 ||
108          format == PIXEL_FORMAT_YUV422P10 || format == PIXEL_FORMAT_YUV444P9 ||
109          format == PIXEL_FORMAT_YUV444P10 || format == PIXEL_FORMAT_YUV420P12 ||
110          format == PIXEL_FORMAT_YUV422P12 || format == PIXEL_FORMAT_YUV444P12);
111 
112   gfx::Size size(codec_context->width, codec_context->height);
113   const int ret = av_image_check_size(size.width(), size.height(), 0, NULL);
114   if (ret < 0)
115     return ret;
116 
117   gfx::Size natural_size;
118   if (codec_context->sample_aspect_ratio.num > 0) {
119     natural_size = GetNaturalSize(size,
120                                   codec_context->sample_aspect_ratio.num,
121                                   codec_context->sample_aspect_ratio.den);
122   } else {
123     natural_size =
124         GetNaturalSize(gfx::Rect(size), config_.GetPixelAspectRatio());
125   }
126 
127   // FFmpeg has specific requirements on the allocation size of the frame.  The
128   // following logic replicates FFmpeg's allocation strategy to ensure buffers
129   // are not overread / overwritten.  See ff_init_buffer_info() for details.
130   //
131   // When lowres is non-zero, dimensions should be divided by 2^(lowres), but
132   // since we don't use this, just DCHECK that it's zero.
133   DCHECK_EQ(codec_context->lowres, 0);
134   gfx::Size coded_size(std::max(size.width(), codec_context->coded_width),
135                        std::max(size.height(), codec_context->coded_height));
136 
137   // FFmpeg expects the initial allocation to be zero-initialized.  Failure to
138   // do so can lead to uninitialized value usage.  See http://crbug.com/390941
139   scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame(
140       format, coded_size, gfx::Rect(size), natural_size, kNoTimestamp);
141 
142   if (!video_frame)
143     return AVERROR(EINVAL);
144 
145   // Prefer the color space from the codec context. If it's not specified (or is
146   // set to an unsupported value), fall back on the value from the config.
147   VideoColorSpace color_space = AVColorSpaceToColorSpace(
148       codec_context->colorspace, codec_context->color_range);
149   if (!color_space.IsSpecified())
150     color_space = config_.color_space_info();
151   video_frame->set_color_space(color_space.ToGfxColorSpace());
152 
153   if (codec_context->codec_id == AV_CODEC_ID_VP8 &&
154       codec_context->color_primaries == AVCOL_PRI_UNSPECIFIED &&
155       codec_context->color_trc == AVCOL_TRC_UNSPECIFIED &&
156       codec_context->colorspace == AVCOL_SPC_BT470BG) {
157     // vp8 has no colorspace information, except for the color range.
158     // However, because of a comment in the vp8 spec, ffmpeg sets the
159     // colorspace to BT470BG. We detect this and treat it as unset.
160     // If the color range is set to full range, we use the jpeg color space.
161     if (codec_context->color_range == AVCOL_RANGE_JPEG) {
162       video_frame->set_color_space(gfx::ColorSpace::CreateJpeg());
163     }
164   } else if (codec_context->color_primaries != AVCOL_PRI_UNSPECIFIED ||
165              codec_context->color_trc != AVCOL_TRC_UNSPECIFIED ||
166              codec_context->colorspace != AVCOL_SPC_UNSPECIFIED) {
167     media::VideoColorSpace video_color_space = media::VideoColorSpace(
168         codec_context->color_primaries, codec_context->color_trc,
169         codec_context->colorspace,
170         codec_context->color_range != AVCOL_RANGE_MPEG
171             ? gfx::ColorSpace::RangeID::FULL
172             : gfx::ColorSpace::RangeID::LIMITED);
173     video_frame->set_color_space(video_color_space.ToGfxColorSpace());
174   }
175 
176   for (size_t i = 0; i < VideoFrame::NumPlanes(video_frame->format()); i++) {
177     frame->data[i] = video_frame->data(i);
178     frame->linesize[i] = video_frame->stride(i);
179   }
180 
181   frame->width = coded_size.width();
182   frame->height = coded_size.height();
183   frame->format = codec_context->pix_fmt;
184   frame->reordered_opaque = codec_context->reordered_opaque;
185 
186   // Now create an AVBufferRef for the data just allocated. It will own the
187   // reference to the VideoFrame object.
188   VideoFrame* opaque = video_frame.get();
189   opaque->AddRef();
190   frame->buf[0] =
191       av_buffer_create(frame->data[0],
192                        VideoFrame::AllocationSize(format, coded_size),
193                        ReleaseVideoBufferImpl,
194                        opaque,
195                        0);
196   return 0;
197 }
198 
GetDisplayName() const199 std::string FFmpegVideoDecoder::GetDisplayName() const {
200   return "FFmpegVideoDecoder";
201 }
202 
Initialize(const VideoDecoderConfig & config,bool low_delay,CdmContext *,InitCB init_cb,const OutputCB & output_cb,const WaitingCB &)203 void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
204                                     bool low_delay,
205                                     CdmContext* /* cdm_context */,
206                                     InitCB init_cb,
207                                     const OutputCB& output_cb,
208                                     const WaitingCB& /* waiting_cb */) {
209   DVLOG(1) << __func__ << ": " << config.AsHumanReadableString();
210   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
211   DCHECK(config.IsValidConfig());
212   DCHECK(output_cb);
213 
214   InitCB bound_init_cb = BindToCurrentLoop(std::move(init_cb));
215 
216   if (config.is_encrypted()) {
217     std::move(bound_init_cb).Run(StatusCode::kEncryptedContentUnsupported);
218     return;
219   }
220 
221   if (!ConfigureDecoder(config, low_delay)) {
222     std::move(bound_init_cb).Run(StatusCode::kDecoderFailedInitialization);
223     return;
224   }
225 
226   // Success!
227   config_ = config;
228   output_cb_ = output_cb;
229   state_ = kNormal;
230   std::move(bound_init_cb).Run(OkStatus());
231 }
232 
Decode(scoped_refptr<DecoderBuffer> buffer,DecodeCB decode_cb)233 void FFmpegVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
234                                 DecodeCB decode_cb) {
235   DVLOG(3) << __func__;
236   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
237   DCHECK(buffer.get());
238   DCHECK(decode_cb);
239   CHECK_NE(state_, kUninitialized);
240 
241   DecodeCB decode_cb_bound = BindToCurrentLoop(std::move(decode_cb));
242 
243   if (state_ == kError) {
244     std::move(decode_cb_bound).Run(DecodeStatus::DECODE_ERROR);
245     return;
246   }
247 
248   if (state_ == kDecodeFinished) {
249     std::move(decode_cb_bound).Run(DecodeStatus::OK);
250     return;
251   }
252 
253   DCHECK_EQ(state_, kNormal);
254 
255   // During decode, because reads are issued asynchronously, it is possible to
256   // receive multiple end of stream buffers since each decode is acked. There
257   // are three states the decoder can be in:
258   //
259   //   kNormal: This is the starting state. Buffers are decoded. Decode errors
260   //            are discarded.
261   //   kDecodeFinished: All calls return empty frames.
262   //   kError: Unexpected error happened.
263   //
264   // These are the possible state transitions.
265   //
266   // kNormal -> kDecodeFinished:
267   //     When EOS buffer is received and the codec has been flushed.
268   // kNormal -> kError:
269   //     A decoding error occurs and decoding needs to stop.
270   // (any state) -> kNormal:
271   //     Any time Reset() is called.
272 
273   if (!FFmpegDecode(*buffer)) {
274     state_ = kError;
275     std::move(decode_cb_bound).Run(DecodeStatus::DECODE_ERROR);
276     return;
277   }
278 
279   if (buffer->end_of_stream())
280     state_ = kDecodeFinished;
281 
282   // VideoDecoderShim expects that |decode_cb| is called only after
283   // |output_cb_|.
284   std::move(decode_cb_bound).Run(DecodeStatus::OK);
285 }
286 
Reset(base::OnceClosure closure)287 void FFmpegVideoDecoder::Reset(base::OnceClosure closure) {
288   DVLOG(2) << __func__;
289   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
290 
291   avcodec_flush_buffers(codec_context_.get());
292   state_ = kNormal;
293   // PostTask() to avoid calling |closure| immediately.
294   base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
295                                                    std::move(closure));
296 }
297 
~FFmpegVideoDecoder()298 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
299   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
300 
301   if (state_ != kUninitialized)
302     ReleaseFFmpegResources();
303 }
304 
FFmpegDecode(const DecoderBuffer & buffer)305 bool FFmpegVideoDecoder::FFmpegDecode(const DecoderBuffer& buffer) {
306   // Create a packet for input data.
307   // Due to FFmpeg API changes we no longer have const read-only pointers.
308   AVPacket packet;
309   av_init_packet(&packet);
310   if (buffer.end_of_stream()) {
311     packet.data = NULL;
312     packet.size = 0;
313   } else {
314     packet.data = const_cast<uint8_t*>(buffer.data());
315     packet.size = buffer.data_size();
316 
317     DCHECK(packet.data);
318     DCHECK_GT(packet.size, 0);
319 
320     // Let FFmpeg handle presentation timestamp reordering.
321     codec_context_->reordered_opaque = buffer.timestamp().InMicroseconds();
322   }
323 
324   switch (decoding_loop_->DecodePacket(
325       &packet, base::BindRepeating(&FFmpegVideoDecoder::OnNewFrame,
326                                    base::Unretained(this)))) {
327     case FFmpegDecodingLoop::DecodeStatus::kSendPacketFailed:
328       MEDIA_LOG(ERROR, media_log_)
329           << "Failed to send video packet for decoding: "
330           << buffer.AsHumanReadableString();
331       return false;
332     case FFmpegDecodingLoop::DecodeStatus::kFrameProcessingFailed:
333       // OnNewFrame() should have already issued a MEDIA_LOG for this.
334       return false;
335     case FFmpegDecodingLoop::DecodeStatus::kDecodeFrameFailed:
336       MEDIA_LOG(DEBUG, media_log_)
337           << GetDisplayName() << " failed to decode a video frame: "
338           << AVErrorToString(decoding_loop_->last_averror_code()) << ", at "
339           << buffer.AsHumanReadableString();
340       return false;
341     case FFmpegDecodingLoop::DecodeStatus::kOkay:
342       break;
343   }
344 
345   return true;
346 }
347 
OnNewFrame(AVFrame * frame)348 bool FFmpegVideoDecoder::OnNewFrame(AVFrame* frame) {
349   // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675
350   // The decoder is in a bad state and not decoding correctly.
351   // Checking for NULL avoids a crash in CopyPlane().
352   if (!frame->data[VideoFrame::kYPlane] || !frame->data[VideoFrame::kUPlane] ||
353       !frame->data[VideoFrame::kVPlane]) {
354     DLOG(ERROR) << "Video frame was produced yet has invalid frame data.";
355     return false;
356   }
357 
358   scoped_refptr<VideoFrame> video_frame =
359       reinterpret_cast<VideoFrame*>(av_buffer_get_opaque(frame->buf[0]));
360   video_frame->set_timestamp(
361       base::TimeDelta::FromMicroseconds(frame->reordered_opaque));
362   video_frame->metadata()->power_efficient = false;
363   output_cb_.Run(video_frame);
364   return true;
365 }
366 
ReleaseFFmpegResources()367 void FFmpegVideoDecoder::ReleaseFFmpegResources() {
368   decoding_loop_.reset();
369   codec_context_.reset();
370 }
371 
ConfigureDecoder(const VideoDecoderConfig & config,bool low_delay)372 bool FFmpegVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config,
373                                           bool low_delay) {
374   DCHECK(config.IsValidConfig());
375   DCHECK(!config.is_encrypted());
376 
377   // Release existing decoder resources if necessary.
378   ReleaseFFmpegResources();
379 
380   // Initialize AVCodecContext structure.
381   codec_context_.reset(avcodec_alloc_context3(NULL));
382   VideoDecoderConfigToAVCodecContext(config, codec_context_.get());
383 
384   codec_context_->thread_count = GetFFmpegVideoDecoderThreadCount(config);
385   codec_context_->thread_type =
386       FF_THREAD_SLICE | (low_delay ? 0 : FF_THREAD_FRAME);
387   codec_context_->opaque = this;
388   codec_context_->get_buffer2 = GetVideoBufferImpl;
389 
390   if (decode_nalus_)
391     codec_context_->flags2 |= AV_CODEC_FLAG2_CHUNKS;
392 
393   AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
394   if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
395     ReleaseFFmpegResources();
396     return false;
397   }
398 
399   decoding_loop_.reset(new FFmpegDecodingLoop(codec_context_.get()));
400   return true;
401 }
402 
403 }  // namespace media
404