Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / ffmpeg_video_decoder.cc
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.
4
5 #include "media/filters/ffmpeg_video_decoder.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <algorithm>
11 #include <memory>
12
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"
28
29 namespace media {
30
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;
36
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.
48       break;
49
50     case VideoCodec::kTheora:
51     case VideoCodec::kMPEG4:
52       // No extra threads for these codecs.
53       break;
54
55     case VideoCodec::kH264:
56     case VideoCodec::kVP8:
57       // Normalize to three threads for 1080p content, then scale linearly
58       // with number of pixels.
59       // Examples:
60       // 4k: 12 threads
61       // 1440p: 5 threads
62       // 1080p: 3 threads
63       // anything lower than 1080p: 2 threads
64       desired_threads = config.coded_size().width() *
65                         config.coded_size().height() * 3 / 1920 / 1080;
66   }
67
68   return VideoDecoder::GetRecommendedThreadCount(desired_threads);
69 }
70
71 static int GetVideoBufferImpl(struct AVCodecContext* s,
72                               AVFrame* frame,
73                               int flags) {
74   FFmpegVideoDecoder* decoder = static_cast<FFmpegVideoDecoder*>(s->opaque);
75   return decoder->GetVideoBuffer(s, frame, flags);
76 }
77
78 static void ReleaseVideoBufferImpl(void* opaque, uint8_t* data) {
79   if (opaque)
80     static_cast<VideoFrame*>(opaque)->Release();
81 }
82
83 // static
84 bool FFmpegVideoDecoder::IsCodecSupported(VideoCodec codec) {
85   return avcodec_find_decoder(VideoCodecToCodecID(codec)) != nullptr;
86 }
87
88 // static
89 SupportedVideoDecoderConfigs FFmpegVideoDecoder::SupportedConfigsForWebRTC() {
90   SupportedVideoDecoderConfigs supported_configs;
91
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);
99   }
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);
107   }
108
109   return supported_configs;
110 }
111
112 FFmpegVideoDecoder::FFmpegVideoDecoder(MediaLog* media_log)
113     : media_log_(media_log) {
114   DVLOG(1) << __func__;
115   DETACH_FROM_SEQUENCE(sequence_checker_);
116 }
117
118 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context,
119                                        AVFrame* frame,
120                                        int flags) {
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
125   // content.
126   const VideoPixelFormat format =
127       AVPixelFormatToVideoPixelFormat(codec_context->pix_fmt);
128
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);
137
138   gfx::Size size(codec_context->width, codec_context->height);
139   const int ret = av_image_check_size(size.width(), size.height(), 0, NULL);
140   if (ret < 0)
141     return ret;
142
143   VideoAspectRatio aspect_ratio = config_.aspect_ratio();
144   if (!aspect_ratio.IsValid() && codec_context->sample_aspect_ratio.num > 0) {
145     aspect_ratio =
146         VideoAspectRatio::PAR(codec_context->sample_aspect_ratio.num,
147                               codec_context->sample_aspect_ratio.den);
148   }
149   gfx::Size natural_size = aspect_ratio.GetNaturalSize(gfx::Rect(size));
150
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.
154   //
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));
160
161   if (force_allocation_error_)
162     return AVERROR(EINVAL);
163
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);
168
169   if (!video_frame)
170     return AVERROR(EINVAL);
171
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());
179
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());
190     }
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());
208   }
209
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);
213   }
214
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;
219
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();
223   opaque->AddRef();
224   frame->buf[0] =
225       av_buffer_create(frame->data[0],
226                        VideoFrame::AllocationSize(format, coded_size),
227                        ReleaseVideoBufferImpl,
228                        opaque,
229                        0);
230   return 0;
231 }
232
233 VideoDecoderType FFmpegVideoDecoder::GetDecoderType() const {
234   return VideoDecoderType::kFFmpeg;
235 }
236
237 void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
238                                     bool low_delay,
239                                     CdmContext* /* cdm_context */,
240                                     InitCB init_cb,
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());
246   DCHECK(output_cb);
247
248   InitCB bound_init_cb = BindToCurrentLoop(std::move(init_cb));
249
250   if (config.is_encrypted()) {
251     std::move(bound_init_cb)
252         .Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
253     return;
254   }
255
256   if (!ConfigureDecoder(config, low_delay)) {
257     std::move(bound_init_cb).Run(DecoderStatus::Codes::kUnsupportedConfig);
258     return;
259   }
260
261   // Success!
262   config_ = config;
263   output_cb_ = output_cb;
264   state_ = DecoderState::kNormal;
265   std::move(bound_init_cb).Run(DecoderStatus::Codes::kOk);
266 }
267
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());
273   DCHECK(decode_cb);
274   CHECK_NE(state_, DecoderState::kUninitialized);
275
276   DecodeCB decode_cb_bound = BindToCurrentLoop(std::move(decode_cb));
277
278   if (state_ == DecoderState::kError) {
279     std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
280     return;
281   }
282
283   if (state_ == DecoderState::kDecodeFinished) {
284     std::move(decode_cb_bound).Run(DecoderStatus::Codes::kOk);
285     return;
286   }
287
288   DCHECK_EQ(state_, DecoderState::kNormal);
289
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:
293   //
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.
298   //
299   // These are the possible state transitions.
300   //
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.
307
308   if (!FFmpegDecode(*buffer)) {
309     state_ = DecoderState::kError;
310     std::move(decode_cb_bound).Run(DecoderStatus::Codes::kFailed);
311     return;
312   }
313
314   if (buffer->end_of_stream())
315     state_ = DecoderState::kDecodeFinished;
316
317   // VideoDecoderShim expects that |decode_cb| is called only after
318   // |output_cb_|.
319   std::move(decode_cb_bound).Run(DecoderStatus::Codes::kOk);
320 }
321
322 void FFmpegVideoDecoder::Reset(base::OnceClosure closure) {
323   DVLOG(2) << __func__;
324   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
325
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,
330                                                    std::move(closure));
331 }
332
333 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
334   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
335
336   if (state_ != DecoderState::kUninitialized)
337     ReleaseFFmpegResources();
338 }
339
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()) {
347     packet->data = NULL;
348     packet->size = 0;
349   } else {
350     packet->data = const_cast<uint8_t*>(buffer.data());
351     packet->size = buffer.data_size();
352
353     DCHECK(packet->data);
354     DCHECK_GT(packet->size, 0);
355
356     // Let FFmpeg handle presentation timestamp reordering.
357     codec_context_->reordered_opaque = buffer.timestamp().InMicroseconds();
358   }
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();
368       return false;
369     case FFmpegDecodingLoop::DecodeStatus::kFrameProcessingFailed:
370       // OnNewFrame() should have already issued a MEDIA_LOG for this.
371       return false;
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();
377       return false;
378     case FFmpegDecodingLoop::DecodeStatus::kOkay:
379       break;
380   }
381
382   return true;
383 }
384
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.";
392     return false;
393   }
394
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);
400   return true;
401 }
402
403 void FFmpegVideoDecoder::ReleaseFFmpegResources() {
404   decoding_loop_.reset();
405   codec_context_.reset();
406 }
407
408 bool FFmpegVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config,
409                                           bool low_delay) {
410   DCHECK(config.IsValidConfig());
411   DCHECK(!config.is_encrypted());
412
413   // Release existing decoder resources if necessary.
414   ReleaseFFmpegResources();
415
416   // Initialize AVCodecContext structure.
417   codec_context_.reset(avcodec_alloc_context3(NULL));
418   VideoDecoderConfigToAVCodecContext(config, codec_context_.get());
419
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;
425
426   if (decode_nalus_)
427     codec_context_->flags2 |= AV_CODEC_FLAG2_CHUNKS;
428
429   const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
430   if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
431     ReleaseFFmpegResources();
432     return false;
433   }
434
435   decoding_loop_ = std::make_unique<FFmpegDecodingLoop>(codec_context_.get());
436   return true;
437 }
438
439 }  // namespace media