blob: b2d3de0cf0fc2c75c0246bfaf88c7284e317f555 [file] [log] [blame]
Chih-Yu Huangde529a82019-06-06 03:26:091// Copyright 2019 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/gpu/v4l2/v4l2_slice_video_decoder.h"
6
7#include <algorithm>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/logging.h"
12#include "base/memory/ptr_util.h"
13#include "base/task/post_task.h"
14#include "media/base/scopedfd_helper.h"
Chih-Yu Huangf4635892019-07-11 14:20:2915#include "media/base/video_util.h"
Chih-Yu Huangde529a82019-06-06 03:26:0916#include "media/gpu/accelerated_video_decoder.h"
Chih-Yu Huanga4bf8342019-06-27 04:03:4417#include "media/gpu/gpu_video_decode_accelerator_helpers.h"
Yuchen Liu241d1c82019-07-16 01:50:1018#include "media/gpu/linux/dmabuf_video_frame_pool.h"
Chih-Yu Huangde529a82019-06-06 03:26:0919#include "media/gpu/macros.h"
Alexandre Courbot447e1f682019-08-20 07:54:5620#include "media/gpu/v4l2/v4l2_h264_accelerator_legacy.h"
Alexandre Courbotd7482212019-09-03 07:39:2121#include "media/gpu/v4l2/v4l2_vp8_accelerator_legacy.h"
Chih-Yu Huangde529a82019-06-06 03:26:0922#include "media/gpu/v4l2/v4l2_vp9_accelerator.h"
Chih-Yu Huangde529a82019-06-06 03:26:0923
24namespace media {
25
26namespace {
27
28// See http://crbug.com/255116.
29constexpr int k1080pArea = 1920 * 1088;
30// Input bitstream buffer size for up to 1080p streams.
31constexpr size_t kInputBufferMaxSizeFor1080p = 1024 * 1024;
32// Input bitstream buffer size for up to 4k streams.
33constexpr size_t kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p;
34constexpr size_t kNumInputBuffers = 16;
35constexpr size_t kNumInputPlanes = 1;
36
David Staessens59766d62019-09-06 04:24:4637// Size of the timestamp cache, needs to be large enough for frame-reordering.
38constexpr size_t kTimestampCacheSize = 128;
39
Chih-Yu Huanga4bf8342019-06-27 04:03:4440// Input format V4L2 fourccs this class supports.
41constexpr uint32_t kSupportedInputFourccs[] = {
42 V4L2_PIX_FMT_H264_SLICE,
43 V4L2_PIX_FMT_VP8_FRAME,
44 V4L2_PIX_FMT_VP9_FRAME,
45};
46
Hirokazu Hondac1f0a602019-06-12 11:09:2947// Checks an underlying video frame buffer of |frame| is valid for VIDIOC_DQBUF
48// that requires |target_num_fds| fds.
49bool IsValidFrameForQueueDMABuf(const VideoFrame* frame,
50 size_t target_num_fds) {
Chih-Yu Huangde529a82019-06-06 03:26:0951 DCHECK(frame);
52 if (frame->DmabufFds().size() < target_num_fds) {
53 VLOGF(1) << "The count of dmabuf fds (" << frame->DmabufFds().size()
54 << ") are not enough, needs " << target_num_fds << " fds.";
Hirokazu Hondac1f0a602019-06-12 11:09:2955 return false;
Chih-Yu Huangde529a82019-06-06 03:26:0956 }
57
58 const std::vector<VideoFrameLayout::Plane>& planes = frame->layout().planes();
59 for (size_t i = frame->DmabufFds().size() - 1; i >= target_num_fds; --i) {
60 // Assume that an fd is a duplicate of a previous plane's fd if offset != 0.
61 // Otherwise, if offset == 0, return error as surface_it may be pointing to
62 // a new plane.
63 if (planes[i].offset == 0) {
64 VLOGF(1) << "Additional dmabuf fds point to a new buffer.";
Hirokazu Hondac1f0a602019-06-12 11:09:2965 return false;
Chih-Yu Huangde529a82019-06-06 03:26:0966 }
67 }
68
Hirokazu Hondac1f0a602019-06-12 11:09:2969 return true;
Chih-Yu Huangde529a82019-06-06 03:26:0970}
71
72} // namespace
73
Alexandre Courbotfdd3b552019-08-05 08:55:0274V4L2SliceVideoDecoder::DecodeRequest::DecodeRequest(
75 scoped_refptr<DecoderBuffer> buf,
76 DecodeCB cb,
77 int32_t id)
78 : buffer(std::move(buf)), decode_cb(std::move(cb)), bitstream_id(id) {}
79
80V4L2SliceVideoDecoder::DecodeRequest::DecodeRequest(DecodeRequest&&) = default;
81V4L2SliceVideoDecoder::DecodeRequest& V4L2SliceVideoDecoder::DecodeRequest::
82operator=(DecodeRequest&&) = default;
83
84V4L2SliceVideoDecoder::DecodeRequest::~DecodeRequest() = default;
85
Chih-Yu Huangde529a82019-06-06 03:26:0986struct V4L2SliceVideoDecoder::OutputRequest {
87 enum OutputRequestType {
88 // The surface to be outputted.
89 kSurface,
90 // The fence to indicate the flush request.
91 kFlushFence,
92 // The fence to indicate resolution change request.
93 kChangeResolutionFence,
94 };
95
96 // The type of the request.
97 const OutputRequestType type;
98 // The surface to be outputted.
99 scoped_refptr<V4L2DecodeSurface> surface;
Chih-Yu Huangccf46032019-07-11 11:48:06100 // The timestamp of the output frame. Because a surface might be outputted
101 // multiple times with different timestamp, we need to store timestamp out of
102 // surface.
103 base::TimeDelta timestamp;
Chih-Yu Huangde529a82019-06-06 03:26:09104
Chih-Yu Huangccf46032019-07-11 11:48:06105 static OutputRequest Surface(scoped_refptr<V4L2DecodeSurface> s,
106 base::TimeDelta t) {
107 return OutputRequest(std::move(s), t);
Alexandre Courbot92afc8b72019-06-12 10:48:32108 }
109
110 static OutputRequest FlushFence() { return OutputRequest(kFlushFence); }
111
112 static OutputRequest ChangeResolutionFence() {
113 return OutputRequest(kChangeResolutionFence);
Chih-Yu Huangde529a82019-06-06 03:26:09114 }
115
116 bool IsReady() const {
117 return (type != OutputRequestType::kSurface) || surface->decoded();
118 }
Alexandre Courbot92afc8b72019-06-12 10:48:32119
120 // Allow move, but not copy.
121 OutputRequest(OutputRequest&&) = default;
122
123 private:
Chih-Yu Huangccf46032019-07-11 11:48:06124 OutputRequest(scoped_refptr<V4L2DecodeSurface> s, base::TimeDelta t)
125 : type(kSurface), surface(std::move(s)), timestamp(t) {}
Alexandre Courbot92afc8b72019-06-12 10:48:32126 explicit OutputRequest(OutputRequestType t) : type(t) {}
127
128 DISALLOW_COPY_AND_ASSIGN(OutputRequest);
Chih-Yu Huangde529a82019-06-06 03:26:09129};
130
131// static
132std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create(
133 scoped_refptr<base::SequencedTaskRunner> client_task_runner,
Chih-Yu Huangfc163802019-09-02 06:17:48134 scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
135 GetFramePoolCB get_pool_cb) {
Chih-Yu Huangde529a82019-06-06 03:26:09136 DCHECK(client_task_runner->RunsTasksInCurrentSequence());
Chih-Yu Huangfc163802019-09-02 06:17:48137 DCHECK(get_pool_cb);
Chih-Yu Huangde529a82019-06-06 03:26:09138
139 scoped_refptr<V4L2Device> device = V4L2Device::Create();
140 if (!device) {
141 VLOGF(1) << "Failed to create V4L2 device.";
142 return nullptr;
143 }
144
145 return base::WrapUnique<VideoDecoder>(new V4L2SliceVideoDecoder(
Chih-Yu Huangfc163802019-09-02 06:17:48146 std::move(client_task_runner), std::move(decoder_task_runner),
147 std::move(device), std::move(get_pool_cb)));
Chih-Yu Huangde529a82019-06-06 03:26:09148}
149
Chih-Yu Huanga4bf8342019-06-27 04:03:44150// static
151SupportedVideoDecoderConfigs V4L2SliceVideoDecoder::GetSupportedConfigs() {
152 scoped_refptr<V4L2Device> device = V4L2Device::Create();
153 if (!device)
154 return SupportedVideoDecoderConfigs();
155
156 return ConvertFromSupportedProfiles(
157 device->GetSupportedDecodeProfiles(base::size(kSupportedInputFourccs),
158 kSupportedInputFourccs),
159 false);
160}
161
Chih-Yu Huangde529a82019-06-06 03:26:09162V4L2SliceVideoDecoder::V4L2SliceVideoDecoder(
163 scoped_refptr<base::SequencedTaskRunner> client_task_runner,
Chih-Yu Huangfc163802019-09-02 06:17:48164 scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
Chih-Yu Huangde529a82019-06-06 03:26:09165 scoped_refptr<V4L2Device> device,
Chih-Yu Huangfc163802019-09-02 06:17:48166 GetFramePoolCB get_pool_cb)
Chih-Yu Huangde529a82019-06-06 03:26:09167 : device_(std::move(device)),
Chih-Yu Huangfc163802019-09-02 06:17:48168 get_pool_cb_(std::move(get_pool_cb)),
Chih-Yu Huangde529a82019-06-06 03:26:09169 client_task_runner_(std::move(client_task_runner)),
Chih-Yu Huangfc163802019-09-02 06:17:48170 decoder_task_runner_(std::move(decoder_task_runner)),
David Staessens59766d62019-09-06 04:24:46171 bitstream_id_to_timestamp_(kTimestampCacheSize),
Chih-Yu Huangde529a82019-06-06 03:26:09172 weak_this_factory_(this) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36173 DETACH_FROM_SEQUENCE(client_sequence_checker_);
174 DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09175 VLOGF(2);
176 weak_this_ = weak_this_factory_.GetWeakPtr();
Chih-Yu Huangde529a82019-06-06 03:26:09177}
178
179V4L2SliceVideoDecoder::~V4L2SliceVideoDecoder() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36180 // We might be called from either the client or the decoder sequence.
181 DETACH_FROM_SEQUENCE(client_sequence_checker_);
182 DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09183 VLOGF(2);
184}
185
186std::string V4L2SliceVideoDecoder::GetDisplayName() const {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36187 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
188
Chih-Yu Huangde529a82019-06-06 03:26:09189 return "V4L2SliceVideoDecoder";
190}
191
192bool V4L2SliceVideoDecoder::IsPlatformDecoder() const {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36193 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
194
Chih-Yu Huangde529a82019-06-06 03:26:09195 return true;
196}
197
198int V4L2SliceVideoDecoder::GetMaxDecodeRequests() const {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36199 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
200
Chih-Yu Huangde529a82019-06-06 03:26:09201 return 4;
202}
203
204bool V4L2SliceVideoDecoder::NeedsBitstreamConversion() const {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36205 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
206
Chih-Yu Huangde529a82019-06-06 03:26:09207 return needs_bitstream_conversion_;
208}
209
210bool V4L2SliceVideoDecoder::CanReadWithoutStalling() const {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36211 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
212
Chih-Yu Huangde529a82019-06-06 03:26:09213 return frame_pool_ && !frame_pool_->IsExhausted();
214}
215
216void V4L2SliceVideoDecoder::Destroy() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36217 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09218 VLOGF(2);
219
220 decoder_task_runner_->PostTask(
221 FROM_HERE,
222 base::BindOnce(&V4L2SliceVideoDecoder::DestroyTask, weak_this_));
223}
224
225void V4L2SliceVideoDecoder::DestroyTask() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36226 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09227 DVLOGF(2);
228
Chih-Yu Huangde529a82019-06-06 03:26:09229 // Call all pending decode callback.
230 ClearPendingRequests(DecodeStatus::ABORTED);
231
Chih-Yu Huang30b5fca2019-09-24 09:03:34232 avd_ = nullptr;
233
Chih-Yu Huangde529a82019-06-06 03:26:09234 // Stop and Destroy device.
235 StopStreamV4L2Queue();
Chih-Yu Huang1c5d4212019-08-01 07:04:47236 if (input_queue_) {
237 input_queue_->DeallocateBuffers();
238 input_queue_ = nullptr;
239 }
240 if (output_queue_) {
241 output_queue_->DeallocateBuffers();
242 output_queue_ = nullptr;
243 }
Chih-Yu Huangde529a82019-06-06 03:26:09244 DCHECK(surfaces_at_device_.empty());
245
246 weak_this_factory_.InvalidateWeakPtrs();
Chih-Yu Huangfc163802019-09-02 06:17:48247
Chih-Yu Huangde529a82019-06-06 03:26:09248 delete this;
249 VLOGF(2) << "Destroyed";
250}
251
252void V4L2SliceVideoDecoder::Initialize(const VideoDecoderConfig& config,
253 bool low_delay,
254 CdmContext* cdm_context,
255 InitCB init_cb,
256 const OutputCB& output_cb,
257 const WaitingCB& /* waiting_cb */) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36258 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09259 VLOGF(2) << "config: " << config.AsHumanReadableString();
260
261 if (!config.IsValidConfig()) {
262 VLOGF(1) << "config is not valid";
263 std::move(init_cb).Run(false);
264 return;
265 }
266 if (cdm_context) {
267 VLOGF(1) << "cdm_context is not supported.";
268 std::move(init_cb).Run(false);
269 return;
270 }
271
272 decoder_task_runner_->PostTask(
273 FROM_HERE,
274 base::BindOnce(&V4L2SliceVideoDecoder::InitializeTask, weak_this_, config,
275 std::move(init_cb), std::move(output_cb)));
276}
277
278void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
279 InitCB init_cb,
280 const OutputCB& output_cb) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36281 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09282 DCHECK(state_ == State::kUninitialized || state_ == State::kDecoding);
283 DVLOGF(3);
284
285 if (!output_request_queue_.empty() || flush_cb_ || current_decode_request_ ||
286 !decode_request_queue_.empty()) {
287 VLOGF(1) << "Should not call Initialize() during pending decode";
288 client_task_runner_->PostTask(FROM_HERE,
289 base::BindOnce(std::move(init_cb), false));
290 return;
291 }
292
293 // Reset V4L2 device and queue if reinitializing decoder.
294 if (state_ != State::kUninitialized) {
295 if (!StopStreamV4L2Queue()) {
296 client_task_runner_->PostTask(FROM_HERE,
297 base::BindOnce(std::move(init_cb), false));
298 return;
299 }
300
301 input_queue_->DeallocateBuffers();
302 output_queue_->DeallocateBuffers();
303 input_queue_ = nullptr;
304 output_queue_ = nullptr;
305
306 device_ = V4L2Device::Create();
307 if (!device_) {
308 VLOGF(1) << "Failed to create V4L2 device.";
309 client_task_runner_->PostTask(FROM_HERE,
310 base::BindOnce(std::move(init_cb), false));
311 return;
312 }
313
314 if (avd_) {
315 avd_->Reset();
316 avd_ = nullptr;
317 }
318 SetState(State::kUninitialized);
319 }
320
Chih-Yu Huangfc163802019-09-02 06:17:48321 // Setup frame pool.
322 frame_pool_ = get_pool_cb_.Run();
323
Chih-Yu Huangde529a82019-06-06 03:26:09324 // Open V4L2 device.
325 VideoCodecProfile profile = config.profile();
326 uint32_t input_format_fourcc =
327 V4L2Device::VideoCodecProfileToV4L2PixFmt(profile, true);
Chih-Yu Huang6052d1c2019-08-26 09:35:46328 if (!input_format_fourcc ||
329 !device_->Open(V4L2Device::Type::kDecoder, input_format_fourcc)) {
Chih-Yu Huangde529a82019-06-06 03:26:09330 VLOGF(1) << "Failed to open device for profile: " << profile
331 << " fourcc: " << FourccToString(input_format_fourcc);
332 client_task_runner_->PostTask(FROM_HERE,
333 base::BindOnce(std::move(init_cb), false));
334 return;
335 }
336
337 struct v4l2_capability caps;
338 const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
339 if (device_->Ioctl(VIDIOC_QUERYCAP, &caps) ||
340 (caps.capabilities & kCapsRequired) != kCapsRequired) {
341 VLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP, "
342 << "caps check failed: 0x" << std::hex << caps.capabilities;
343 client_task_runner_->PostTask(FROM_HERE,
344 base::BindOnce(std::move(init_cb), false));
345 return;
346 }
347
348 // Create codec-specific AcceleratedVideoDecoder.
349 // TODO(akahuang): Check the profile is supported.
350 if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
351 avd_.reset(new H264Decoder(
Alexandre Courbot447e1f682019-08-20 07:54:56352 std::make_unique<V4L2LegacyH264Accelerator>(this, device_.get())));
Chih-Yu Huangde529a82019-06-06 03:26:09353 } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
354 avd_.reset(new VP8Decoder(
Alexandre Courbotd7482212019-09-03 07:39:21355 std::make_unique<V4L2LegacyVP8Accelerator>(this, device_.get())));
Chih-Yu Huangde529a82019-06-06 03:26:09356 } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
357 avd_.reset(new VP9Decoder(
358 std::make_unique<V4L2VP9Accelerator>(this, device_.get())));
359 } else {
360 VLOGF(1) << "Unsupported profile " << GetProfileName(profile);
361 client_task_runner_->PostTask(FROM_HERE,
362 base::BindOnce(std::move(init_cb), false));
363 return;
364 }
Hirokazu Honda23c6a6a2019-07-25 11:14:45365
Chih-Yu Huangde529a82019-06-06 03:26:09366 needs_bitstream_conversion_ = (config.codec() == kCodecH264);
Hirokazu Honda23c6a6a2019-07-25 11:14:45367 pixel_aspect_ratio_ = config.GetPixelAspectRatio();
Chih-Yu Huangde529a82019-06-06 03:26:09368
369 // Setup input format.
370 if (!SetupInputFormat(input_format_fourcc)) {
371 VLOGF(1) << "Failed to setup input format.";
372 client_task_runner_->PostTask(FROM_HERE,
373 base::BindOnce(std::move(init_cb), false));
374 return;
375 }
376
377 // Setup output format.
Hirokazu Honda23c6a6a2019-07-25 11:14:45378 if (!SetupOutputFormat(config.coded_size(), config.visible_rect())) {
Chih-Yu Huangde529a82019-06-06 03:26:09379 VLOGF(1) << "Failed to setup output format.";
380 client_task_runner_->PostTask(FROM_HERE,
381 base::BindOnce(std::move(init_cb), false));
382 return;
383 }
384
Chih-Yu Huangde529a82019-06-06 03:26:09385 // Create Input/Output V4L2Queue
386 input_queue_ = device_->GetQueue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
387 output_queue_ = device_->GetQueue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
388 if (!input_queue_ || !output_queue_) {
389 VLOGF(1) << "Failed to create V4L2 queue.";
390 client_task_runner_->PostTask(FROM_HERE,
391 base::BindOnce(std::move(init_cb), false));
392 return;
393 }
394 if (input_queue_->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_MMAP) == 0) {
395 VLOGF(1) << "Failed to allocate input buffer.";
396 client_task_runner_->PostTask(FROM_HERE,
397 base::BindOnce(std::move(init_cb), false));
398 return;
399 }
Chih-Yu Huangde529a82019-06-06 03:26:09400
401 // Call init_cb
402 output_cb_ = output_cb;
403 SetState(State::kDecoding);
404 client_task_runner_->PostTask(FROM_HERE,
405 base::BindOnce(std::move(init_cb), true));
406}
407
408bool V4L2SliceVideoDecoder::SetupInputFormat(uint32_t input_format_fourcc) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36409 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09410 DCHECK_EQ(state_, State::kUninitialized);
411
412 // Check if the format is supported.
413 std::vector<uint32_t> formats = device_->EnumerateSupportedPixelformats(
414 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
415 if (std::find(formats.begin(), formats.end(), input_format_fourcc) ==
416 formats.end()) {
417 DVLOGF(3) << "Input fourcc " << input_format_fourcc
418 << " not supported by device.";
419 return false;
420 }
421
422 // Determine the input buffer size.
423 gfx::Size max_size, min_size;
424 device_->GetSupportedResolution(input_format_fourcc, &min_size, &max_size);
425 size_t input_size = max_size.GetArea() > k1080pArea
426 ? kInputBufferMaxSizeFor4k
427 : kInputBufferMaxSizeFor1080p;
428
429 // Setup the input format.
430 struct v4l2_format format;
431 memset(&format, 0, sizeof(format));
432 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
433 format.fmt.pix_mp.pixelformat = input_format_fourcc;
434 format.fmt.pix_mp.plane_fmt[0].sizeimage = input_size;
435 format.fmt.pix_mp.num_planes = kNumInputPlanes;
436 if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) {
437 VPLOGF(1) << "Failed to call IOCTL to set input format.";
438 return false;
439 }
440 DCHECK_EQ(format.fmt.pix_mp.pixelformat, input_format_fourcc);
441
442 return true;
443}
444
Hirokazu Honda23c6a6a2019-07-25 11:14:45445base::Optional<struct v4l2_format>
Hirokazu Honda685bf012019-08-05 01:30:00446V4L2SliceVideoDecoder::SetV4L2FormatOnOutputQueue(uint32_t format_fourcc,
447 const gfx::Size& size) {
Hirokazu Honda23c6a6a2019-07-25 11:14:45448 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
449
450 struct v4l2_format format = {};
451 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
452 format.fmt.pix_mp.pixelformat = format_fourcc;
453 format.fmt.pix_mp.width = size.width();
454 format.fmt.pix_mp.height = size.height();
455 format.fmt.pix_mp.num_planes =
456 V4L2Device::GetNumPlanesOfV4L2PixFmt(format_fourcc);
457 if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0 ||
458 format.fmt.pix_mp.pixelformat != format_fourcc) {
459 VPLOGF(2) << "Failed to set output format. format_fourcc=" << format_fourcc;
460 return base::nullopt;
461 }
462 return format;
463}
464
465base::Optional<VideoFrameLayout> V4L2SliceVideoDecoder::SetupOutputFormat(
466 const gfx::Size& size,
467 const gfx::Rect& visible_rect) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36468 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09469
470 const std::vector<uint32_t> formats = device_->EnumerateSupportedPixelformats(
471 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
472 DCHECK(!formats.empty());
Hirokazu Honda23c6a6a2019-07-25 11:14:45473 for (const auto format_fourcc : formats) {
474 if (!device_->CanCreateEGLImageFrom(format_fourcc))
475 continue;
476
Hirokazu Honda685bf012019-08-05 01:30:00477 base::Optional<struct v4l2_format> format =
478 SetV4L2FormatOnOutputQueue(format_fourcc, size);
479 if (!format)
480 continue;
481
482 // S_FMT is successful. Next make sure VFPool can allocate video frames with
483 // width and height adjusted by a video driver.
484 gfx::Size adjusted_size(format->fmt.pix_mp.width,
485 format->fmt.pix_mp.height);
486
Hirokazu Honda23c6a6a2019-07-25 11:14:45487 // Make sure VFPool can allocate video frames with width and height.
488 auto frame_layout =
Hirokazu Honda685bf012019-08-05 01:30:00489 UpdateVideoFramePoolFormat(format_fourcc, adjusted_size, visible_rect);
490 if (frame_layout) {
491 if (frame_layout->coded_size() != adjusted_size) {
492 VLOGF(1) << "The size adjusted by VFPool is different from one "
493 << "adjusted by a video driver";
494 continue;
495 }
Hirokazu Honda23c6a6a2019-07-25 11:14:45496
Hirokazu Honda23c6a6a2019-07-25 11:14:45497 num_output_planes_ = format->fmt.pix_mp.num_planes;
498 return frame_layout;
Chih-Yu Huangde529a82019-06-06 03:26:09499 }
500 }
501
502 // TODO(akahuang): Use ImageProcessor in this case.
503 VLOGF(2) << "WARNING: Cannot find format that can create EGL image. "
504 << "We need ImageProcessor to convert pixel format.";
Hirokazu Honda23c6a6a2019-07-25 11:14:45505 NOTIMPLEMENTED();
506 return base::nullopt;
Chih-Yu Huangde529a82019-06-06 03:26:09507}
508
Hirokazu Honda23c6a6a2019-07-25 11:14:45509base::Optional<VideoFrameLayout>
510V4L2SliceVideoDecoder::UpdateVideoFramePoolFormat(
511 uint32_t output_format_fourcc,
512 const gfx::Size& size,
Hirokazu Honda815c8412019-07-17 08:15:53513 const gfx::Rect& visible_rect) {
Hirokazu Honda23c6a6a2019-07-25 11:14:45514 VideoPixelFormat output_format =
515 V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc);
516 if (output_format == PIXEL_FORMAT_UNKNOWN) {
517 return base::nullopt;
518 }
519 auto layout = VideoFrameLayout::Create(output_format, size);
520 if (!layout) {
521 VLOGF(1) << "Failed to create video frame layout.";
522 return base::nullopt;
523 }
524
Hirokazu Honda815c8412019-07-17 08:15:53525 gfx::Size natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio_);
Hirokazu Honda23c6a6a2019-07-25 11:14:45526 return frame_pool_->NegotiateFrameFormat(*layout, visible_rect, natural_size);
Chih-Yu Huangf4635892019-07-11 14:20:29527}
528
Chih-Yu Huangde529a82019-06-06 03:26:09529void V4L2SliceVideoDecoder::Reset(base::OnceClosure closure) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36530 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09531 DVLOGF(3);
532
533 decoder_task_runner_->PostTask(
534 FROM_HERE, base::BindOnce(&V4L2SliceVideoDecoder::ResetTask, weak_this_,
535 std::move(closure)));
536}
537
538void V4L2SliceVideoDecoder::ResetTask(base::OnceClosure closure) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36539 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09540 DVLOGF(3);
541
Chih-Yu Huangde529a82019-06-06 03:26:09542 // Call all pending decode callback.
543 ClearPendingRequests(DecodeStatus::ABORTED);
544
545 // Streamoff V4L2 queues to drop input and output buffers.
546 // If the queues are streaming before reset, then we need to start streaming
547 // them after stopping.
Alexandre Courbotba021e32019-09-26 07:24:35548 bool is_streaming = input_queue_->IsStreaming();
Chih-Yu Huangde529a82019-06-06 03:26:09549 if (!StopStreamV4L2Queue())
550 return;
551
Alexandre Courbotba021e32019-09-26 07:24:35552 if (is_streaming) {
Chih-Yu Huangde529a82019-06-06 03:26:09553 if (!StartStreamV4L2Queue())
554 return;
555 }
556
557 client_task_runner_->PostTask(FROM_HERE, std::move(closure));
558}
559
560void V4L2SliceVideoDecoder::ClearPendingRequests(DecodeStatus status) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36561 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09562 DVLOGF(3);
563
Chih-Yu Huang30b5fca2019-09-24 09:03:34564 if (avd_)
565 avd_->Reset();
566
Chih-Yu Huangde529a82019-06-06 03:26:09567 // Clear output_request_queue_.
568 while (!output_request_queue_.empty())
569 output_request_queue_.pop();
570
571 if (flush_cb_)
572 RunDecodeCB(std::move(flush_cb_), status);
573
574 // Clear current_decode_request_ and decode_request_queue_.
575 if (current_decode_request_) {
576 RunDecodeCB(std::move(current_decode_request_->decode_cb), status);
Alexandre Courbot399c547f2019-06-12 08:22:46577 current_decode_request_ = base::nullopt;
Chih-Yu Huangde529a82019-06-06 03:26:09578 }
579
580 while (!decode_request_queue_.empty()) {
581 auto request = std::move(decode_request_queue_.front());
582 decode_request_queue_.pop();
Alexandre Courbot399c547f2019-06-12 08:22:46583 RunDecodeCB(std::move(request.decode_cb), status);
Chih-Yu Huangde529a82019-06-06 03:26:09584 }
585}
586
587void V4L2SliceVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
588 DecodeCB decode_cb) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36589 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09590
591 decoder_task_runner_->PostTask(
592 FROM_HERE,
Alexandre Courbot399c547f2019-06-12 08:22:46593 base::BindOnce(&V4L2SliceVideoDecoder::EnqueueDecodeTask, weak_this_,
594 DecodeRequest(std::move(buffer), std::move(decode_cb),
595 GetNextBitstreamId())));
Chih-Yu Huangde529a82019-06-06 03:26:09596}
597
Alexandre Courbot399c547f2019-06-12 08:22:46598void V4L2SliceVideoDecoder::EnqueueDecodeTask(DecodeRequest request) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36599 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huang30b5fca2019-09-24 09:03:34600 DCHECK_NE(state_, State::kUninitialized);
601
602 if (state_ == State::kError) {
603 std::move(request.decode_cb).Run(DecodeStatus::DECODE_ERROR);
604 return;
605 }
Chih-Yu Huangde529a82019-06-06 03:26:09606
Chih-Yu Huangccf46032019-07-11 11:48:06607 if (!request.buffer->end_of_stream()) {
David Staessens59766d62019-09-06 04:24:46608 bitstream_id_to_timestamp_.Put(request.bitstream_id,
609 request.buffer->timestamp());
Chih-Yu Huangccf46032019-07-11 11:48:06610 }
Chih-Yu Huangde529a82019-06-06 03:26:09611 decode_request_queue_.push(std::move(request));
Chih-Yu Huang1a5f9fc2019-07-09 04:18:24612 // If we are already decoding, then we don't need to pump again.
613 if (!current_decode_request_)
614 PumpDecodeTask();
Chih-Yu Huangde529a82019-06-06 03:26:09615}
616
617void V4L2SliceVideoDecoder::PumpDecodeTask() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36618 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09619 DVLOGF(3) << "state_:" << static_cast<int>(state_)
620 << " Number of Decode requests: " << decode_request_queue_.size();
621
Chih-Yu Huang30b5fca2019-09-24 09:03:34622 if (state_ != State::kDecoding)
Chih-Yu Huangde529a82019-06-06 03:26:09623 return;
624
Chih-Yu Huang40adcdf2019-07-11 03:37:02625 pause_reason_ = PauseReason::kNone;
Chih-Yu Huangde529a82019-06-06 03:26:09626 while (true) {
627 switch (avd_->Decode()) {
628 case AcceleratedVideoDecoder::kAllocateNewSurfaces:
629 DVLOGF(3) << "Need to change resolution. Pause decoding.";
Chih-Yu Huang40adcdf2019-07-11 03:37:02630 SetState(State::kFlushing);
Chih-Yu Huangde529a82019-06-06 03:26:09631
Alexandre Courbot92afc8b72019-06-12 10:48:32632 output_request_queue_.push(OutputRequest::ChangeResolutionFence());
Chih-Yu Huangde529a82019-06-06 03:26:09633 PumpOutputSurfaces();
634 return;
635
636 case AcceleratedVideoDecoder::kRanOutOfStreamData:
637 // Current decode request is finished processing.
638 if (current_decode_request_) {
639 DCHECK(current_decode_request_->decode_cb);
640 RunDecodeCB(std::move(current_decode_request_->decode_cb),
641 DecodeStatus::OK);
Alexandre Courbot399c547f2019-06-12 08:22:46642 current_decode_request_ = base::nullopt;
Chih-Yu Huangde529a82019-06-06 03:26:09643 }
644
645 // Process next decodee request.
646 if (decode_request_queue_.empty())
647 return;
648 current_decode_request_ = std::move(decode_request_queue_.front());
649 decode_request_queue_.pop();
650
651 if (current_decode_request_->buffer->end_of_stream()) {
652 if (!avd_->Flush()) {
653 VLOGF(1) << "Failed flushing the decoder.";
654 SetState(State::kError);
655 return;
656 }
657 // Put the decoder in an idle state, ready to resume.
658 avd_->Reset();
659
Chih-Yu Huang40adcdf2019-07-11 03:37:02660 SetState(State::kFlushing);
Chih-Yu Huangde529a82019-06-06 03:26:09661 DCHECK(!flush_cb_);
662 flush_cb_ = std::move(current_decode_request_->decode_cb);
663
Alexandre Courbot92afc8b72019-06-12 10:48:32664 output_request_queue_.push(OutputRequest::FlushFence());
Chih-Yu Huangde529a82019-06-06 03:26:09665 PumpOutputSurfaces();
Alexandre Courbot399c547f2019-06-12 08:22:46666 current_decode_request_ = base::nullopt;
Chih-Yu Huangde529a82019-06-06 03:26:09667 return;
668 }
669
670 avd_->SetStream(current_decode_request_->bitstream_id,
Hirokazu Honda23132c32019-07-09 14:31:20671 *current_decode_request_->buffer);
Chih-Yu Huangde529a82019-06-06 03:26:09672 break;
673
674 case AcceleratedVideoDecoder::kRanOutOfSurfaces:
675 DVLOGF(3) << "Ran out of surfaces. Resume when buffer is returned.";
Chih-Yu Huang40adcdf2019-07-11 03:37:02676 pause_reason_ = PauseReason::kRanOutOfSurfaces;
Chih-Yu Huangde529a82019-06-06 03:26:09677 return;
678
679 case AcceleratedVideoDecoder::kNeedContextUpdate:
680 DVLOGF(3) << "Awaiting context update";
Chih-Yu Huang40adcdf2019-07-11 03:37:02681 pause_reason_ = PauseReason::kWaitSubFrameDecoded;
Chih-Yu Huangde529a82019-06-06 03:26:09682 return;
683
684 case AcceleratedVideoDecoder::kDecodeError:
685 DVLOGF(3) << "Error decoding stream";
686 SetState(State::kError);
687 return;
688
689 case AcceleratedVideoDecoder::kTryAgain:
690 NOTREACHED() << "Should not reach here unless this class accepts "
691 "encrypted streams.";
692 DVLOGF(4) << "No key for decoding stream.";
693 SetState(State::kError);
694 return;
695 }
696 }
697}
698
699void V4L2SliceVideoDecoder::PumpOutputSurfaces() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36700 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09701 DVLOGF(3) << "state_: " << static_cast<int>(state_)
702 << " Number of display surfaces: " << output_request_queue_.size();
703
704 bool resume_decode = false;
705 while (!output_request_queue_.empty()) {
Alexandre Courbot92afc8b72019-06-12 10:48:32706 if (!output_request_queue_.front().IsReady()) {
Chih-Yu Huangde529a82019-06-06 03:26:09707 DVLOGF(3) << "The first surface is not ready yet.";
708 break;
709 }
710
Alexandre Courbot92afc8b72019-06-12 10:48:32711 OutputRequest request = std::move(output_request_queue_.front());
Chih-Yu Huangde529a82019-06-06 03:26:09712 output_request_queue_.pop();
Alexandre Courbot92afc8b72019-06-12 10:48:32713 switch (request.type) {
Chih-Yu Huangde529a82019-06-06 03:26:09714 case OutputRequest::kFlushFence:
715 DCHECK(output_request_queue_.empty());
716 DVLOGF(2) << "Flush finished.";
717 RunDecodeCB(std::move(flush_cb_), DecodeStatus::OK);
718 resume_decode = true;
719 break;
720
721 case OutputRequest::kChangeResolutionFence:
722 DCHECK(output_request_queue_.empty());
723 if (!ChangeResolution()) {
724 SetState(State::kError);
725 return;
726 }
727 resume_decode = true;
728 break;
729
730 case OutputRequest::kSurface:
Alexandre Courbot92afc8b72019-06-12 10:48:32731 scoped_refptr<V4L2DecodeSurface> surface = std::move(request.surface);
Chih-Yu Huangde529a82019-06-06 03:26:09732
Alexandre Courbotb2196352019-06-14 03:28:50733 DCHECK(surface->video_frame());
Chih-Yu Huangf4635892019-07-11 14:20:29734 RunOutputCB(surface->video_frame(), surface->visible_rect(),
735 request.timestamp);
Chih-Yu Huangde529a82019-06-06 03:26:09736 break;
737 }
738 }
739
740 if (resume_decode) {
741 SetState(State::kDecoding);
742 decoder_task_runner_->PostTask(
743 FROM_HERE,
744 base::BindOnce(&V4L2SliceVideoDecoder::PumpDecodeTask, weak_this_));
745 }
746}
747
748bool V4L2SliceVideoDecoder::ChangeResolution() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36749 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huang40adcdf2019-07-11 03:37:02750 DCHECK_EQ(state_, State::kFlushing);
Chih-Yu Huangde529a82019-06-06 03:26:09751 // We change resolution after outputting all pending surfaces, there should
Alexandre Courbotb2196352019-06-14 03:28:50752 // be no V4L2DecodeSurface left.
Chih-Yu Huangde529a82019-06-06 03:26:09753 DCHECK(surfaces_at_device_.empty());
Alexandre Courbotb2196352019-06-14 03:28:50754 DCHECK_EQ(input_queue_->QueuedBuffersCount(), 0u);
755 DCHECK_EQ(output_queue_->QueuedBuffersCount(), 0u);
Chih-Yu Huangde529a82019-06-06 03:26:09756
757 DCHECK(output_request_queue_.empty());
758 if (!StopStreamV4L2Queue())
759 return false;
760
Hirokazu Honda23c6a6a2019-07-25 11:14:45761 // Set output format with the new resolution.
Chih-Yu Huangde529a82019-06-06 03:26:09762 gfx::Size pic_size = avd_->GetPicSize();
763 DCHECK(!pic_size.IsEmpty());
764 DVLOGF(3) << "Change resolution to " << pic_size.width() << "x"
765 << pic_size.height();
Hirokazu Honda23c6a6a2019-07-25 11:14:45766 auto frame_layout = SetupOutputFormat(pic_size, avd_->GetVisibleRect());
767 if (!frame_layout) {
768 VLOGF(1) << "No format is available with thew new resolution";
Chih-Yu Huangde529a82019-06-06 03:26:09769 return false;
770 }
771
Hirokazu Honda23c6a6a2019-07-25 11:14:45772 auto coded_size = frame_layout->coded_size();
Chih-Yu Huangde529a82019-06-06 03:26:09773 DCHECK_EQ(coded_size.width() % 16, 0);
774 DCHECK_EQ(coded_size.height() % 16, 0);
775 if (!gfx::Rect(coded_size).Contains(gfx::Rect(pic_size))) {
776 VLOGF(1) << "Got invalid adjusted coded size: " << coded_size.ToString();
777 return false;
778 }
Chih-Yu Huangde529a82019-06-06 03:26:09779
780 // Allocate new output buffers.
Chih-Yu Huangf4635892019-07-11 14:20:29781 if (!output_queue_->DeallocateBuffers())
782 return false;
Chih-Yu Huangde529a82019-06-06 03:26:09783 size_t num_output_frames = avd_->GetRequiredNumOfPictures();
784 DCHECK_GT(num_output_frames, 0u);
785 if (output_queue_->AllocateBuffers(num_output_frames, V4L2_MEMORY_DMABUF) ==
786 0) {
787 VLOGF(1) << "Failed to request output buffers.";
788 return false;
789 }
790 if (output_queue_->AllocatedBuffersCount() != num_output_frames) {
791 VLOGF(1) << "Could not allocate requested number of output buffers.";
792 return false;
793 }
794 frame_pool_->SetMaxNumFrames(num_output_frames);
795
796 if (!StartStreamV4L2Queue())
797 return false;
798
799 SetState(State::kDecoding);
800 return true;
801}
802
803scoped_refptr<V4L2DecodeSurface> V4L2SliceVideoDecoder::CreateSurface() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36804 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09805 DVLOGF(4);
806
807 // Request VideoFrame.
808 scoped_refptr<VideoFrame> frame = frame_pool_->GetFrame();
809 if (!frame) {
810 // We allocate the same number of output buffer slot in V4L2 device and the
811 // output VideoFrame. If there is free output buffer slot but no free
812 // VideoFrame, surface_it means the VideoFrame is not released at client
Chih-Yu Huangbe8d9a02019-06-13 07:25:54813 // side. Post PumpDecodeTask when the pool has available frames.
Chih-Yu Huangde529a82019-06-06 03:26:09814 DVLOGF(3) << "There is no available VideoFrame.";
Chih-Yu Huangbe8d9a02019-06-13 07:25:54815 frame_pool_->NotifyWhenFrameAvailable(base::BindOnce(
816 base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
817 decoder_task_runner_, FROM_HERE,
818 base::BindOnce(&V4L2SliceVideoDecoder::PumpDecodeTask, weak_this_)));
Chih-Yu Huangde529a82019-06-06 03:26:09819 return nullptr;
820 }
Chih-Yu Huangde529a82019-06-06 03:26:09821
822 // Request V4L2 input and output buffers.
823 V4L2WritableBufferRef input_buf = input_queue_->GetFreeBuffer();
824 V4L2WritableBufferRef output_buf = output_queue_->GetFreeBuffer();
Chih-Yu Huangbe8d9a02019-06-13 07:25:54825 if (!input_buf.IsValid() || !output_buf.IsValid()) {
826 DVLOGF(3) << "There is no free V4L2 buffer.";
Chih-Yu Huangde529a82019-06-06 03:26:09827 return nullptr;
Chih-Yu Huangbe8d9a02019-06-13 07:25:54828 }
Chih-Yu Huangde529a82019-06-06 03:26:09829
Chih-Yu Huangde529a82019-06-06 03:26:09830 return scoped_refptr<V4L2DecodeSurface>(new V4L2ConfigStoreDecodeSurface(
Alexandre Courbot41cb76392019-07-29 07:35:23831 std::move(input_buf), std::move(output_buf), std::move(frame)));
Chih-Yu Huangde529a82019-06-06 03:26:09832}
833
Alexandre Courbot3f8a0bd2019-06-12 13:30:08834void V4L2SliceVideoDecoder::ReuseOutputBuffer(V4L2ReadableBufferRef buffer) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36835 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Alexandre Courbot3f8a0bd2019-06-12 13:30:08836 DVLOGF(3) << "Reuse output surface #" << buffer->BufferId();
Chih-Yu Huangde529a82019-06-06 03:26:09837
Chih-Yu Huangde529a82019-06-06 03:26:09838 // Resume decoding in case of ran out of surface.
Chih-Yu Huang40adcdf2019-07-11 03:37:02839 if (pause_reason_ == PauseReason::kRanOutOfSurfaces) {
Chih-Yu Huangde529a82019-06-06 03:26:09840 decoder_task_runner_->PostTask(
841 FROM_HERE,
842 base::BindOnce(&V4L2SliceVideoDecoder::PumpDecodeTask, weak_this_));
843 }
844}
845
846bool V4L2SliceVideoDecoder::SubmitSlice(
847 const scoped_refptr<V4L2DecodeSurface>& dec_surface,
848 const uint8_t* data,
849 size_t size) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36850 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09851 DVLOGF(3);
852
Alexandre Courbotb2196352019-06-14 03:28:50853 size_t plane_size = dec_surface->input_buffer().GetPlaneSize(0);
854 size_t bytes_used = dec_surface->input_buffer().GetPlaneBytesUsed(0);
Chih-Yu Huangde529a82019-06-06 03:26:09855 if (size > plane_size - bytes_used) {
856 VLOGF(1) << "The size of submitted slice(" << size
857 << ") is larger than the remaining buffer size("
858 << plane_size - bytes_used << "). Plane size is " << plane_size;
859 SetState(State::kError);
860 return false;
861 }
862
Alexandre Courbotb2196352019-06-14 03:28:50863 void* mapping = dec_surface->input_buffer().GetPlaneMapping(0);
Chih-Yu Huangde529a82019-06-06 03:26:09864 memcpy(reinterpret_cast<uint8_t*>(mapping) + bytes_used, data, size);
Alexandre Courbotb2196352019-06-14 03:28:50865 dec_surface->input_buffer().SetPlaneBytesUsed(0, bytes_used + size);
Chih-Yu Huangde529a82019-06-06 03:26:09866 return true;
867}
868
869void V4L2SliceVideoDecoder::DecodeSurface(
870 const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36871 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09872 DVLOGF(3);
873
874 // Enqueue input_buf and output_buf
Alexandre Courbot52611e72019-07-29 04:57:40875 dec_surface->input_buffer().PrepareQueueBuffer(*dec_surface);
Alexandre Courbotb2196352019-06-14 03:28:50876 if (!std::move(dec_surface->input_buffer()).QueueMMap()) {
Chih-Yu Huangde529a82019-06-06 03:26:09877 SetState(State::kError);
878 return;
879 }
Chih-Yu Huangde529a82019-06-06 03:26:09880
Alexandre Courbotb2196352019-06-14 03:28:50881 if (!IsValidFrameForQueueDMABuf(dec_surface->video_frame().get(),
Hirokazu Hondac1f0a602019-06-12 11:09:29882 num_output_planes_)) {
Chih-Yu Huangde529a82019-06-06 03:26:09883 SetState(State::kError);
884 return;
885 }
Alexandre Courbotb2196352019-06-14 03:28:50886 if (!std::move(dec_surface->output_buffer())
887 .QueueDMABuf(dec_surface->video_frame()->DmabufFds())) {
Chih-Yu Huangde529a82019-06-06 03:26:09888 SetState(State::kError);
889 return;
890 }
Chih-Yu Huangde529a82019-06-06 03:26:09891
892 if (!dec_surface->Submit()) {
893 VLOGF(1) << "Error while submitting frame for decoding!";
894 SetState(State::kError);
895 return;
896 }
897
Alexandre Courbot5f7f2ef2019-06-12 06:39:17898 surfaces_at_device_.push(std::move(dec_surface));
Chih-Yu Huangde529a82019-06-06 03:26:09899}
900
901void V4L2SliceVideoDecoder::SurfaceReady(
902 const scoped_refptr<V4L2DecodeSurface>& dec_surface,
903 int32_t bitstream_id,
904 const gfx::Rect& visible_rect,
905 const VideoColorSpace& /* color_space */) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36906 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09907 DVLOGF(3);
908
Chih-Yu Huange497fcc2019-09-25 02:33:11909 // Find the timestamp associated with |bitstream_id|. It's possible that a
910 // surface is output multiple times for different |bitstream_id|s (e.g. VP9
911 // show_existing_frame feature). This means we need to output the same frame
912 // again with a different timestamp.
913 // On some rare occasions it's also possible that a single DecoderBuffer
914 // produces multiple surfaces with the same |bitstream_id|, so we shouldn't
915 // remove the timestamp from the cache.
David Staessens59766d62019-09-06 04:24:46916 const auto it = bitstream_id_to_timestamp_.Peek(bitstream_id);
Chih-Yu Huangccf46032019-07-11 11:48:06917 DCHECK(it != bitstream_id_to_timestamp_.end());
918 base::TimeDelta timestamp = it->second;
Chih-Yu Huangccf46032019-07-11 11:48:06919
Chih-Yu Huangde529a82019-06-06 03:26:09920 dec_surface->SetVisibleRect(visible_rect);
Chih-Yu Huangccf46032019-07-11 11:48:06921 output_request_queue_.push(
922 OutputRequest::Surface(std::move(dec_surface), timestamp));
Chih-Yu Huangde529a82019-06-06 03:26:09923 PumpOutputSurfaces();
924}
925
926bool V4L2SliceVideoDecoder::StartStreamV4L2Queue() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36927 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09928 DVLOGF(3);
929
Chih-Yu Huangde529a82019-06-06 03:26:09930 if (!input_queue_->Streamon() || !output_queue_->Streamon()) {
931 VLOGF(1) << "Failed to streamon V4L2 queue.";
932 SetState(State::kError);
933 return false;
934 }
935
Alexandre Courbotba021e32019-09-26 07:24:35936 if (!device_->StartPolling(
937 base::BindRepeating(&V4L2SliceVideoDecoder::ServiceDeviceTask,
938 weak_this_),
939 base::BindRepeating(&V4L2SliceVideoDecoder::SetState, weak_this_,
940 State::kError))) {
941 SetState(State::kError);
942 return false;
943 }
944
Chih-Yu Huangde529a82019-06-06 03:26:09945 return true;
946}
947
948bool V4L2SliceVideoDecoder::StopStreamV4L2Queue() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36949 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09950 DVLOGF(3);
951
Alexandre Courbotba021e32019-09-26 07:24:35952 if (!device_->StopPolling()) {
Chih-Yu Huangde529a82019-06-06 03:26:09953 SetState(State::kError);
954 return false;
955 }
956
Chih-Yu Huang1c5d4212019-08-01 07:04:47957 // Streamoff input and output queue.
958 if (input_queue_)
Chih-Yu Huangde529a82019-06-06 03:26:09959 input_queue_->Streamoff();
Chih-Yu Huang1c5d4212019-08-01 07:04:47960 if (output_queue_)
Chih-Yu Huangde529a82019-06-06 03:26:09961 output_queue_->Streamoff();
Chih-Yu Huang1c5d4212019-08-01 07:04:47962
Alexandre Courbot5f7f2ef2019-06-12 06:39:17963 while (!surfaces_at_device_.empty())
964 surfaces_at_device_.pop();
Chih-Yu Huangde529a82019-06-06 03:26:09965
966 return true;
967}
968
Alexandre Courbotba021e32019-09-26 07:24:35969void V4L2SliceVideoDecoder::ServiceDeviceTask(bool /* event */) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:36970 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:09971 DVLOGF(3) << "Number of queued input buffers: "
972 << input_queue_->QueuedBuffersCount()
973 << ", Number of queued output buffers: "
974 << output_queue_->QueuedBuffersCount();
975
Chih-Yu Huang40adcdf2019-07-11 03:37:02976 bool resume_decode = false;
Chih-Yu Huangde529a82019-06-06 03:26:09977 // Dequeue V4L2 output buffer first to reduce output latency.
978 bool success;
979 V4L2ReadableBufferRef dequeued_buffer;
980 while (output_queue_->QueuedBuffersCount() > 0) {
981 std::tie(success, dequeued_buffer) = output_queue_->DequeueBuffer();
982 if (!success) {
983 SetState(State::kError);
984 return;
985 }
986 if (!dequeued_buffer)
987 break;
988
989 // Mark the output buffer decoded, and try to output surface.
Alexandre Courbot5f7f2ef2019-06-12 06:39:17990 DCHECK(!surfaces_at_device_.empty());
991 auto surface = std::move(surfaces_at_device_.front());
992 DCHECK_EQ(static_cast<size_t>(surface->output_record()),
993 dequeued_buffer->BufferId());
994 surfaces_at_device_.pop();
995
996 surface->SetDecoded();
Chih-Yu Huang40adcdf2019-07-11 03:37:02997 // VP9Decoder update context after surface is decoded. Resume decoding for
998 // previous pause of AVD::kWaitSubFrameDecoded.
999 resume_decode = true;
Chih-Yu Huangde529a82019-06-06 03:26:091000
Alexandre Courbot3f8a0bd2019-06-12 13:30:081001 // Keep a reference to the V4L2 buffer until the buffer is reused. The
1002 // reason for this is that the config store uses V4L2 buffer IDs to
1003 // reference frames, therefore we cannot reuse the same V4L2 buffer ID for
1004 // another decode operation until all references to that frame are gone.
1005 // Request API does not have this limitation, so we can probably remove this
1006 // after config store is gone.
1007 surface->SetReleaseCallback(
1008 base::BindOnce(&V4L2SliceVideoDecoder::ReuseOutputBuffer, weak_this_,
1009 std::move(dequeued_buffer)));
Chih-Yu Huangde529a82019-06-06 03:26:091010
1011 PumpOutputSurfaces();
1012 }
1013
1014 // Dequeue V4L2 input buffer.
1015 while (input_queue_->QueuedBuffersCount() > 0) {
1016 std::tie(success, dequeued_buffer) = input_queue_->DequeueBuffer();
1017 if (!success) {
1018 SetState(State::kError);
1019 return;
1020 }
1021 if (!dequeued_buffer)
1022 break;
1023 }
1024
Chih-Yu Huang40adcdf2019-07-11 03:37:021025 if (resume_decode && pause_reason_ == PauseReason::kWaitSubFrameDecoded) {
1026 decoder_task_runner_->PostTask(
1027 FROM_HERE,
1028 base::BindOnce(&V4L2SliceVideoDecoder::PumpDecodeTask, weak_this_));
1029 }
Chih-Yu Huangde529a82019-06-06 03:26:091030}
1031
1032int32_t V4L2SliceVideoDecoder::GetNextBitstreamId() {
Alexandre Courbotdcb6ebb2019-06-25 04:25:361033 DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:091034
1035 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x7FFFFFFF;
1036 return next_bitstream_buffer_id_;
1037}
1038
1039void V4L2SliceVideoDecoder::RunDecodeCB(DecodeCB cb, DecodeStatus status) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:361040 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:091041
1042 client_task_runner_->PostTask(FROM_HERE,
1043 base::BindOnce(std::move(cb), status));
1044}
1045
Chih-Yu Huangccf46032019-07-11 11:48:061046void V4L2SliceVideoDecoder::RunOutputCB(scoped_refptr<VideoFrame> frame,
Chih-Yu Huangf4635892019-07-11 14:20:291047 const gfx::Rect& visible_rect,
Chih-Yu Huangccf46032019-07-11 11:48:061048 base::TimeDelta timestamp) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:361049 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangccf46032019-07-11 11:48:061050 DVLOGF(4) << "timestamp: " << timestamp;
Chih-Yu Huangde529a82019-06-06 03:26:091051
Chih-Yu Huange497fcc2019-09-25 02:33:111052 // Set the timestamp at which the decode operation started on the
1053 // |frame|. If the frame has been outputted before (e.g. because of VP9
1054 // show-existing-frame feature) we can't overwrite the timestamp directly, as
1055 // the original frame might still be in use. Instead we wrap the frame in
1056 // another frame with a different timestamp.
Chih-Yu Huangeacec322019-09-24 05:51:341057 if (frame->timestamp().is_zero())
1058 frame->set_timestamp(timestamp);
1059
Chih-Yu Huangf4635892019-07-11 14:20:291060 if (frame->visible_rect() != visible_rect ||
1061 frame->timestamp() != timestamp) {
1062 gfx::Size natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio_);
Chih-Yu Huangccf46032019-07-11 11:48:061063 scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame(
Chih-Yu Huangf4635892019-07-11 14:20:291064 *frame, frame->format(), visible_rect, natural_size);
Chih-Yu Huangccf46032019-07-11 11:48:061065 wrapped_frame->set_timestamp(timestamp);
1066 wrapped_frame->AddDestructionObserver(base::BindOnce(
1067 base::DoNothing::Once<scoped_refptr<VideoFrame>>(), std::move(frame)));
1068
1069 frame = std::move(wrapped_frame);
1070 }
Chih-Yu Huangccf46032019-07-11 11:48:061071
Chih-Yu Huangde529a82019-06-06 03:26:091072 // Although the document of VideoDecoder says "should run |output_cb| as soon
1073 // as possible (without thread trampolining)", MojoVideoDecoderService still
1074 // assumes the callback is called at original thread.
1075 // TODO(akahuang): call the callback directly after updating MojoVDService.
Yuchen Liu1adaf9b2019-07-16 20:41:431076 client_task_runner_->PostTask(FROM_HERE,
1077 base::BindOnce(output_cb_, std::move(frame)));
Chih-Yu Huangde529a82019-06-06 03:26:091078}
1079
1080void V4L2SliceVideoDecoder::SetState(State new_state) {
Alexandre Courbotdcb6ebb2019-06-25 04:25:361081 DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
Chih-Yu Huangde529a82019-06-06 03:26:091082 DVLOGF(3) << "Change state from " << static_cast<int>(state_) << " to "
1083 << static_cast<int>(new_state);
1084
1085 if (state_ == new_state)
1086 return;
1087 if (state_ == State::kError) {
1088 DVLOGF(3) << "Already in kError state.";
1089 return;
1090 }
1091
1092 // Check if the state transition is valid.
1093 switch (new_state) {
1094 case State::kUninitialized:
1095 if (state_ != State::kDecoding) {
1096 VLOGF(1) << "Should not set to kUninitialized.";
1097 new_state = State::kError;
1098 }
1099 break;
1100
1101 case State::kDecoding:
1102 break;
1103
Chih-Yu Huang40adcdf2019-07-11 03:37:021104 case State::kFlushing:
Chih-Yu Huangde529a82019-06-06 03:26:091105 if (state_ != State::kDecoding) {
Chih-Yu Huang40adcdf2019-07-11 03:37:021106 VLOGF(1) << "kFlushing should only be set when kDecoding.";
Chih-Yu Huangde529a82019-06-06 03:26:091107 new_state = State::kError;
1108 }
1109 break;
1110
1111 case State::kError:
1112 break;
1113 }
1114
1115 if (new_state == State::kError) {
1116 VLOGF(1) << "Error occurred.";
1117 ClearPendingRequests(DecodeStatus::DECODE_ERROR);
1118 return;
1119 }
1120 state_ = new_state;
1121 return;
1122}
1123
1124} // namespace media