• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 "v4l2_slice_video_decode_accelerator.h"
6 
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <poll.h>
10 #include <string.h>
11 #include <sys/eventfd.h>
12 #include <sys/ioctl.h>
13 #include <sys/mman.h>
14 
15 #include <memory>
16 
17 #include "base/bind.h"
18 #include "base/bind_helpers.h"
19 #include "base/callback.h"
20 #include "base/callback_helpers.h"
21 #include "base/command_line.h"
22 #include "base/macros.h"
23 #include "base/memory/ptr_util.h"
24 #include "base/numerics/safe_conversions.h"
25 #include "base/single_thread_task_runner.h"
26 #include "base/strings/stringprintf.h"
27 #include "base/threading/thread_task_runner_handle.h"
28 #include "shared_memory_region.h"
29 
30 #define LOGF(level) LOG(level) << __func__ << "(): "
31 #define DLOGF(level) DLOG(level) << __func__ << "(): "
32 #define DVLOGF(level) DVLOG(level) << __func__ << "(): "
33 #define PLOGF(level) PLOG(level) << __func__ << "(): "
34 
35 #define NOTIFY_ERROR(x)                         \
36   do {                                          \
37     LOGF(ERROR) << "Setting error state:" << x; \
38     SetErrorState(x);                           \
39   } while (0)
40 
41 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \
42   do {                                                          \
43     if (device_->Ioctl(type, arg) != 0) {                       \
44       PLOGF(ERROR) << "ioctl() failed: " << type_str;           \
45       return value;                                             \
46     }                                                           \
47   } while (0)
48 
49 #define IOCTL_OR_ERROR_RETURN(type, arg) \
50   IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0), #type)
51 
52 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \
53   IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false, #type)
54 
55 #define IOCTL_OR_LOG_ERROR(type, arg)              \
56   do {                                             \
57     if (device_->Ioctl(type, arg) != 0)            \
58       PLOGF(ERROR) << "ioctl() failed: " << #type; \
59   } while (0)
60 
61 namespace media {
62 
63 // static
64 const uint32_t V4L2SliceVideoDecodeAccelerator::supported_input_fourccs_[] = {
65     V4L2_PIX_FMT_H264_SLICE, V4L2_PIX_FMT_VP8_FRAME, V4L2_PIX_FMT_VP9_FRAME,
66 };
67 
68 class V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface
69     : public base::RefCounted<V4L2DecodeSurface> {
70  public:
71   using ReleaseCB = base::Callback<void(int)>;
72 
73   V4L2DecodeSurface(int32_t bitstream_id,
74                     int input_record,
75                     int output_record,
76                     const ReleaseCB& release_cb);
77 
78   // Mark the surface as decoded. This will also release all references, as
79   // they are not needed anymore and execute the done callback, if not null.
80   void SetDecoded();
decoded() const81   bool decoded() const { return decoded_; }
82 
bitstream_id() const83   int32_t bitstream_id() const { return bitstream_id_; }
input_record() const84   int input_record() const { return input_record_; }
output_record() const85   int output_record() const { return output_record_; }
config_store() const86   uint32_t config_store() const { return config_store_; }
87 
88   // Take references to each reference surface and keep them until the
89   // target surface is decoded.
90   void SetReferenceSurfaces(
91       const std::vector<scoped_refptr<V4L2DecodeSurface>>& ref_surfaces);
92 
93   // If provided via this method, |done_cb| callback will be executed after
94   // decoding into this surface is finished. The callback is reset afterwards,
95   // so it needs to be set again before each decode operation.
SetDecodeDoneCallback(const base::Closure & done_cb)96   void SetDecodeDoneCallback(const base::Closure& done_cb) {
97     DCHECK(done_cb_.is_null());
98     done_cb_ = done_cb;
99   }
100 
101   std::string ToString() const;
102 
103  private:
104   friend class base::RefCounted<V4L2DecodeSurface>;
105   ~V4L2DecodeSurface();
106 
107   int32_t bitstream_id_;
108   int input_record_;
109   int output_record_;
110   uint32_t config_store_;
111 
112   bool decoded_;
113   ReleaseCB release_cb_;
114   base::Closure done_cb_;
115 
116   std::vector<scoped_refptr<V4L2DecodeSurface>> reference_surfaces_;
117 
118   DISALLOW_COPY_AND_ASSIGN(V4L2DecodeSurface);
119 };
120 
V4L2DecodeSurface(int32_t bitstream_id,int input_record,int output_record,const ReleaseCB & release_cb)121 V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface::V4L2DecodeSurface(
122     int32_t bitstream_id,
123     int input_record,
124     int output_record,
125     const ReleaseCB& release_cb)
126     : bitstream_id_(bitstream_id),
127       input_record_(input_record),
128       output_record_(output_record),
129       config_store_(input_record + 1),
130       decoded_(false),
131       release_cb_(release_cb) {}
132 
~V4L2DecodeSurface()133 V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface::~V4L2DecodeSurface() {
134   DVLOGF(5) << "Releasing output record id=" << output_record_;
135   release_cb_.Run(output_record_);
136 }
137 
SetReferenceSurfaces(const std::vector<scoped_refptr<V4L2DecodeSurface>> & ref_surfaces)138 void V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface::SetReferenceSurfaces(
139     const std::vector<scoped_refptr<V4L2DecodeSurface>>& ref_surfaces) {
140   DCHECK(reference_surfaces_.empty());
141   reference_surfaces_ = ref_surfaces;
142 }
143 
SetDecoded()144 void V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface::SetDecoded() {
145   DCHECK(!decoded_);
146   decoded_ = true;
147 
148   // We can now drop references to all reference surfaces for this surface
149   // as we are done with decoding.
150   reference_surfaces_.clear();
151 
152   // And finally execute and drop the decode done callback, if set.
153   if (!done_cb_.is_null())
154     base::ResetAndReturn(&done_cb_).Run();
155 }
156 
ToString() const157 std::string V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface::ToString()
158     const {
159   std::string out;
160   base::StringAppendF(&out, "Buffer %d -> %d. ", input_record_, output_record_);
161   base::StringAppendF(&out, "Reference surfaces:");
162   for (const auto& ref : reference_surfaces_) {
163     DCHECK_NE(ref->output_record(), output_record_);
164     base::StringAppendF(&out, " %d", ref->output_record());
165   }
166   return out;
167 }
168 
InputRecord()169 V4L2SliceVideoDecodeAccelerator::InputRecord::InputRecord()
170     : input_id(-1),
171       address(nullptr),
172       length(0),
173       bytes_used(0),
174       at_device(false) {}
175 
OutputRecord()176 V4L2SliceVideoDecodeAccelerator::OutputRecord::OutputRecord()
177     : at_device(false),
178       at_client(false),
179       picture_id(-1),
180       cleared(false) {}
181 
182 struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef {
183   BitstreamBufferRef(
184       base::WeakPtr<VideoDecodeAccelerator::Client>& client,
185       const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
186       SharedMemoryRegion* shm,
187       int32_t input_id);
188   ~BitstreamBufferRef();
189   const base::WeakPtr<VideoDecodeAccelerator::Client> client;
190   const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner;
191   const std::unique_ptr<SharedMemoryRegion> shm;
192   off_t bytes_used;
193   const int32_t input_id;
194 };
195 
BitstreamBufferRef(base::WeakPtr<VideoDecodeAccelerator::Client> & client,const scoped_refptr<base::SingleThreadTaskRunner> & client_task_runner,SharedMemoryRegion * shm,int32_t input_id)196 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef(
197     base::WeakPtr<VideoDecodeAccelerator::Client>& client,
198     const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
199     SharedMemoryRegion* shm,
200     int32_t input_id)
201     : client(client),
202       client_task_runner(client_task_runner),
203       shm(shm),
204       bytes_used(0),
205       input_id(input_id) {}
206 
~BitstreamBufferRef()207 V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::~BitstreamBufferRef() {
208   if (input_id >= 0) {
209     DVLOGF(5) << "returning input_id: " << input_id;
210     client_task_runner->PostTask(
211         FROM_HERE,
212         base::Bind(&VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer,
213                    client, input_id));
214   }
215 }
216 
PictureRecord(bool cleared,const Picture & picture)217 V4L2SliceVideoDecodeAccelerator::PictureRecord::PictureRecord(
218     bool cleared,
219     const Picture& picture)
220     : cleared(cleared), picture(picture) {}
221 
~PictureRecord()222 V4L2SliceVideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
223 
224 class V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator
225     : public H264Decoder::H264Accelerator {
226  public:
227   explicit V4L2H264Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
228   ~V4L2H264Accelerator() override;
229 
230   // H264Decoder::H264Accelerator implementation.
231   scoped_refptr<H264Picture> CreateH264Picture() override;
232 
233   bool SubmitFrameMetadata(const H264SPS* sps,
234                            const H264PPS* pps,
235                            const H264DPB& dpb,
236                            const H264Picture::Vector& ref_pic_listp0,
237                            const H264Picture::Vector& ref_pic_listb0,
238                            const H264Picture::Vector& ref_pic_listb1,
239                            const scoped_refptr<H264Picture>& pic) override;
240 
241   bool SubmitSlice(const H264PPS* pps,
242                    const H264SliceHeader* slice_hdr,
243                    const H264Picture::Vector& ref_pic_list0,
244                    const H264Picture::Vector& ref_pic_list1,
245                    const scoped_refptr<H264Picture>& pic,
246                    const uint8_t* data,
247                    size_t size) override;
248 
249   bool SubmitDecode(const scoped_refptr<H264Picture>& pic) override;
250   bool OutputPicture(const scoped_refptr<H264Picture>& pic) override;
251 
252   void Reset() override;
253 
254  private:
255   // Max size of reference list.
256   static const size_t kDPBIndicesListSize = 32;
257   void H264PictureListToDPBIndicesList(const H264Picture::Vector& src_pic_list,
258                                        uint8_t dst_list[kDPBIndicesListSize]);
259 
260   void H264DPBToV4L2DPB(
261       const H264DPB& dpb,
262       std::vector<scoped_refptr<V4L2DecodeSurface>>* ref_surfaces);
263 
264   scoped_refptr<V4L2DecodeSurface> H264PictureToV4L2DecodeSurface(
265       const scoped_refptr<H264Picture>& pic);
266 
267   size_t num_slices_;
268   V4L2SliceVideoDecodeAccelerator* v4l2_dec_;
269 
270   // TODO(posciak): This should be queried from hardware once supported.
271   static const size_t kMaxSlices = 16;
272   struct v4l2_ctrl_h264_slice_param v4l2_slice_params_[kMaxSlices];
273   struct v4l2_ctrl_h264_decode_param v4l2_decode_param_;
274 
275   DISALLOW_COPY_AND_ASSIGN(V4L2H264Accelerator);
276 };
277 
278 class V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator
279     : public VP8Decoder::VP8Accelerator {
280  public:
281   explicit V4L2VP8Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
282   ~V4L2VP8Accelerator() override;
283 
284   // VP8Decoder::VP8Accelerator implementation.
285   scoped_refptr<VP8Picture> CreateVP8Picture() override;
286 
287   bool SubmitDecode(const scoped_refptr<VP8Picture>& pic,
288                     const Vp8FrameHeader* frame_hdr,
289                     const scoped_refptr<VP8Picture>& last_frame,
290                     const scoped_refptr<VP8Picture>& golden_frame,
291                     const scoped_refptr<VP8Picture>& alt_frame) override;
292 
293   bool OutputPicture(const scoped_refptr<VP8Picture>& pic) override;
294 
295  private:
296   scoped_refptr<V4L2DecodeSurface> VP8PictureToV4L2DecodeSurface(
297       const scoped_refptr<VP8Picture>& pic);
298 
299   V4L2SliceVideoDecodeAccelerator* v4l2_dec_;
300 
301   DISALLOW_COPY_AND_ASSIGN(V4L2VP8Accelerator);
302 };
303 
304 class V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator
305     : public VP9Decoder::VP9Accelerator {
306  public:
307   explicit V4L2VP9Accelerator(V4L2SliceVideoDecodeAccelerator* v4l2_dec);
308   ~V4L2VP9Accelerator() override;
309 
310   // VP9Decoder::VP9Accelerator implementation.
311   scoped_refptr<VP9Picture> CreateVP9Picture() override;
312 
313   bool SubmitDecode(const scoped_refptr<VP9Picture>& pic,
314                     const Vp9SegmentationParams& segm_params,
315                     const Vp9LoopFilterParams& lf_params,
316                     const std::vector<scoped_refptr<VP9Picture>>& ref_pictures,
317                     const base::Closure& done_cb) override;
318 
319   bool OutputPicture(const scoped_refptr<VP9Picture>& pic) override;
320 
321   bool GetFrameContext(const scoped_refptr<VP9Picture>& pic,
322                        Vp9FrameContext* frame_ctx) override;
323 
IsFrameContextRequired() const324   bool IsFrameContextRequired() const override {
325     return device_needs_frame_context_;
326   }
327 
328  private:
329   scoped_refptr<V4L2DecodeSurface> VP9PictureToV4L2DecodeSurface(
330       const scoped_refptr<VP9Picture>& pic);
331 
332   bool device_needs_frame_context_;
333 
334   V4L2SliceVideoDecodeAccelerator* v4l2_dec_;
335 
336   DISALLOW_COPY_AND_ASSIGN(V4L2VP9Accelerator);
337 };
338 
339 // Codec-specific subclasses of software decoder picture classes.
340 // This allows us to keep decoders oblivious of our implementation details.
341 class V4L2H264Picture : public H264Picture {
342  public:
343   explicit V4L2H264Picture(
344       const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
345           dec_surface);
346 
AsV4L2H264Picture()347   V4L2H264Picture* AsV4L2H264Picture() override { return this; }
348   scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
dec_surface()349   dec_surface() {
350     return dec_surface_;
351   }
352 
353  private:
354   ~V4L2H264Picture() override;
355 
356   scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
357       dec_surface_;
358 
359   DISALLOW_COPY_AND_ASSIGN(V4L2H264Picture);
360 };
361 
V4L2H264Picture(const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> & dec_surface)362 V4L2H264Picture::V4L2H264Picture(
363     const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
364         dec_surface)
365     : dec_surface_(dec_surface) {}
366 
~V4L2H264Picture()367 V4L2H264Picture::~V4L2H264Picture() {}
368 
369 class V4L2VP8Picture : public VP8Picture {
370  public:
371   explicit V4L2VP8Picture(
372       const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
373           dec_surface);
374 
AsV4L2VP8Picture()375   V4L2VP8Picture* AsV4L2VP8Picture() override { return this; }
376   scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
dec_surface()377   dec_surface() {
378     return dec_surface_;
379   }
380 
381  private:
382   ~V4L2VP8Picture() override;
383 
384   scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
385       dec_surface_;
386 
387   DISALLOW_COPY_AND_ASSIGN(V4L2VP8Picture);
388 };
389 
V4L2VP8Picture(const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> & dec_surface)390 V4L2VP8Picture::V4L2VP8Picture(
391     const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
392         dec_surface)
393     : dec_surface_(dec_surface) {}
394 
~V4L2VP8Picture()395 V4L2VP8Picture::~V4L2VP8Picture() {}
396 
397 class V4L2VP9Picture : public VP9Picture {
398  public:
399   explicit V4L2VP9Picture(
400       const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
401           dec_surface);
402 
AsV4L2VP9Picture()403   V4L2VP9Picture* AsV4L2VP9Picture() override { return this; }
404   scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
dec_surface()405   dec_surface() {
406     return dec_surface_;
407   }
408 
409  private:
410   ~V4L2VP9Picture() override;
411 
412   scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
413       dec_surface_;
414 
415   DISALLOW_COPY_AND_ASSIGN(V4L2VP9Picture);
416 };
417 
V4L2VP9Picture(const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> & dec_surface)418 V4L2VP9Picture::V4L2VP9Picture(
419     const scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>&
420         dec_surface)
421     : dec_surface_(dec_surface) {}
422 
~V4L2VP9Picture()423 V4L2VP9Picture::~V4L2VP9Picture() {}
424 
V4L2SliceVideoDecodeAccelerator(const scoped_refptr<V4L2Device> & device)425 V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator(
426     const scoped_refptr<V4L2Device>& device)
427     : input_planes_count_(0),
428       output_planes_count_(0),
429       child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
430       device_(device),
431       decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"),
432       device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"),
433       input_streamon_(false),
434       input_buffer_queued_count_(0),
435       output_streamon_(false),
436       output_buffer_queued_count_(0),
437       video_profile_(VIDEO_CODEC_PROFILE_UNKNOWN),
438       input_format_fourcc_(0),
439       output_format_fourcc_(0),
440       state_(kUninitialized),
441       output_mode_(Config::OutputMode::ALLOCATE),
442       decoder_flushing_(false),
443       decoder_resetting_(false),
444       surface_set_change_pending_(false),
445       picture_clearing_count_(0),
446       weak_this_factory_(this) {
447   weak_this_ = weak_this_factory_.GetWeakPtr();
448 }
449 
~V4L2SliceVideoDecodeAccelerator()450 V4L2SliceVideoDecodeAccelerator::~V4L2SliceVideoDecodeAccelerator() {
451   DVLOGF(2);
452 
453   DCHECK(child_task_runner_->BelongsToCurrentThread());
454   DCHECK(!decoder_thread_.IsRunning());
455   DCHECK(!device_poll_thread_.IsRunning());
456 
457   DCHECK(input_buffer_map_.empty());
458   DCHECK(output_buffer_map_.empty());
459 }
460 
NotifyError(Error error)461 void V4L2SliceVideoDecodeAccelerator::NotifyError(Error error) {
462   if (!child_task_runner_->BelongsToCurrentThread()) {
463     child_task_runner_->PostTask(
464         FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::NotifyError,
465                               weak_this_, error));
466     return;
467   }
468 
469   if (client_) {
470     client_->NotifyError(error);
471     client_ptr_factory_.reset();
472   }
473 }
474 
Initialize(const Config & config,Client * client)475 bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
476                                                  Client* client) {
477   DVLOGF(3) << "profile: " << config.profile;
478   DCHECK(child_task_runner_->BelongsToCurrentThread());
479   DCHECK_EQ(state_, kUninitialized);
480 
481   if (config.output_mode != Config::OutputMode::ALLOCATE &&
482       config.output_mode != Config::OutputMode::IMPORT) {
483     NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported";
484     return false;
485   }
486 
487   client_ptr_factory_.reset(
488       new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client));
489   client_ = client_ptr_factory_->GetWeakPtr();
490   // If we haven't been set up to decode on separate thread via
491   // TryToSetupDecodeOnSeparateThread(), use the main thread/client for
492   // decode tasks.
493   if (!decode_task_runner_) {
494     decode_task_runner_ = child_task_runner_;
495     DCHECK(!decode_client_);
496     decode_client_ = client_;
497   }
498 
499   video_profile_ = config.profile;
500 
501   // TODO(posciak): This needs to be queried once supported.
502   input_planes_count_ = 1;
503   output_planes_count_ = 1;
504 
505   input_format_fourcc_ =
506       V4L2Device::VideoCodecProfileToV4L2PixFmt(video_profile_, true);
507 
508   if (!device_->Open(V4L2Device::Type::kDecoder, input_format_fourcc_)) {
509     DVLOGF(1) << "Failed to open device for profile: " << config.profile
510               << " fourcc: " << std::hex << "0x" << input_format_fourcc_;
511     return false;
512   }
513 
514   if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) {
515     h264_accelerator_.reset(new V4L2H264Accelerator(this));
516     decoder_.reset(new H264Decoder(h264_accelerator_.get()));
517   } else if (video_profile_ >= VP8PROFILE_MIN &&
518              video_profile_ <= VP8PROFILE_MAX) {
519     vp8_accelerator_.reset(new V4L2VP8Accelerator(this));
520     decoder_.reset(new VP8Decoder(vp8_accelerator_.get()));
521   } else if (video_profile_ >= VP9PROFILE_MIN &&
522              video_profile_ <= VP9PROFILE_MAX) {
523     vp9_accelerator_.reset(new V4L2VP9Accelerator(this));
524     decoder_.reset(new VP9Decoder(vp9_accelerator_.get()));
525   } else {
526     NOTREACHED() << "Unsupported profile " << video_profile_;
527     return false;
528   }
529 
530   // Capabilities check.
531   struct v4l2_capability caps;
532   const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
533   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
534   if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
535     LOGF(ERROR) << "ioctl() failed: VIDIOC_QUERYCAP"
536                 << ", caps check failed: 0x" << std::hex << caps.capabilities;
537     return false;
538   }
539 
540   if (!SetupFormats())
541     return false;
542 
543   if (!decoder_thread_.Start()) {
544     DLOGF(ERROR) << "device thread failed to start";
545     return false;
546   }
547   decoder_thread_task_runner_ = decoder_thread_.task_runner();
548 
549   state_ = kInitialized;
550   output_mode_ = config.output_mode;
551 
552   // InitializeTask will NOTIFY_ERROR on failure.
553   decoder_thread_task_runner_->PostTask(
554       FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::InitializeTask,
555                             base::Unretained(this)));
556 
557   DVLOGF(1) << "V4L2SliceVideoDecodeAccelerator initialized";
558   return true;
559 }
560 
InitializeTask()561 void V4L2SliceVideoDecodeAccelerator::InitializeTask() {
562   DVLOGF(3);
563   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
564   DCHECK_EQ(state_, kInitialized);
565 
566   if (!CreateInputBuffers())
567     NOTIFY_ERROR(PLATFORM_FAILURE);
568 
569   // Output buffers will be created once decoder gives us information
570   // about their size and required count.
571   state_ = kDecoding;
572 }
573 
Destroy()574 void V4L2SliceVideoDecodeAccelerator::Destroy() {
575   DVLOGF(3);
576   DCHECK(child_task_runner_->BelongsToCurrentThread());
577 
578   if (decoder_thread_.IsRunning()) {
579     decoder_thread_task_runner_->PostTask(
580         FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DestroyTask,
581                               base::Unretained(this)));
582 
583     // Wait for tasks to finish/early-exit.
584     decoder_thread_.Stop();
585   }
586 
587   delete this;
588   DVLOGF(3) << "Destroyed";
589 }
590 
DestroyTask()591 void V4L2SliceVideoDecodeAccelerator::DestroyTask() {
592   DVLOGF(3);
593   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
594 
595   state_ = kError;
596 
597   decoder_->Reset();
598 
599   decoder_current_bitstream_buffer_.reset();
600   while (!decoder_input_queue_.empty())
601     decoder_input_queue_.pop();
602 
603   // Stop streaming and the device_poll_thread_.
604   StopDevicePoll(false);
605 
606   DestroyInputBuffers();
607   DestroyOutputs(false);
608 
609   DCHECK(surfaces_at_device_.empty());
610   DCHECK(surfaces_at_display_.empty());
611   DCHECK(decoder_display_queue_.empty());
612 }
613 
IsSupportedOutputFormat(uint32_t v4l2_format)614 static bool IsSupportedOutputFormat(uint32_t v4l2_format) {
615   // Only support V4L2_PIX_FMT_NV12 output format for now.
616   // TODO(johnylin): add more supported format if necessary.
617   uint32_t kSupportedOutputFmtFourcc[] = { V4L2_PIX_FMT_NV12 };
618   return std::find(
619       kSupportedOutputFmtFourcc,
620       kSupportedOutputFmtFourcc + arraysize(kSupportedOutputFmtFourcc),
621       v4l2_format) !=
622           kSupportedOutputFmtFourcc + arraysize(kSupportedOutputFmtFourcc);
623 }
624 
SetupFormats()625 bool V4L2SliceVideoDecodeAccelerator::SetupFormats() {
626   DCHECK_EQ(state_, kUninitialized);
627 
628   size_t input_size;
629   Size max_resolution, min_resolution;
630   device_->GetSupportedResolution(input_format_fourcc_, &min_resolution,
631                                   &max_resolution);
632   if (max_resolution.width() > 1920 && max_resolution.height() > 1088)
633     input_size = kInputBufferMaxSizeFor4k;
634   else
635     input_size = kInputBufferMaxSizeFor1080p;
636 
637   struct v4l2_fmtdesc fmtdesc;
638   memset(&fmtdesc, 0, sizeof(fmtdesc));
639   fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
640   bool is_format_supported = false;
641   while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
642     if (fmtdesc.pixelformat == input_format_fourcc_) {
643       is_format_supported = true;
644       break;
645     }
646     ++fmtdesc.index;
647   }
648 
649   if (!is_format_supported) {
650     DVLOGF(1) << "Input fourcc " << input_format_fourcc_
651               << " not supported by device.";
652     return false;
653   }
654 
655   struct v4l2_format format;
656   memset(&format, 0, sizeof(format));
657   format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
658   format.fmt.pix_mp.pixelformat = input_format_fourcc_;
659   format.fmt.pix_mp.plane_fmt[0].sizeimage = input_size;
660   format.fmt.pix_mp.num_planes = input_planes_count_;
661   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
662 
663   // We have to set up the format for output, because the driver may not allow
664   // changing it once we start streaming; whether it can support our chosen
665   // output format or not may depend on the input format.
666   memset(&fmtdesc, 0, sizeof(fmtdesc));
667   fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
668   output_format_fourcc_ = 0;
669   while (device_->Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
670     if (IsSupportedOutputFormat(fmtdesc.pixelformat)) {
671       output_format_fourcc_ = fmtdesc.pixelformat;
672       break;
673     }
674     ++fmtdesc.index;
675   }
676 
677   if (output_format_fourcc_ == 0) {
678     LOGF(ERROR) << "Could not find a usable output format";
679     return false;
680   }
681 
682   // Only set fourcc for output; resolution, etc., will come from the
683   // driver once it extracts it from the stream.
684   memset(&format, 0, sizeof(format));
685   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
686   format.fmt.pix_mp.pixelformat = output_format_fourcc_;
687   format.fmt.pix_mp.num_planes = output_planes_count_;
688   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
689 
690   return true;
691 }
692 
CreateInputBuffers()693 bool V4L2SliceVideoDecodeAccelerator::CreateInputBuffers() {
694   DVLOGF(3);
695   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
696   DCHECK(!input_streamon_);
697   DCHECK(input_buffer_map_.empty());
698 
699   struct v4l2_requestbuffers reqbufs;
700   memset(&reqbufs, 0, sizeof(reqbufs));
701   reqbufs.count = kNumInputBuffers;
702   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
703   reqbufs.memory = V4L2_MEMORY_MMAP;
704   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
705   if (reqbufs.count < kNumInputBuffers) {
706     PLOGF(ERROR) << "Could not allocate enough output buffers";
707     return false;
708   }
709   input_buffer_map_.resize(reqbufs.count);
710   for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
711     free_input_buffers_.push_back(i);
712 
713     // Query for the MEMORY_MMAP pointer.
714     struct v4l2_plane planes[VIDEO_MAX_PLANES];
715     struct v4l2_buffer buffer;
716     memset(&buffer, 0, sizeof(buffer));
717     memset(planes, 0, sizeof(planes));
718     buffer.index = i;
719     buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
720     buffer.memory = V4L2_MEMORY_MMAP;
721     buffer.m.planes = planes;
722     buffer.length = input_planes_count_;
723     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYBUF, &buffer);
724     void* address = device_->Mmap(nullptr,
725                                   buffer.m.planes[0].length,
726                                   PROT_READ | PROT_WRITE,
727                                   MAP_SHARED,
728                                   buffer.m.planes[0].m.mem_offset);
729     if (address == MAP_FAILED) {
730       PLOGF(ERROR) << "mmap() failed";
731       return false;
732     }
733     input_buffer_map_[i].address = address;
734     input_buffer_map_[i].length = buffer.m.planes[0].length;
735   }
736 
737   return true;
738 }
739 
CreateOutputBuffers()740 bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() {
741   DVLOGF(3);
742   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
743   DCHECK(!output_streamon_);
744   DCHECK(output_buffer_map_.empty());
745   DCHECK(surfaces_at_display_.empty());
746   DCHECK(surfaces_at_device_.empty());
747 
748   visible_size_ = decoder_->GetPicSize();
749   size_t num_pictures = decoder_->GetRequiredNumOfPictures();
750 
751   DCHECK_GT(num_pictures, 0u);
752   DCHECK(!visible_size_.IsEmpty());
753 
754   struct v4l2_format format;
755   memset(&format, 0, sizeof(format));
756   format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
757   format.fmt.pix_mp.pixelformat = output_format_fourcc_;
758   format.fmt.pix_mp.width = visible_size_.width();
759   format.fmt.pix_mp.height = visible_size_.height();
760   format.fmt.pix_mp.num_planes = input_planes_count_;
761 
762   if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) {
763     PLOGF(ERROR) << "Failed setting format to: " << output_format_fourcc_;
764     NOTIFY_ERROR(PLATFORM_FAILURE);
765     return false;
766   }
767 
768   coded_size_.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width),
769                       base::checked_cast<int>(format.fmt.pix_mp.height));
770   DCHECK_EQ(coded_size_.width() % 16, 0);
771   DCHECK_EQ(coded_size_.height() % 16, 0);
772 
773   if (!Rect(coded_size_).Contains(Rect(visible_size_))) {
774     LOGF(ERROR) << "Got invalid adjusted coded size: "
775                 << coded_size_.ToString();
776     return false;
777   }
778 
779   DVLOGF(3) << "buffer_count=" << num_pictures
780             << ", visible size=" << visible_size_.ToString()
781             << ", coded size=" << coded_size_.ToString();
782 
783   // With ALLOCATE mode the client can sample it as RGB and doesn't need to
784   // know the precise format.
785   VideoPixelFormat pixel_format =
786       (output_mode_ == Config::OutputMode::IMPORT)
787           ? V4L2Device::V4L2PixFmtToVideoPixelFormat(output_format_fourcc_)
788           : PIXEL_FORMAT_UNKNOWN;
789 
790   child_task_runner_->PostTask(
791       FROM_HERE,
792       base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers,
793                  client_, num_pictures, pixel_format, coded_size_));
794 
795   // Go into kAwaitingPictureBuffers to prevent us from doing any more decoding
796   // or event handling while we are waiting for AssignPictureBuffers(). Not
797   // having Pictures available would not have prevented us from making decoding
798   // progress entirely e.g. in the case of H.264 where we could further decode
799   // non-slice NALUs and could even get another resolution change before we were
800   // done with this one. After we get the buffers, we'll go back into kIdle and
801   // kick off further event processing, and eventually go back into kDecoding
802   // once no more events are pending (if any).
803   state_ = kAwaitingPictureBuffers;
804   return true;
805 }
806 
DestroyInputBuffers()807 void V4L2SliceVideoDecodeAccelerator::DestroyInputBuffers() {
808   DVLOGF(3);
809   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() ||
810          !decoder_thread_.IsRunning());
811   DCHECK(!input_streamon_);
812 
813   if (input_buffer_map_.empty())
814     return;
815 
816   for (auto& input_record : input_buffer_map_) {
817     if (input_record.address != nullptr)
818       device_->Munmap(input_record.address, input_record.length);
819   }
820 
821   struct v4l2_requestbuffers reqbufs;
822   memset(&reqbufs, 0, sizeof(reqbufs));
823   reqbufs.count = 0;
824   reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
825   reqbufs.memory = V4L2_MEMORY_MMAP;
826   IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
827 
828   input_buffer_map_.clear();
829   free_input_buffers_.clear();
830 }
831 
DismissPictures(const std::vector<int32_t> & picture_buffer_ids,base::WaitableEvent * done)832 void V4L2SliceVideoDecodeAccelerator::DismissPictures(
833     const std::vector<int32_t>& picture_buffer_ids,
834     base::WaitableEvent* done) {
835   DVLOGF(3);
836   DCHECK(child_task_runner_->BelongsToCurrentThread());
837 
838   for (auto picture_buffer_id : picture_buffer_ids) {
839     DVLOGF(1) << "dismissing PictureBuffer id=" << picture_buffer_id;
840     client_->DismissPictureBuffer(picture_buffer_id);
841   }
842 
843   done->Signal();
844 }
845 
DevicePollTask(bool poll_device)846 void V4L2SliceVideoDecodeAccelerator::DevicePollTask(bool poll_device) {
847   DVLOGF(4);
848   DCHECK(device_poll_thread_.task_runner()->BelongsToCurrentThread());
849 
850   bool event_pending;
851   if (!device_->Poll(poll_device, &event_pending)) {
852     NOTIFY_ERROR(PLATFORM_FAILURE);
853     return;
854   }
855 
856   // All processing should happen on ServiceDeviceTask(), since we shouldn't
857   // touch encoder state from this thread.
858   decoder_thread_task_runner_->PostTask(
859       FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ServiceDeviceTask,
860                             base::Unretained(this)));
861 }
862 
ServiceDeviceTask()863 void V4L2SliceVideoDecodeAccelerator::ServiceDeviceTask() {
864   DVLOGF(4);
865   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
866 
867   // ServiceDeviceTask() should only ever be scheduled from DevicePollTask().
868 
869   Dequeue();
870   SchedulePollIfNeeded();
871 }
872 
SchedulePollIfNeeded()873 void V4L2SliceVideoDecodeAccelerator::SchedulePollIfNeeded() {
874   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
875 
876   if (!device_poll_thread_.IsRunning()) {
877     DVLOGF(2) << "Device poll thread stopped, will not schedule poll";
878     return;
879   }
880 
881   DCHECK(input_streamon_ || output_streamon_);
882 
883   if (input_buffer_queued_count_ + output_buffer_queued_count_ == 0) {
884     DVLOGF(4) << "No buffers queued, will not schedule poll";
885     return;
886   }
887 
888   DVLOGF(4) << "Scheduling device poll task";
889 
890   device_poll_thread_.task_runner()->PostTask(
891       FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DevicePollTask,
892                             base::Unretained(this), true));
893 
894   DVLOGF(2) << "buffer counts: "
895             << "INPUT[" << decoder_input_queue_.size() << "]"
896             << " => DEVICE["
897             << free_input_buffers_.size() << "+"
898             << input_buffer_queued_count_ << "/"
899             << input_buffer_map_.size() << "]->["
900             << free_output_buffers_.size() << "+"
901             << output_buffer_queued_count_ << "/"
902             << output_buffer_map_.size() << "]"
903             << " => DISPLAYQ[" << decoder_display_queue_.size() << "]"
904             << " => CLIENT[" << surfaces_at_display_.size() << "]";
905 }
906 
Enqueue(const scoped_refptr<V4L2DecodeSurface> & dec_surface)907 void V4L2SliceVideoDecodeAccelerator::Enqueue(
908     const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
909   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
910 
911   const int old_inputs_queued = input_buffer_queued_count_;
912   const int old_outputs_queued = output_buffer_queued_count_;
913 
914   if (!EnqueueInputRecord(dec_surface->input_record(),
915                           dec_surface->config_store())) {
916     DVLOGF(1) << "Failed queueing an input buffer";
917     NOTIFY_ERROR(PLATFORM_FAILURE);
918     return;
919   }
920 
921   if (!EnqueueOutputRecord(dec_surface->output_record())) {
922     DVLOGF(1) << "Failed queueing an output buffer";
923     NOTIFY_ERROR(PLATFORM_FAILURE);
924     return;
925   }
926 
927   bool inserted =
928       surfaces_at_device_
929           .insert(std::make_pair(dec_surface->output_record(), dec_surface))
930           .second;
931   DCHECK(inserted);
932 
933   if (old_inputs_queued == 0 && old_outputs_queued == 0)
934     SchedulePollIfNeeded();
935 }
936 
Dequeue()937 void V4L2SliceVideoDecodeAccelerator::Dequeue() {
938   DVLOGF(3);
939   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
940 
941   struct v4l2_buffer dqbuf;
942   struct v4l2_plane planes[VIDEO_MAX_PLANES];
943   while (input_buffer_queued_count_ > 0) {
944     DCHECK(input_streamon_);
945     memset(&dqbuf, 0, sizeof(dqbuf));
946     memset(&planes, 0, sizeof(planes));
947     dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
948     dqbuf.memory = V4L2_MEMORY_MMAP;
949     dqbuf.m.planes = planes;
950     dqbuf.length = input_planes_count_;
951     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
952       if (errno == EAGAIN) {
953         // EAGAIN if we're just out of buffers to dequeue.
954         break;
955       }
956       PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
957       NOTIFY_ERROR(PLATFORM_FAILURE);
958       return;
959     }
960     InputRecord& input_record = input_buffer_map_[dqbuf.index];
961     DCHECK(input_record.at_device);
962     input_record.at_device = false;
963     ReuseInputBuffer(dqbuf.index);
964     input_buffer_queued_count_--;
965     DVLOGF(4) << "Dequeued input=" << dqbuf.index
966               << " count: " << input_buffer_queued_count_;
967   }
968 
969   while (output_buffer_queued_count_ > 0) {
970     DCHECK(output_streamon_);
971     memset(&dqbuf, 0, sizeof(dqbuf));
972     memset(&planes, 0, sizeof(planes));
973     dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
974     dqbuf.memory =
975         (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP
976                                                       : V4L2_MEMORY_DMABUF);
977     dqbuf.m.planes = planes;
978     dqbuf.length = output_planes_count_;
979     if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
980       if (errno == EAGAIN) {
981         // EAGAIN if we're just out of buffers to dequeue.
982         break;
983       }
984       PLOGF(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
985       NOTIFY_ERROR(PLATFORM_FAILURE);
986       return;
987     }
988     OutputRecord& output_record = output_buffer_map_[dqbuf.index];
989     DCHECK(output_record.at_device);
990     output_record.at_device = false;
991     output_buffer_queued_count_--;
992     DVLOGF(3) << "Dequeued output=" << dqbuf.index
993               << " count " << output_buffer_queued_count_;
994 
995     V4L2DecodeSurfaceByOutputId::iterator it =
996         surfaces_at_device_.find(dqbuf.index);
997     if (it == surfaces_at_device_.end()) {
998       DLOGF(ERROR) << "Got invalid surface from device.";
999       NOTIFY_ERROR(PLATFORM_FAILURE);
1000       return;
1001     }
1002 
1003     it->second->SetDecoded();
1004     surfaces_at_device_.erase(it);
1005   }
1006 
1007   // A frame was decoded, see if we can output it.
1008   TryOutputSurfaces();
1009 
1010   ProcessPendingEventsIfNeeded();
1011   ScheduleDecodeBufferTaskIfNeeded();
1012 }
1013 
NewEventPending()1014 void V4L2SliceVideoDecodeAccelerator::NewEventPending() {
1015   // Switch to event processing mode if we are decoding. Otherwise we are either
1016   // already in it, or we will potentially switch to it later, after finishing
1017   // other tasks.
1018   if (state_ == kDecoding)
1019     state_ = kIdle;
1020 
1021   ProcessPendingEventsIfNeeded();
1022 }
1023 
FinishEventProcessing()1024 bool V4L2SliceVideoDecodeAccelerator::FinishEventProcessing() {
1025   DCHECK_EQ(state_, kIdle);
1026 
1027   state_ = kDecoding;
1028   ScheduleDecodeBufferTaskIfNeeded();
1029 
1030   return true;
1031 }
1032 
ProcessPendingEventsIfNeeded()1033 void V4L2SliceVideoDecodeAccelerator::ProcessPendingEventsIfNeeded() {
1034   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1035 
1036   // Process pending events, if any, in the correct order.
1037   // We always first process the surface set change, as it is an internal
1038   // event from the decoder and interleaving it with external requests would
1039   // put the decoder in an undefined state.
1040   using ProcessFunc = bool (V4L2SliceVideoDecodeAccelerator::*)();
1041   const ProcessFunc process_functions[] = {
1042       &V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChange,
1043       &V4L2SliceVideoDecodeAccelerator::FinishFlush,
1044       &V4L2SliceVideoDecodeAccelerator::FinishReset,
1045       &V4L2SliceVideoDecodeAccelerator::FinishEventProcessing,
1046   };
1047 
1048   for (const auto& fn : process_functions) {
1049     if (state_ != kIdle)
1050       return;
1051 
1052     if (!(this->*fn)())
1053       return;
1054   }
1055 }
1056 
ReuseInputBuffer(int index)1057 void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) {
1058   DVLOGF(4) << "Reusing input buffer, index=" << index;
1059   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1060 
1061   DCHECK_LT(index, static_cast<int>(input_buffer_map_.size()));
1062   InputRecord& input_record = input_buffer_map_[index];
1063 
1064   DCHECK(!input_record.at_device);
1065   input_record.input_id = -1;
1066   input_record.bytes_used = 0;
1067 
1068   DCHECK_EQ(
1069       std::count(free_input_buffers_.begin(), free_input_buffers_.end(), index),
1070       0);
1071   free_input_buffers_.push_back(index);
1072 }
1073 
ReuseOutputBuffer(int index)1074 void V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer(int index) {
1075   DVLOGF(4) << "Reusing output buffer, index=" << index;
1076   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1077 
1078   DCHECK_LT(index, static_cast<int>(output_buffer_map_.size()));
1079   OutputRecord& output_record = output_buffer_map_[index];
1080   DCHECK(!output_record.at_device);
1081   DCHECK(!output_record.at_client);
1082 
1083   DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(),
1084                        index),
1085             0);
1086   free_output_buffers_.push_back(index);
1087 
1088   ScheduleDecodeBufferTaskIfNeeded();
1089 }
1090 
EnqueueInputRecord(int index,uint32_t config_store)1091 bool V4L2SliceVideoDecodeAccelerator::EnqueueInputRecord(
1092     int index,
1093     uint32_t config_store) {
1094   DVLOGF(3);
1095   DCHECK_LT(index, static_cast<int>(input_buffer_map_.size()));
1096   DCHECK_GT(config_store, 0u);
1097 
1098   // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
1099   InputRecord& input_record = input_buffer_map_[index];
1100   DCHECK(!input_record.at_device);
1101   struct v4l2_buffer qbuf;
1102   struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES];
1103   memset(&qbuf, 0, sizeof(qbuf));
1104   memset(qbuf_planes, 0, sizeof(qbuf_planes));
1105   qbuf.index = index;
1106   qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1107   qbuf.memory = V4L2_MEMORY_MMAP;
1108   qbuf.m.planes = qbuf_planes;
1109   qbuf.m.planes[0].bytesused = input_record.bytes_used;
1110   qbuf.length = input_planes_count_;
1111   qbuf.config_store = config_store;
1112   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
1113   input_record.at_device = true;
1114   input_buffer_queued_count_++;
1115   DVLOGF(4) << "Enqueued input=" << qbuf.index
1116             << " count: " << input_buffer_queued_count_;
1117 
1118   return true;
1119 }
1120 
EnqueueOutputRecord(int index)1121 bool V4L2SliceVideoDecodeAccelerator::EnqueueOutputRecord(int index) {
1122   DVLOGF(3);
1123   DCHECK_LT(index, static_cast<int>(output_buffer_map_.size()));
1124 
1125   // Enqueue an output (VIDEO_CAPTURE) buffer.
1126   OutputRecord& output_record = output_buffer_map_[index];
1127   DCHECK(!output_record.at_device);
1128   DCHECK(!output_record.at_client);
1129   DCHECK_NE(output_record.picture_id, -1);
1130 
1131   struct v4l2_buffer qbuf;
1132   struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES];
1133   memset(&qbuf, 0, sizeof(qbuf));
1134   memset(qbuf_planes, 0, sizeof(qbuf_planes));
1135   qbuf.index = index;
1136   qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1137   if (output_mode_ == Config::OutputMode::ALLOCATE) {
1138     qbuf.memory = V4L2_MEMORY_MMAP;
1139   } else {
1140     qbuf.memory = V4L2_MEMORY_DMABUF;
1141     DCHECK_EQ(output_planes_count_, output_record.dmabuf_fds.size());
1142     for (size_t i = 0; i < output_record.dmabuf_fds.size(); ++i) {
1143       DCHECK(output_record.dmabuf_fds[i].is_valid());
1144       qbuf_planes[i].m.fd = output_record.dmabuf_fds[i].get();
1145     }
1146   }
1147   qbuf.m.planes = qbuf_planes;
1148   qbuf.length = output_planes_count_;
1149   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
1150   output_record.at_device = true;
1151   output_buffer_queued_count_++;
1152   DVLOGF(4) << "Enqueued output=" << qbuf.index
1153             << " count: " << output_buffer_queued_count_;
1154 
1155   return true;
1156 }
1157 
StartDevicePoll()1158 bool V4L2SliceVideoDecodeAccelerator::StartDevicePoll() {
1159   DVLOGF(3) << "Starting device poll";
1160   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1161   DCHECK(!device_poll_thread_.IsRunning());
1162 
1163   // Start up the device poll thread and schedule its first DevicePollTask().
1164   if (!device_poll_thread_.Start()) {
1165     DLOGF(ERROR) << "Device thread failed to start";
1166     NOTIFY_ERROR(PLATFORM_FAILURE);
1167     return false;
1168   }
1169   if (!input_streamon_) {
1170     __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1171     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMON, &type);
1172     input_streamon_ = true;
1173   }
1174 
1175   if (!output_streamon_) {
1176     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1177     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMON, &type);
1178     output_streamon_ = true;
1179   }
1180 
1181   device_poll_thread_.task_runner()->PostTask(
1182       FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DevicePollTask,
1183                             base::Unretained(this), true));
1184 
1185   return true;
1186 }
1187 
StopDevicePoll(bool keep_input_state)1188 bool V4L2SliceVideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) {
1189   DVLOGF(3) << "Stopping device poll";
1190   if (decoder_thread_.IsRunning())
1191     DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1192 
1193   // Signal the DevicePollTask() to stop, and stop the device poll thread.
1194   if (!device_->SetDevicePollInterrupt()) {
1195     PLOGF(ERROR) << "SetDevicePollInterrupt(): failed";
1196     NOTIFY_ERROR(PLATFORM_FAILURE);
1197     return false;
1198   }
1199   device_poll_thread_.Stop();
1200   DVLOGF(3) << "Device poll thread stopped";
1201 
1202   // Clear the interrupt now, to be sure.
1203   if (!device_->ClearDevicePollInterrupt()) {
1204     NOTIFY_ERROR(PLATFORM_FAILURE);
1205     return false;
1206   }
1207 
1208   if (!keep_input_state) {
1209     if (input_streamon_) {
1210       __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1211       IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type);
1212     }
1213     input_streamon_ = false;
1214   }
1215 
1216   if (output_streamon_) {
1217     __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1218     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_STREAMOFF, &type);
1219   }
1220   output_streamon_ = false;
1221 
1222   if (!keep_input_state) {
1223     for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
1224       InputRecord& input_record = input_buffer_map_[i];
1225       if (input_record.at_device) {
1226         input_record.at_device = false;
1227         ReuseInputBuffer(i);
1228         input_buffer_queued_count_--;
1229       }
1230     }
1231     DCHECK_EQ(input_buffer_queued_count_, 0);
1232   }
1233 
1234   // STREAMOFF makes the driver drop all buffers without decoding and DQBUFing,
1235   // so we mark them all as at_device = false and clear surfaces_at_device_.
1236   for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1237     OutputRecord& output_record = output_buffer_map_[i];
1238     if (output_record.at_device) {
1239       output_record.at_device = false;
1240       output_buffer_queued_count_--;
1241     }
1242   }
1243   surfaces_at_device_.clear();
1244   DCHECK_EQ(output_buffer_queued_count_, 0);
1245 
1246   // Drop all surfaces that were awaiting decode before being displayed,
1247   // since we've just cancelled all outstanding decodes.
1248   while (!decoder_display_queue_.empty())
1249     decoder_display_queue_.pop();
1250 
1251   DVLOGF(3) << "Device poll stopped";
1252   return true;
1253 }
1254 
Decode(const BitstreamBuffer & bitstream_buffer)1255 void V4L2SliceVideoDecodeAccelerator::Decode(
1256     const BitstreamBuffer& bitstream_buffer) {
1257   DVLOGF(3) << "input_id=" << bitstream_buffer.id()
1258             << ", size=" << bitstream_buffer.size();
1259   DCHECK(decode_task_runner_->BelongsToCurrentThread());
1260 
1261   if (bitstream_buffer.id() < 0) {
1262     LOGF(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
1263     if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
1264       base::SharedMemory::CloseHandle(bitstream_buffer.handle());
1265     NOTIFY_ERROR(INVALID_ARGUMENT);
1266     return;
1267   }
1268 
1269   decoder_thread_task_runner_->PostTask(
1270       FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeTask,
1271                             base::Unretained(this), bitstream_buffer));
1272 }
1273 
DecodeTask(const BitstreamBuffer & bitstream_buffer)1274 void V4L2SliceVideoDecodeAccelerator::DecodeTask(
1275     const BitstreamBuffer& bitstream_buffer) {
1276   DVLOGF(3) << "input_id=" << bitstream_buffer.id()
1277             << " size=" << bitstream_buffer.size();
1278   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1279 
1280   std::unique_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef(
1281       decode_client_, decode_task_runner_,
1282       new SharedMemoryRegion(bitstream_buffer, true), bitstream_buffer.id()));
1283 
1284   // Skip empty buffer.
1285   if (bitstream_buffer.size() == 0)
1286     return;
1287 
1288   if (!bitstream_record->shm->Map()) {
1289     LOGF(ERROR) << "Could not map bitstream_buffer";
1290     NOTIFY_ERROR(UNREADABLE_INPUT);
1291     return;
1292   }
1293   DVLOGF(3) << "mapped at=" << bitstream_record->shm->memory();
1294 
1295   decoder_input_queue_.push(
1296       linked_ptr<BitstreamBufferRef>(bitstream_record.release()));
1297 
1298   ScheduleDecodeBufferTaskIfNeeded();
1299 }
1300 
TrySetNewBistreamBuffer()1301 bool V4L2SliceVideoDecodeAccelerator::TrySetNewBistreamBuffer() {
1302   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1303   DCHECK(!decoder_current_bitstream_buffer_);
1304 
1305   if (decoder_input_queue_.empty())
1306     return false;
1307 
1308   decoder_current_bitstream_buffer_.reset(
1309       decoder_input_queue_.front().release());
1310   decoder_input_queue_.pop();
1311 
1312   if (decoder_current_bitstream_buffer_->input_id == kFlushBufferId) {
1313     // This is a buffer we queued for ourselves to trigger flush at this time.
1314     InitiateFlush();
1315     return false;
1316   }
1317 
1318   const uint8_t* const data = reinterpret_cast<const uint8_t*>(
1319       decoder_current_bitstream_buffer_->shm->memory());
1320   const size_t data_size = decoder_current_bitstream_buffer_->shm->size();
1321   decoder_->SetStream(data, data_size);
1322 
1323   return true;
1324 }
1325 
ScheduleDecodeBufferTaskIfNeeded()1326 void V4L2SliceVideoDecodeAccelerator::ScheduleDecodeBufferTaskIfNeeded() {
1327   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1328   if (state_ == kDecoding) {
1329     decoder_thread_task_runner_->PostTask(
1330         FROM_HERE,
1331         base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeBufferTask,
1332                    base::Unretained(this)));
1333   }
1334 }
1335 
DecodeBufferTask()1336 void V4L2SliceVideoDecodeAccelerator::DecodeBufferTask() {
1337   DVLOGF(3);
1338   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1339 
1340   if (state_ != kDecoding) {
1341     DVLOGF(3) << "Early exit, not in kDecoding";
1342     return;
1343   }
1344 
1345   while (true) {
1346     AcceleratedVideoDecoder::DecodeResult res;
1347     res = decoder_->Decode();
1348     switch (res) {
1349       case AcceleratedVideoDecoder::kAllocateNewSurfaces:
1350         DVLOGF(2) << "Decoder requesting a new set of surfaces";
1351         InitiateSurfaceSetChange();
1352         return;
1353 
1354       case AcceleratedVideoDecoder::kRanOutOfStreamData:
1355         decoder_current_bitstream_buffer_.reset();
1356         if (!TrySetNewBistreamBuffer())
1357           return;
1358 
1359         break;
1360 
1361       case AcceleratedVideoDecoder::kRanOutOfSurfaces:
1362         // No more surfaces for the decoder, we'll come back once we have more.
1363         DVLOGF(4) << "Ran out of surfaces";
1364         return;
1365 
1366       case AcceleratedVideoDecoder::kNeedContextUpdate:
1367         DVLOGF(4) << "Awaiting context update";
1368         return;
1369 
1370       case AcceleratedVideoDecoder::kDecodeError:
1371         DVLOGF(1) << "Error decoding stream";
1372         NOTIFY_ERROR(PLATFORM_FAILURE);
1373         return;
1374     }
1375   }
1376 }
1377 
InitiateSurfaceSetChange()1378 void V4L2SliceVideoDecodeAccelerator::InitiateSurfaceSetChange() {
1379   DVLOGF(2);
1380   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1381   DCHECK_EQ(state_, kDecoding);
1382 
1383   DCHECK(!surface_set_change_pending_);
1384   surface_set_change_pending_ = true;
1385   NewEventPending();
1386 }
1387 
FinishSurfaceSetChange()1388 bool V4L2SliceVideoDecodeAccelerator::FinishSurfaceSetChange() {
1389   DVLOGF(2);
1390   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1391 
1392   if (!surface_set_change_pending_)
1393     return true;
1394 
1395   if (!surfaces_at_device_.empty())
1396     return false;
1397 
1398   DCHECK_EQ(state_, kIdle);
1399   DCHECK(decoder_display_queue_.empty());
1400   // All output buffers should've been returned from decoder and device by now.
1401   // The only remaining owner of surfaces may be display (client), and we will
1402   // dismiss them when destroying output buffers below.
1403   DCHECK_EQ(free_output_buffers_.size() + surfaces_at_display_.size(),
1404             output_buffer_map_.size());
1405 
1406   // Keep input queue running while we switch outputs.
1407   if (!StopDevicePoll(true)) {
1408     NOTIFY_ERROR(PLATFORM_FAILURE);
1409     return false;
1410   }
1411 
1412   // This will return only once all buffers are dismissed and destroyed.
1413   // This does not wait until they are displayed however, as display retains
1414   // references to the buffers bound to textures and will release them
1415   // after displaying.
1416   if (!DestroyOutputs(true)) {
1417     NOTIFY_ERROR(PLATFORM_FAILURE);
1418     return false;
1419   }
1420 
1421   if (!CreateOutputBuffers()) {
1422     NOTIFY_ERROR(PLATFORM_FAILURE);
1423     return false;
1424   }
1425 
1426   surface_set_change_pending_ = false;
1427   DVLOGF(3) << "Surface set change finished";
1428   return true;
1429 }
1430 
DestroyOutputs(bool dismiss)1431 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputs(bool dismiss) {
1432   DVLOGF(3);
1433   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1434   std::vector<int32_t> picture_buffers_to_dismiss;
1435 
1436   if (output_buffer_map_.empty())
1437     return true;
1438 
1439   for (const auto& output_record : output_buffer_map_) {
1440     DCHECK(!output_record.at_device);
1441     picture_buffers_to_dismiss.push_back(output_record.picture_id);
1442   }
1443 
1444   if (dismiss) {
1445     DVLOGF(2) << "Scheduling picture dismissal";
1446     base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1447                              base::WaitableEvent::InitialState::NOT_SIGNALED);
1448     child_task_runner_->PostTask(
1449         FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DismissPictures,
1450                               weak_this_, picture_buffers_to_dismiss, &done));
1451     done.Wait();
1452   }
1453 
1454   // At this point client can't call ReusePictureBuffer on any of the pictures
1455   // anymore, so it's safe to destroy.
1456   return DestroyOutputBuffers();
1457 }
1458 
DestroyOutputBuffers()1459 bool V4L2SliceVideoDecodeAccelerator::DestroyOutputBuffers() {
1460   DVLOGF(3);
1461   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread() ||
1462          !decoder_thread_.IsRunning());
1463   DCHECK(!output_streamon_);
1464   DCHECK(surfaces_at_device_.empty());
1465   DCHECK(decoder_display_queue_.empty());
1466   DCHECK_EQ(surfaces_at_display_.size() + free_output_buffers_.size(),
1467             output_buffer_map_.size());
1468 
1469   if (output_buffer_map_.empty())
1470     return true;
1471 
1472   // It's ok to do this, client will retain references to textures, but we are
1473   // not interested in reusing the surfaces anymore.
1474   // This will prevent us from reusing old surfaces in case we have some
1475   // ReusePictureBuffer() pending on ChildThread already. It's ok to ignore
1476   // them, because we have already dismissed them (in DestroyOutputs()).
1477   for (const auto& surface_at_display : surfaces_at_display_) {
1478     size_t index = surface_at_display.second->output_record();
1479     DCHECK_LT(index, output_buffer_map_.size());
1480     OutputRecord& output_record = output_buffer_map_[index];
1481     DCHECK(output_record.at_client);
1482     output_record.at_client = false;
1483   }
1484   surfaces_at_display_.clear();
1485   DCHECK_EQ(free_output_buffers_.size(), output_buffer_map_.size());
1486 
1487   free_output_buffers_.clear();
1488   output_buffer_map_.clear();
1489 
1490   struct v4l2_requestbuffers reqbufs;
1491   memset(&reqbufs, 0, sizeof(reqbufs));
1492   reqbufs.count = 0;
1493   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1494   reqbufs.memory = V4L2_MEMORY_MMAP;
1495   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
1496 
1497   return true;
1498 }
1499 
AssignPictureBuffers(const std::vector<PictureBuffer> & buffers)1500 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers(
1501     const std::vector<PictureBuffer>& buffers) {
1502   DVLOGF(3);
1503   DCHECK(child_task_runner_->BelongsToCurrentThread());
1504 
1505   decoder_thread_task_runner_->PostTask(
1506       FROM_HERE,
1507       base::Bind(&V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask,
1508                  base::Unretained(this), buffers));
1509 }
1510 
AssignPictureBuffersTask(const std::vector<PictureBuffer> & buffers)1511 void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffersTask(
1512     const std::vector<PictureBuffer>& buffers) {
1513   DVLOGF(3);
1514   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1515   DCHECK_EQ(state_, kAwaitingPictureBuffers);
1516 
1517   const uint32_t req_buffer_count = decoder_->GetRequiredNumOfPictures();
1518 
1519   if (buffers.size() < req_buffer_count) {
1520     DLOG(ERROR) << "Failed to provide requested picture buffers. "
1521                 << "(Got " << buffers.size()
1522                 << ", requested " << req_buffer_count << ")";
1523     NOTIFY_ERROR(INVALID_ARGUMENT);
1524     return;
1525   }
1526 
1527   // Allocate the output buffers.
1528   struct v4l2_requestbuffers reqbufs;
1529   memset(&reqbufs, 0, sizeof(reqbufs));
1530   reqbufs.count = buffers.size();
1531   reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1532   reqbufs.memory =
1533       (output_mode_ == Config::OutputMode::ALLOCATE ? V4L2_MEMORY_MMAP
1534                                                     : V4L2_MEMORY_DMABUF);
1535   IOCTL_OR_ERROR_RETURN(VIDIOC_REQBUFS, &reqbufs);
1536 
1537   if (reqbufs.count != buffers.size()) {
1538     DLOGF(ERROR) << "Could not allocate enough output buffers";
1539     NOTIFY_ERROR(PLATFORM_FAILURE);
1540     return;
1541   }
1542 
1543   DCHECK(free_output_buffers_.empty());
1544   DCHECK(output_buffer_map_.empty());
1545   output_buffer_map_.resize(buffers.size());
1546   for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1547     DCHECK(buffers[i].size() == coded_size_);
1548 
1549     OutputRecord& output_record = output_buffer_map_[i];
1550     DCHECK(!output_record.at_device);
1551     DCHECK(!output_record.at_client);
1552     DCHECK_EQ(output_record.picture_id, -1);
1553     DCHECK(output_record.dmabuf_fds.empty());
1554     DCHECK_EQ(output_record.cleared, false);
1555 
1556     output_record.picture_id = buffers[i].id();
1557 
1558     // This will remain true until ImportBufferForPicture is called, either by
1559     // the client, or by ourselves, if we are allocating.
1560     output_record.at_client = true;
1561     if (output_mode_ == Config::OutputMode::ALLOCATE) {
1562       std::vector<base::ScopedFD> dmabuf_fds = device_->GetDmabufsForV4L2Buffer(
1563           i, output_planes_count_, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1564       if (dmabuf_fds.empty()) {
1565         NOTIFY_ERROR(PLATFORM_FAILURE);
1566         return;
1567       }
1568 
1569       auto passed_dmabuf_fds(base::WrapUnique(
1570           new std::vector<base::ScopedFD>(std::move(dmabuf_fds))));
1571       ImportBufferForPictureTask(output_record.picture_id,
1572                                  std::move(passed_dmabuf_fds));
1573     }  // else we'll get triggered via ImportBufferForPicture() from client.
1574     DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id;
1575   }
1576 
1577   if (!StartDevicePoll()) {
1578     NOTIFY_ERROR(PLATFORM_FAILURE);
1579     return;
1580   }
1581 
1582   // Put us in kIdle to allow further event processing.
1583   // ProcessPendingEventsIfNeeded() will put us back into kDecoding after all
1584   // other pending events are processed successfully.
1585   state_ = kIdle;
1586   ProcessPendingEventsIfNeeded();
1587 }
1588 
ImportBufferForPicture(int32_t picture_buffer_id,const std::vector<base::FileDescriptor> & dmabuf_fds)1589 void V4L2SliceVideoDecodeAccelerator::ImportBufferForPicture(
1590     int32_t picture_buffer_id,
1591     const std::vector<base::FileDescriptor>& dmabuf_fds) {
1592   DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
1593   DCHECK(child_task_runner_->BelongsToCurrentThread());
1594 
1595   auto passed_dmabuf_fds(base::WrapUnique(new std::vector<base::ScopedFD>()));
1596   for (const auto& fd : dmabuf_fds) {
1597     DCHECK_NE(fd.fd, -1);
1598     passed_dmabuf_fds->push_back(base::ScopedFD(fd.fd));
1599   }
1600 
1601   if (output_mode_ != Config::OutputMode::IMPORT) {
1602     LOGF(ERROR) << "Cannot import in non-import mode";
1603     NOTIFY_ERROR(INVALID_ARGUMENT);
1604     return;
1605   }
1606 
1607   decoder_thread_task_runner_->PostTask(
1608       FROM_HERE,
1609       base::Bind(&V4L2SliceVideoDecodeAccelerator::ImportBufferForPictureTask,
1610                  base::Unretained(this), picture_buffer_id,
1611                  base::Passed(&passed_dmabuf_fds)));
1612 }
1613 
ImportBufferForPictureTask(int32_t picture_buffer_id,std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds)1614 void V4L2SliceVideoDecodeAccelerator::ImportBufferForPictureTask(
1615     int32_t picture_buffer_id,
1616     std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds) {
1617   DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
1618   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1619 
1620   const auto iter =
1621       std::find_if(output_buffer_map_.begin(), output_buffer_map_.end(),
1622                    [picture_buffer_id](const OutputRecord& output_record) {
1623                      return output_record.picture_id == picture_buffer_id;
1624                    });
1625   if (iter == output_buffer_map_.end()) {
1626     // It's possible that we've already posted a DismissPictureBuffer for this
1627     // picture, but it has not yet executed when this ImportBufferForPicture was
1628     // posted to us by the client. In that case just ignore this (we've already
1629     // dismissed it and accounted for that).
1630     DVLOGF(3) << "got picture id=" << picture_buffer_id
1631               << " not in use (anymore?).";
1632     return;
1633   }
1634 
1635   if (!iter->at_client) {
1636     LOGF(ERROR) << "Cannot import buffer that not owned by client";
1637     NOTIFY_ERROR(INVALID_ARGUMENT);
1638     return;
1639   }
1640 
1641   size_t index = iter - output_buffer_map_.begin();
1642   DCHECK_EQ(std::count(free_output_buffers_.begin(), free_output_buffers_.end(),
1643                        index),
1644             0);
1645 
1646   DCHECK(!iter->at_device);
1647   iter->at_client = false;
1648 
1649   DCHECK_EQ(output_planes_count_, passed_dmabuf_fds->size());
1650   iter->dmabuf_fds.swap(*passed_dmabuf_fds);
1651   free_output_buffers_.push_back(index);
1652   ScheduleDecodeBufferTaskIfNeeded();
1653 }
1654 
ReusePictureBuffer(int32_t picture_buffer_id)1655 void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer(
1656     int32_t picture_buffer_id) {
1657   DCHECK(child_task_runner_->BelongsToCurrentThread());
1658   DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id;
1659 
1660   decoder_thread_task_runner_->PostTask(
1661       FROM_HERE,
1662       base::Bind(&V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask,
1663                  base::Unretained(this), picture_buffer_id));
1664 }
1665 
ReusePictureBufferTask(int32_t picture_buffer_id)1666 void V4L2SliceVideoDecodeAccelerator::ReusePictureBufferTask(
1667     int32_t picture_buffer_id) {
1668   DVLOGF(3) << "picture_buffer_id=" << picture_buffer_id;
1669   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1670 
1671   V4L2DecodeSurfaceByPictureBufferId::iterator it =
1672       surfaces_at_display_.find(picture_buffer_id);
1673   if (it == surfaces_at_display_.end()) {
1674     // It's possible that we've already posted a DismissPictureBuffer for this
1675     // picture, but it has not yet executed when this ReusePictureBuffer was
1676     // posted to us by the client. In that case just ignore this (we've already
1677     // dismissed it and accounted for that) and let the sync object get
1678     // destroyed.
1679     DVLOGF(3) << "got picture id=" << picture_buffer_id
1680               << " not in use (anymore?).";
1681     return;
1682   }
1683 
1684   OutputRecord& output_record = output_buffer_map_[it->second->output_record()];
1685   if (output_record.at_device || !output_record.at_client) {
1686     DVLOGF(1) << "picture_buffer_id not reusable";
1687     NOTIFY_ERROR(INVALID_ARGUMENT);
1688     return;
1689   }
1690 
1691   DCHECK(!output_record.at_device);
1692   output_record.at_client = false;
1693 
1694   surfaces_at_display_.erase(it);
1695 }
1696 
Flush()1697 void V4L2SliceVideoDecodeAccelerator::Flush() {
1698   DVLOGF(3);
1699   DCHECK(child_task_runner_->BelongsToCurrentThread());
1700 
1701   decoder_thread_task_runner_->PostTask(
1702       FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::FlushTask,
1703                             base::Unretained(this)));
1704 }
1705 
FlushTask()1706 void V4L2SliceVideoDecodeAccelerator::FlushTask() {
1707   DVLOGF(3);
1708   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1709 
1710   // Queue an empty buffer which - when reached - will trigger flush sequence.
1711   decoder_input_queue_.push(
1712       linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef(
1713           decode_client_, decode_task_runner_, nullptr, kFlushBufferId)));
1714 
1715   ScheduleDecodeBufferTaskIfNeeded();
1716 }
1717 
InitiateFlush()1718 void V4L2SliceVideoDecodeAccelerator::InitiateFlush() {
1719   DVLOGF(3);
1720   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1721 
1722   // This will trigger output for all remaining surfaces in the decoder.
1723   // However, not all of them may be decoded yet (they would be queued
1724   // in hardware then).
1725   if (!decoder_->Flush()) {
1726     DVLOGF(1) << "Failed flushing the decoder.";
1727     NOTIFY_ERROR(PLATFORM_FAILURE);
1728     return;
1729   }
1730 
1731   // Put the decoder in an idle state, ready to resume.
1732   decoder_->Reset();
1733 
1734   DCHECK(!decoder_flushing_);
1735   decoder_flushing_ = true;
1736   NewEventPending();
1737 }
1738 
FinishFlush()1739 bool V4L2SliceVideoDecodeAccelerator::FinishFlush() {
1740   DVLOGF(3);
1741   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1742 
1743   if (!decoder_flushing_)
1744     return true;
1745 
1746   if (!surfaces_at_device_.empty())
1747     return false;
1748 
1749   DCHECK_EQ(state_, kIdle);
1750 
1751   // At this point, all remaining surfaces are decoded and dequeued, and since
1752   // we have already scheduled output for them in InitiateFlush(), their
1753   // respective PictureReady calls have been posted (or they have been queued on
1754   // pending_picture_ready_). So at this time, once we SendPictureReady(),
1755   // we will have all remaining PictureReady() posted to the client and we
1756   // can post NotifyFlushDone().
1757   DCHECK(decoder_display_queue_.empty());
1758 
1759   // Decoder should have already returned all surfaces and all surfaces are
1760   // out of hardware. There can be no other owners of input buffers.
1761   DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size());
1762 
1763   SendPictureReady();
1764 
1765   decoder_flushing_ = false;
1766   DVLOGF(3) << "Flush finished";
1767 
1768   child_task_runner_->PostTask(FROM_HERE,
1769                                base::Bind(&Client::NotifyFlushDone, client_));
1770 
1771   return true;
1772 }
1773 
Reset()1774 void V4L2SliceVideoDecodeAccelerator::Reset() {
1775   DVLOGF(3);
1776   DCHECK(child_task_runner_->BelongsToCurrentThread());
1777 
1778   decoder_thread_task_runner_->PostTask(
1779       FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::ResetTask,
1780                             base::Unretained(this)));
1781 }
1782 
ResetTask()1783 void V4L2SliceVideoDecodeAccelerator::ResetTask() {
1784   DVLOGF(3);
1785   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1786 
1787   if (decoder_resetting_) {
1788     // This is a bug in the client, multiple Reset()s before NotifyResetDone()
1789     // are not allowed.
1790     NOTREACHED() << "Client should not be requesting multiple Reset()s";
1791     return;
1792   }
1793 
1794   // Put the decoder in an idle state, ready to resume.
1795   decoder_->Reset();
1796 
1797   // Drop all remaining inputs.
1798   decoder_current_bitstream_buffer_.reset();
1799   while (!decoder_input_queue_.empty())
1800     decoder_input_queue_.pop();
1801 
1802   decoder_resetting_ = true;
1803   NewEventPending();
1804 }
1805 
FinishReset()1806 bool V4L2SliceVideoDecodeAccelerator::FinishReset() {
1807   DVLOGF(3);
1808   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
1809 
1810   if (!decoder_resetting_)
1811     return true;
1812 
1813   if (!surfaces_at_device_.empty())
1814     return false;
1815 
1816   DCHECK_EQ(state_, kIdle);
1817   DCHECK(!decoder_flushing_);
1818   SendPictureReady();
1819 
1820   // Drop any pending outputs.
1821   while (!decoder_display_queue_.empty())
1822     decoder_display_queue_.pop();
1823 
1824   // At this point we can have no input buffers in the decoder, because we
1825   // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s
1826   // having been in kIdle since. We don't have any surfaces in the HW either -
1827   // we just checked that surfaces_at_device_.empty(), and inputs are tied
1828   // to surfaces. Since there can be no other owners of input buffers, we can
1829   // simply mark them all as available.
1830   DCHECK_EQ(input_buffer_queued_count_, 0);
1831   free_input_buffers_.clear();
1832   for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
1833     DCHECK(!input_buffer_map_[i].at_device);
1834     ReuseInputBuffer(i);
1835   }
1836 
1837   decoder_resetting_ = false;
1838   DVLOGF(3) << "Reset finished";
1839 
1840   child_task_runner_->PostTask(FROM_HERE,
1841                                base::Bind(&Client::NotifyResetDone, client_));
1842 
1843   return true;
1844 }
1845 
SetErrorState(Error error)1846 void V4L2SliceVideoDecodeAccelerator::SetErrorState(Error error) {
1847   // We can touch decoder_state_ only if this is the decoder thread or the
1848   // decoder thread isn't running.
1849   if (decoder_thread_.IsRunning() &&
1850       !decoder_thread_task_runner_->BelongsToCurrentThread()) {
1851     decoder_thread_task_runner_->PostTask(
1852         FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::SetErrorState,
1853                               base::Unretained(this), error));
1854     return;
1855   }
1856 
1857   // Post NotifyError only if we are already initialized, as the API does
1858   // not allow doing so before that.
1859   if (state_ != kError && state_ != kUninitialized)
1860     NotifyError(error);
1861 
1862   state_ = kError;
1863 }
1864 
V4L2H264Accelerator(V4L2SliceVideoDecodeAccelerator * v4l2_dec)1865 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::V4L2H264Accelerator(
1866     V4L2SliceVideoDecodeAccelerator* v4l2_dec)
1867     : num_slices_(0), v4l2_dec_(v4l2_dec) {
1868   DCHECK(v4l2_dec_);
1869 }
1870 
~V4L2H264Accelerator()1871 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::~V4L2H264Accelerator() {}
1872 
1873 scoped_refptr<H264Picture>
CreateH264Picture()1874 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::CreateH264Picture() {
1875   scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface();
1876   if (!dec_surface)
1877     return nullptr;
1878 
1879   return new V4L2H264Picture(dec_surface);
1880 }
1881 
1882 void V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::
H264PictureListToDPBIndicesList(const H264Picture::Vector & src_pic_list,uint8_t dst_list[kDPBIndicesListSize])1883     H264PictureListToDPBIndicesList(const H264Picture::Vector& src_pic_list,
1884                                     uint8_t dst_list[kDPBIndicesListSize]) {
1885   size_t i;
1886   for (i = 0; i < src_pic_list.size() && i < kDPBIndicesListSize; ++i) {
1887     const scoped_refptr<H264Picture>& pic = src_pic_list[i];
1888     dst_list[i] = pic ? pic->dpb_position : VIDEO_MAX_FRAME;
1889   }
1890 
1891   while (i < kDPBIndicesListSize)
1892     dst_list[i++] = VIDEO_MAX_FRAME;
1893 }
1894 
H264DPBToV4L2DPB(const H264DPB & dpb,std::vector<scoped_refptr<V4L2DecodeSurface>> * ref_surfaces)1895 void V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::H264DPBToV4L2DPB(
1896     const H264DPB& dpb,
1897     std::vector<scoped_refptr<V4L2DecodeSurface>>* ref_surfaces) {
1898   memset(v4l2_decode_param_.dpb, 0, sizeof(v4l2_decode_param_.dpb));
1899   size_t i = 0;
1900   for (const auto& pic : dpb) {
1901     if (i >= arraysize(v4l2_decode_param_.dpb)) {
1902       DVLOGF(1) << "Invalid DPB size";
1903       break;
1904     }
1905 
1906     int index = VIDEO_MAX_FRAME;
1907     if (!pic->nonexisting) {
1908       scoped_refptr<V4L2DecodeSurface> dec_surface =
1909           H264PictureToV4L2DecodeSurface(pic);
1910       index = dec_surface->output_record();
1911       ref_surfaces->push_back(dec_surface);
1912     }
1913 
1914     struct v4l2_h264_dpb_entry& entry = v4l2_decode_param_.dpb[i++];
1915     entry.buf_index = index;
1916     entry.frame_num = pic->frame_num;
1917     entry.pic_num = pic->pic_num;
1918     entry.top_field_order_cnt = pic->top_field_order_cnt;
1919     entry.bottom_field_order_cnt = pic->bottom_field_order_cnt;
1920     entry.flags = (pic->ref ? V4L2_H264_DPB_ENTRY_FLAG_ACTIVE : 0) |
1921                   (pic->long_term ? V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM : 0);
1922   }
1923 }
1924 
SubmitFrameMetadata(const H264SPS * sps,const H264PPS * pps,const H264DPB & dpb,const H264Picture::Vector & ref_pic_listp0,const H264Picture::Vector & ref_pic_listb0,const H264Picture::Vector & ref_pic_listb1,const scoped_refptr<H264Picture> & pic)1925 bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::SubmitFrameMetadata(
1926     const H264SPS* sps,
1927     const H264PPS* pps,
1928     const H264DPB& dpb,
1929     const H264Picture::Vector& ref_pic_listp0,
1930     const H264Picture::Vector& ref_pic_listb0,
1931     const H264Picture::Vector& ref_pic_listb1,
1932     const scoped_refptr<H264Picture>& pic) {
1933   struct v4l2_ext_control ctrl;
1934   std::vector<struct v4l2_ext_control> ctrls;
1935 
1936   struct v4l2_ctrl_h264_sps v4l2_sps;
1937   memset(&v4l2_sps, 0, sizeof(v4l2_sps));
1938   v4l2_sps.constraint_set_flags =
1939       (sps->constraint_set0_flag ? V4L2_H264_SPS_CONSTRAINT_SET0_FLAG : 0) |
1940       (sps->constraint_set1_flag ? V4L2_H264_SPS_CONSTRAINT_SET1_FLAG : 0) |
1941       (sps->constraint_set2_flag ? V4L2_H264_SPS_CONSTRAINT_SET2_FLAG : 0) |
1942       (sps->constraint_set3_flag ? V4L2_H264_SPS_CONSTRAINT_SET3_FLAG : 0) |
1943       (sps->constraint_set4_flag ? V4L2_H264_SPS_CONSTRAINT_SET4_FLAG : 0) |
1944       (sps->constraint_set5_flag ? V4L2_H264_SPS_CONSTRAINT_SET5_FLAG : 0);
1945 #define SPS_TO_V4L2SPS(a) v4l2_sps.a = sps->a
1946   SPS_TO_V4L2SPS(profile_idc);
1947   SPS_TO_V4L2SPS(level_idc);
1948   SPS_TO_V4L2SPS(seq_parameter_set_id);
1949   SPS_TO_V4L2SPS(chroma_format_idc);
1950   SPS_TO_V4L2SPS(bit_depth_luma_minus8);
1951   SPS_TO_V4L2SPS(bit_depth_chroma_minus8);
1952   SPS_TO_V4L2SPS(log2_max_frame_num_minus4);
1953   SPS_TO_V4L2SPS(pic_order_cnt_type);
1954   SPS_TO_V4L2SPS(log2_max_pic_order_cnt_lsb_minus4);
1955   SPS_TO_V4L2SPS(offset_for_non_ref_pic);
1956   SPS_TO_V4L2SPS(offset_for_top_to_bottom_field);
1957   SPS_TO_V4L2SPS(num_ref_frames_in_pic_order_cnt_cycle);
1958 
1959   static_assert(arraysize(v4l2_sps.offset_for_ref_frame) ==
1960                     arraysize(sps->offset_for_ref_frame),
1961                 "offset_for_ref_frame arrays must be same size");
1962   for (size_t i = 0; i < arraysize(v4l2_sps.offset_for_ref_frame); ++i)
1963     v4l2_sps.offset_for_ref_frame[i] = sps->offset_for_ref_frame[i];
1964   SPS_TO_V4L2SPS(max_num_ref_frames);
1965   SPS_TO_V4L2SPS(pic_width_in_mbs_minus1);
1966   SPS_TO_V4L2SPS(pic_height_in_map_units_minus1);
1967 #undef SPS_TO_V4L2SPS
1968 
1969 #define SET_V4L2_SPS_FLAG_IF(cond, flag) \
1970   v4l2_sps.flags |= ((sps->cond) ? (flag) : 0)
1971   SET_V4L2_SPS_FLAG_IF(separate_colour_plane_flag,
1972                        V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE);
1973   SET_V4L2_SPS_FLAG_IF(qpprime_y_zero_transform_bypass_flag,
1974                        V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS);
1975   SET_V4L2_SPS_FLAG_IF(delta_pic_order_always_zero_flag,
1976                        V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO);
1977   SET_V4L2_SPS_FLAG_IF(gaps_in_frame_num_value_allowed_flag,
1978                        V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED);
1979   SET_V4L2_SPS_FLAG_IF(frame_mbs_only_flag, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY);
1980   SET_V4L2_SPS_FLAG_IF(mb_adaptive_frame_field_flag,
1981                        V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD);
1982   SET_V4L2_SPS_FLAG_IF(direct_8x8_inference_flag,
1983                        V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE);
1984 #undef SET_V4L2_SPS_FLAG_IF
1985   memset(&ctrl, 0, sizeof(ctrl));
1986   ctrl.id = V4L2_CID_MPEG_VIDEO_H264_SPS;
1987   ctrl.size = sizeof(v4l2_sps);
1988   ctrl.p_h264_sps = &v4l2_sps;
1989   ctrls.push_back(ctrl);
1990 
1991   struct v4l2_ctrl_h264_pps v4l2_pps;
1992   memset(&v4l2_pps, 0, sizeof(v4l2_pps));
1993 #define PPS_TO_V4L2PPS(a) v4l2_pps.a = pps->a
1994   PPS_TO_V4L2PPS(pic_parameter_set_id);
1995   PPS_TO_V4L2PPS(seq_parameter_set_id);
1996   PPS_TO_V4L2PPS(num_slice_groups_minus1);
1997   PPS_TO_V4L2PPS(num_ref_idx_l0_default_active_minus1);
1998   PPS_TO_V4L2PPS(num_ref_idx_l1_default_active_minus1);
1999   PPS_TO_V4L2PPS(weighted_bipred_idc);
2000   PPS_TO_V4L2PPS(pic_init_qp_minus26);
2001   PPS_TO_V4L2PPS(pic_init_qs_minus26);
2002   PPS_TO_V4L2PPS(chroma_qp_index_offset);
2003   PPS_TO_V4L2PPS(second_chroma_qp_index_offset);
2004 #undef PPS_TO_V4L2PPS
2005 
2006 #define SET_V4L2_PPS_FLAG_IF(cond, flag) \
2007   v4l2_pps.flags |= ((pps->cond) ? (flag) : 0)
2008   SET_V4L2_PPS_FLAG_IF(entropy_coding_mode_flag,
2009                        V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE);
2010   SET_V4L2_PPS_FLAG_IF(
2011       bottom_field_pic_order_in_frame_present_flag,
2012       V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT);
2013   SET_V4L2_PPS_FLAG_IF(weighted_pred_flag, V4L2_H264_PPS_FLAG_WEIGHTED_PRED);
2014   SET_V4L2_PPS_FLAG_IF(deblocking_filter_control_present_flag,
2015                        V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT);
2016   SET_V4L2_PPS_FLAG_IF(constrained_intra_pred_flag,
2017                        V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED);
2018   SET_V4L2_PPS_FLAG_IF(redundant_pic_cnt_present_flag,
2019                        V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT);
2020   SET_V4L2_PPS_FLAG_IF(transform_8x8_mode_flag,
2021                        V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE);
2022   SET_V4L2_PPS_FLAG_IF(pic_scaling_matrix_present_flag,
2023                        V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT);
2024 #undef SET_V4L2_PPS_FLAG_IF
2025   memset(&ctrl, 0, sizeof(ctrl));
2026   ctrl.id = V4L2_CID_MPEG_VIDEO_H264_PPS;
2027   ctrl.size = sizeof(v4l2_pps);
2028   ctrl.p_h264_pps = &v4l2_pps;
2029   ctrls.push_back(ctrl);
2030 
2031   struct v4l2_ctrl_h264_scaling_matrix v4l2_scaling_matrix;
2032   memset(&v4l2_scaling_matrix, 0, sizeof(v4l2_scaling_matrix));
2033 
2034   static_assert(arraysize(v4l2_scaling_matrix.scaling_list_4x4) <=
2035                         arraysize(pps->scaling_list4x4) &&
2036                     arraysize(v4l2_scaling_matrix.scaling_list_4x4[0]) <=
2037                         arraysize(pps->scaling_list4x4[0]) &&
2038                     arraysize(v4l2_scaling_matrix.scaling_list_8x8) <=
2039                         arraysize(pps->scaling_list8x8) &&
2040                     arraysize(v4l2_scaling_matrix.scaling_list_8x8[0]) <=
2041                         arraysize(pps->scaling_list8x8[0]),
2042                 "scaling_lists must be of correct size");
2043   static_assert(arraysize(v4l2_scaling_matrix.scaling_list_4x4) <=
2044                         arraysize(sps->scaling_list4x4) &&
2045                     arraysize(v4l2_scaling_matrix.scaling_list_4x4[0]) <=
2046                         arraysize(sps->scaling_list4x4[0]) &&
2047                     arraysize(v4l2_scaling_matrix.scaling_list_8x8) <=
2048                         arraysize(sps->scaling_list8x8) &&
2049                     arraysize(v4l2_scaling_matrix.scaling_list_8x8[0]) <=
2050                         arraysize(sps->scaling_list8x8[0]),
2051                 "scaling_lists must be of correct size");
2052 
2053   const auto* scaling_list4x4 = &sps->scaling_list4x4[0];
2054   const auto* scaling_list8x8 = &sps->scaling_list8x8[0];
2055   if (pps->pic_scaling_matrix_present_flag) {
2056     scaling_list4x4 = &pps->scaling_list4x4[0];
2057     scaling_list8x8 = &pps->scaling_list8x8[0];
2058   }
2059 
2060   for (size_t i = 0; i < arraysize(v4l2_scaling_matrix.scaling_list_4x4); ++i) {
2061     for (size_t j = 0; j < arraysize(v4l2_scaling_matrix.scaling_list_4x4[i]);
2062          ++j) {
2063       v4l2_scaling_matrix.scaling_list_4x4[i][j] = scaling_list4x4[i][j];
2064     }
2065   }
2066   for (size_t i = 0; i < arraysize(v4l2_scaling_matrix.scaling_list_8x8); ++i) {
2067     for (size_t j = 0; j < arraysize(v4l2_scaling_matrix.scaling_list_8x8[i]);
2068          ++j) {
2069       v4l2_scaling_matrix.scaling_list_8x8[i][j] = scaling_list8x8[i][j];
2070     }
2071   }
2072 
2073   memset(&ctrl, 0, sizeof(ctrl));
2074   ctrl.id = V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX;
2075   ctrl.size = sizeof(v4l2_scaling_matrix);
2076   ctrl.p_h264_scal_mtrx = &v4l2_scaling_matrix;
2077   ctrls.push_back(ctrl);
2078 
2079   scoped_refptr<V4L2DecodeSurface> dec_surface =
2080       H264PictureToV4L2DecodeSurface(pic);
2081 
2082   struct v4l2_ext_controls ext_ctrls;
2083   memset(&ext_ctrls, 0, sizeof(ext_ctrls));
2084   ext_ctrls.count = ctrls.size();
2085   ext_ctrls.controls = &ctrls[0];
2086   ext_ctrls.config_store = dec_surface->config_store();
2087   v4l2_dec_->SubmitExtControls(&ext_ctrls);
2088 
2089   H264PictureListToDPBIndicesList(ref_pic_listp0,
2090                                   v4l2_decode_param_.ref_pic_list_p0);
2091   H264PictureListToDPBIndicesList(ref_pic_listb0,
2092                                   v4l2_decode_param_.ref_pic_list_b0);
2093   H264PictureListToDPBIndicesList(ref_pic_listb1,
2094                                   v4l2_decode_param_.ref_pic_list_b1);
2095 
2096   std::vector<scoped_refptr<V4L2DecodeSurface>> ref_surfaces;
2097   H264DPBToV4L2DPB(dpb, &ref_surfaces);
2098   dec_surface->SetReferenceSurfaces(ref_surfaces);
2099 
2100   return true;
2101 }
2102 
SubmitSlice(const H264PPS * pps,const H264SliceHeader * slice_hdr,const H264Picture::Vector & ref_pic_list0,const H264Picture::Vector & ref_pic_list1,const scoped_refptr<H264Picture> & pic,const uint8_t * data,size_t size)2103 bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::SubmitSlice(
2104     const H264PPS* pps,
2105     const H264SliceHeader* slice_hdr,
2106     const H264Picture::Vector& ref_pic_list0,
2107     const H264Picture::Vector& ref_pic_list1,
2108     const scoped_refptr<H264Picture>& pic,
2109     const uint8_t* data,
2110     size_t size) {
2111   if (num_slices_ == kMaxSlices) {
2112     LOGF(ERROR) << "Over limit of supported slices per frame";
2113     return false;
2114   }
2115 
2116   struct v4l2_ctrl_h264_slice_param& v4l2_slice_param =
2117       v4l2_slice_params_[num_slices_++];
2118   memset(&v4l2_slice_param, 0, sizeof(v4l2_slice_param));
2119 
2120   v4l2_slice_param.size = size;
2121 #define SHDR_TO_V4L2SPARM(a) v4l2_slice_param.a = slice_hdr->a
2122   SHDR_TO_V4L2SPARM(header_bit_size);
2123   SHDR_TO_V4L2SPARM(first_mb_in_slice);
2124   SHDR_TO_V4L2SPARM(slice_type);
2125   SHDR_TO_V4L2SPARM(pic_parameter_set_id);
2126   SHDR_TO_V4L2SPARM(colour_plane_id);
2127   SHDR_TO_V4L2SPARM(frame_num);
2128   SHDR_TO_V4L2SPARM(idr_pic_id);
2129   SHDR_TO_V4L2SPARM(pic_order_cnt_lsb);
2130   SHDR_TO_V4L2SPARM(delta_pic_order_cnt_bottom);
2131   SHDR_TO_V4L2SPARM(delta_pic_order_cnt0);
2132   SHDR_TO_V4L2SPARM(delta_pic_order_cnt1);
2133   SHDR_TO_V4L2SPARM(redundant_pic_cnt);
2134   SHDR_TO_V4L2SPARM(dec_ref_pic_marking_bit_size);
2135   SHDR_TO_V4L2SPARM(cabac_init_idc);
2136   SHDR_TO_V4L2SPARM(slice_qp_delta);
2137   SHDR_TO_V4L2SPARM(slice_qs_delta);
2138   SHDR_TO_V4L2SPARM(disable_deblocking_filter_idc);
2139   SHDR_TO_V4L2SPARM(slice_alpha_c0_offset_div2);
2140   SHDR_TO_V4L2SPARM(slice_beta_offset_div2);
2141   SHDR_TO_V4L2SPARM(num_ref_idx_l0_active_minus1);
2142   SHDR_TO_V4L2SPARM(num_ref_idx_l1_active_minus1);
2143   SHDR_TO_V4L2SPARM(pic_order_cnt_bit_size);
2144 #undef SHDR_TO_V4L2SPARM
2145 
2146 #define SET_V4L2_SPARM_FLAG_IF(cond, flag) \
2147   v4l2_slice_param.flags |= ((slice_hdr->cond) ? (flag) : 0)
2148   SET_V4L2_SPARM_FLAG_IF(field_pic_flag, V4L2_SLICE_FLAG_FIELD_PIC);
2149   SET_V4L2_SPARM_FLAG_IF(bottom_field_flag, V4L2_SLICE_FLAG_BOTTOM_FIELD);
2150   SET_V4L2_SPARM_FLAG_IF(direct_spatial_mv_pred_flag,
2151                          V4L2_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED);
2152   SET_V4L2_SPARM_FLAG_IF(sp_for_switch_flag, V4L2_SLICE_FLAG_SP_FOR_SWITCH);
2153 #undef SET_V4L2_SPARM_FLAG_IF
2154 
2155   struct v4l2_h264_pred_weight_table* pred_weight_table =
2156       &v4l2_slice_param.pred_weight_table;
2157 
2158   if (((slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) &&
2159        pps->weighted_pred_flag) ||
2160       (slice_hdr->IsBSlice() && pps->weighted_bipred_idc == 1)) {
2161     pred_weight_table->luma_log2_weight_denom =
2162         slice_hdr->luma_log2_weight_denom;
2163     pred_weight_table->chroma_log2_weight_denom =
2164         slice_hdr->chroma_log2_weight_denom;
2165 
2166     struct v4l2_h264_weight_factors* factorsl0 =
2167         &pred_weight_table->weight_factors[0];
2168 
2169     for (int i = 0; i < 32; ++i) {
2170       factorsl0->luma_weight[i] =
2171           slice_hdr->pred_weight_table_l0.luma_weight[i];
2172       factorsl0->luma_offset[i] =
2173           slice_hdr->pred_weight_table_l0.luma_offset[i];
2174 
2175       for (int j = 0; j < 2; ++j) {
2176         factorsl0->chroma_weight[i][j] =
2177             slice_hdr->pred_weight_table_l0.chroma_weight[i][j];
2178         factorsl0->chroma_offset[i][j] =
2179             slice_hdr->pred_weight_table_l0.chroma_offset[i][j];
2180       }
2181     }
2182 
2183     if (slice_hdr->IsBSlice()) {
2184       struct v4l2_h264_weight_factors* factorsl1 =
2185           &pred_weight_table->weight_factors[1];
2186 
2187       for (int i = 0; i < 32; ++i) {
2188         factorsl1->luma_weight[i] =
2189             slice_hdr->pred_weight_table_l1.luma_weight[i];
2190         factorsl1->luma_offset[i] =
2191             slice_hdr->pred_weight_table_l1.luma_offset[i];
2192 
2193         for (int j = 0; j < 2; ++j) {
2194           factorsl1->chroma_weight[i][j] =
2195               slice_hdr->pred_weight_table_l1.chroma_weight[i][j];
2196           factorsl1->chroma_offset[i][j] =
2197               slice_hdr->pred_weight_table_l1.chroma_offset[i][j];
2198         }
2199       }
2200     }
2201   }
2202 
2203   H264PictureListToDPBIndicesList(ref_pic_list0,
2204                                   v4l2_slice_param.ref_pic_list0);
2205   H264PictureListToDPBIndicesList(ref_pic_list1,
2206                                   v4l2_slice_param.ref_pic_list1);
2207 
2208   scoped_refptr<V4L2DecodeSurface> dec_surface =
2209       H264PictureToV4L2DecodeSurface(pic);
2210 
2211   v4l2_decode_param_.nal_ref_idc = slice_hdr->nal_ref_idc;
2212 
2213   // TODO(posciak): Don't add start code back here, but have it passed from
2214   // the parser.
2215   size_t data_copy_size = size + 3;
2216   std::unique_ptr<uint8_t[]> data_copy(new uint8_t[data_copy_size]);
2217   memset(data_copy.get(), 0, data_copy_size);
2218   data_copy[2] = 0x01;
2219   memcpy(data_copy.get() + 3, data, size);
2220   return v4l2_dec_->SubmitSlice(dec_surface->input_record(), data_copy.get(),
2221                                 data_copy_size);
2222 }
2223 
SubmitSlice(int index,const uint8_t * data,size_t size)2224 bool V4L2SliceVideoDecodeAccelerator::SubmitSlice(int index,
2225                                                   const uint8_t* data,
2226                                                   size_t size) {
2227   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2228 
2229   InputRecord& input_record = input_buffer_map_[index];
2230 
2231   if (input_record.bytes_used + size > input_record.length) {
2232     DVLOGF(1) << "Input buffer too small";
2233     return false;
2234   }
2235 
2236   memcpy(static_cast<uint8_t*>(input_record.address) + input_record.bytes_used,
2237          data, size);
2238   input_record.bytes_used += size;
2239 
2240   return true;
2241 }
2242 
SubmitExtControls(struct v4l2_ext_controls * ext_ctrls)2243 bool V4L2SliceVideoDecodeAccelerator::SubmitExtControls(
2244     struct v4l2_ext_controls* ext_ctrls) {
2245   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2246   DCHECK_GT(ext_ctrls->config_store, 0u);
2247   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_EXT_CTRLS, ext_ctrls);
2248   return true;
2249 }
2250 
GetExtControls(struct v4l2_ext_controls * ext_ctrls)2251 bool V4L2SliceVideoDecodeAccelerator::GetExtControls(
2252     struct v4l2_ext_controls* ext_ctrls) {
2253   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2254   DCHECK_GT(ext_ctrls->config_store, 0u);
2255   IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_EXT_CTRLS, ext_ctrls);
2256   return true;
2257 }
2258 
IsCtrlExposed(uint32_t ctrl_id)2259 bool V4L2SliceVideoDecodeAccelerator::IsCtrlExposed(uint32_t ctrl_id) {
2260   struct v4l2_queryctrl query_ctrl;
2261   memset(&query_ctrl, 0, sizeof(query_ctrl));
2262   query_ctrl.id = ctrl_id;
2263 
2264   return (device_->Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) == 0);
2265 }
2266 
SubmitDecode(const scoped_refptr<H264Picture> & pic)2267 bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::SubmitDecode(
2268     const scoped_refptr<H264Picture>& pic) {
2269   scoped_refptr<V4L2DecodeSurface> dec_surface =
2270       H264PictureToV4L2DecodeSurface(pic);
2271 
2272   v4l2_decode_param_.num_slices = num_slices_;
2273   v4l2_decode_param_.idr_pic_flag = pic->idr;
2274   v4l2_decode_param_.top_field_order_cnt = pic->top_field_order_cnt;
2275   v4l2_decode_param_.bottom_field_order_cnt = pic->bottom_field_order_cnt;
2276 
2277   struct v4l2_ext_control ctrl;
2278   std::vector<struct v4l2_ext_control> ctrls;
2279 
2280   memset(&ctrl, 0, sizeof(ctrl));
2281   ctrl.id = V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAM;
2282   ctrl.size = sizeof(v4l2_slice_params_);
2283   ctrl.p_h264_slice_param = v4l2_slice_params_;
2284   ctrls.push_back(ctrl);
2285 
2286   memset(&ctrl, 0, sizeof(ctrl));
2287   ctrl.id = V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAM;
2288   ctrl.size = sizeof(v4l2_decode_param_);
2289   ctrl.p_h264_decode_param = &v4l2_decode_param_;
2290   ctrls.push_back(ctrl);
2291 
2292   struct v4l2_ext_controls ext_ctrls;
2293   memset(&ext_ctrls, 0, sizeof(ext_ctrls));
2294   ext_ctrls.count = ctrls.size();
2295   ext_ctrls.controls = &ctrls[0];
2296   ext_ctrls.config_store = dec_surface->config_store();
2297   if (!v4l2_dec_->SubmitExtControls(&ext_ctrls))
2298     return false;
2299 
2300   Reset();
2301 
2302   v4l2_dec_->DecodeSurface(dec_surface);
2303   return true;
2304 }
2305 
OutputPicture(const scoped_refptr<H264Picture> & pic)2306 bool V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::OutputPicture(
2307     const scoped_refptr<H264Picture>& pic) {
2308   scoped_refptr<V4L2DecodeSurface> dec_surface =
2309       H264PictureToV4L2DecodeSurface(pic);
2310   v4l2_dec_->SurfaceReady(dec_surface);
2311   return true;
2312 }
2313 
Reset()2314 void V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::Reset() {
2315   num_slices_ = 0;
2316   memset(&v4l2_decode_param_, 0, sizeof(v4l2_decode_param_));
2317   memset(&v4l2_slice_params_, 0, sizeof(v4l2_slice_params_));
2318 }
2319 
2320 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
2321 V4L2SliceVideoDecodeAccelerator::V4L2H264Accelerator::
H264PictureToV4L2DecodeSurface(const scoped_refptr<H264Picture> & pic)2322     H264PictureToV4L2DecodeSurface(const scoped_refptr<H264Picture>& pic) {
2323   V4L2H264Picture* v4l2_pic = pic->AsV4L2H264Picture();
2324   CHECK(v4l2_pic);
2325   return v4l2_pic->dec_surface();
2326 }
2327 
V4L2VP8Accelerator(V4L2SliceVideoDecodeAccelerator * v4l2_dec)2328 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::V4L2VP8Accelerator(
2329     V4L2SliceVideoDecodeAccelerator* v4l2_dec)
2330     : v4l2_dec_(v4l2_dec) {
2331   DCHECK(v4l2_dec_);
2332 }
2333 
~V4L2VP8Accelerator()2334 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::~V4L2VP8Accelerator() {}
2335 
2336 scoped_refptr<VP8Picture>
CreateVP8Picture()2337 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::CreateVP8Picture() {
2338   scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface();
2339   if (!dec_surface)
2340     return nullptr;
2341 
2342   return new V4L2VP8Picture(dec_surface);
2343 }
2344 
2345 #define ARRAY_MEMCPY_CHECKED(to, from)                               \
2346   do {                                                               \
2347     static_assert(sizeof(to) == sizeof(from),                        \
2348                   #from " and " #to " arrays must be of same size"); \
2349     memcpy(to, from, sizeof(to));                                    \
2350   } while (0)
2351 
FillV4L2SegmentationHeader(const Vp8SegmentationHeader & vp8_sgmnt_hdr,struct v4l2_vp8_sgmnt_hdr * v4l2_sgmnt_hdr)2352 static void FillV4L2SegmentationHeader(
2353     const Vp8SegmentationHeader& vp8_sgmnt_hdr,
2354     struct v4l2_vp8_sgmnt_hdr* v4l2_sgmnt_hdr) {
2355 #define SET_V4L2_SGMNT_HDR_FLAG_IF(cond, flag) \
2356   v4l2_sgmnt_hdr->flags |= ((vp8_sgmnt_hdr.cond) ? (flag) : 0)
2357   SET_V4L2_SGMNT_HDR_FLAG_IF(segmentation_enabled,
2358                              V4L2_VP8_SEGMNT_HDR_FLAG_ENABLED);
2359   SET_V4L2_SGMNT_HDR_FLAG_IF(update_mb_segmentation_map,
2360                              V4L2_VP8_SEGMNT_HDR_FLAG_UPDATE_MAP);
2361   SET_V4L2_SGMNT_HDR_FLAG_IF(update_segment_feature_data,
2362                              V4L2_VP8_SEGMNT_HDR_FLAG_UPDATE_FEATURE_DATA);
2363 #undef SET_V4L2_SPARM_FLAG_IF
2364   v4l2_sgmnt_hdr->segment_feature_mode = vp8_sgmnt_hdr.segment_feature_mode;
2365 
2366   ARRAY_MEMCPY_CHECKED(v4l2_sgmnt_hdr->quant_update,
2367                        vp8_sgmnt_hdr.quantizer_update_value);
2368   ARRAY_MEMCPY_CHECKED(v4l2_sgmnt_hdr->lf_update,
2369                        vp8_sgmnt_hdr.lf_update_value);
2370   ARRAY_MEMCPY_CHECKED(v4l2_sgmnt_hdr->segment_probs,
2371                        vp8_sgmnt_hdr.segment_prob);
2372 }
2373 
FillV4L2LoopfilterHeader(const Vp8LoopFilterHeader & vp8_loopfilter_hdr,struct v4l2_vp8_loopfilter_hdr * v4l2_lf_hdr)2374 static void FillV4L2LoopfilterHeader(
2375     const Vp8LoopFilterHeader& vp8_loopfilter_hdr,
2376     struct v4l2_vp8_loopfilter_hdr* v4l2_lf_hdr) {
2377 #define SET_V4L2_LF_HDR_FLAG_IF(cond, flag) \
2378   v4l2_lf_hdr->flags |= ((vp8_loopfilter_hdr.cond) ? (flag) : 0)
2379   SET_V4L2_LF_HDR_FLAG_IF(loop_filter_adj_enable, V4L2_VP8_LF_HDR_ADJ_ENABLE);
2380   SET_V4L2_LF_HDR_FLAG_IF(mode_ref_lf_delta_update,
2381                           V4L2_VP8_LF_HDR_DELTA_UPDATE);
2382 #undef SET_V4L2_SGMNT_HDR_FLAG_IF
2383 
2384 #define LF_HDR_TO_V4L2_LF_HDR(a) v4l2_lf_hdr->a = vp8_loopfilter_hdr.a;
2385   LF_HDR_TO_V4L2_LF_HDR(type);
2386   LF_HDR_TO_V4L2_LF_HDR(level);
2387   LF_HDR_TO_V4L2_LF_HDR(sharpness_level);
2388 #undef LF_HDR_TO_V4L2_LF_HDR
2389 
2390   ARRAY_MEMCPY_CHECKED(v4l2_lf_hdr->ref_frm_delta_magnitude,
2391                        vp8_loopfilter_hdr.ref_frame_delta);
2392   ARRAY_MEMCPY_CHECKED(v4l2_lf_hdr->mb_mode_delta_magnitude,
2393                        vp8_loopfilter_hdr.mb_mode_delta);
2394 }
2395 
FillV4L2QuantizationHeader(const Vp8QuantizationHeader & vp8_quant_hdr,struct v4l2_vp8_quantization_hdr * v4l2_quant_hdr)2396 static void FillV4L2QuantizationHeader(
2397     const Vp8QuantizationHeader& vp8_quant_hdr,
2398     struct v4l2_vp8_quantization_hdr* v4l2_quant_hdr) {
2399   v4l2_quant_hdr->y_ac_qi = vp8_quant_hdr.y_ac_qi;
2400   v4l2_quant_hdr->y_dc_delta = vp8_quant_hdr.y_dc_delta;
2401   v4l2_quant_hdr->y2_dc_delta = vp8_quant_hdr.y2_dc_delta;
2402   v4l2_quant_hdr->y2_ac_delta = vp8_quant_hdr.y2_ac_delta;
2403   v4l2_quant_hdr->uv_dc_delta = vp8_quant_hdr.uv_dc_delta;
2404   v4l2_quant_hdr->uv_ac_delta = vp8_quant_hdr.uv_ac_delta;
2405 }
2406 
FillV4L2Vp8EntropyHeader(const Vp8EntropyHeader & vp8_entropy_hdr,struct v4l2_vp8_entropy_hdr * v4l2_entropy_hdr)2407 static void FillV4L2Vp8EntropyHeader(
2408     const Vp8EntropyHeader& vp8_entropy_hdr,
2409     struct v4l2_vp8_entropy_hdr* v4l2_entropy_hdr) {
2410   ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->coeff_probs,
2411                        vp8_entropy_hdr.coeff_probs);
2412   ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->y_mode_probs,
2413                        vp8_entropy_hdr.y_mode_probs);
2414   ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->uv_mode_probs,
2415                        vp8_entropy_hdr.uv_mode_probs);
2416   ARRAY_MEMCPY_CHECKED(v4l2_entropy_hdr->mv_probs, vp8_entropy_hdr.mv_probs);
2417 }
2418 
SubmitDecode(const scoped_refptr<VP8Picture> & pic,const Vp8FrameHeader * frame_hdr,const scoped_refptr<VP8Picture> & last_frame,const scoped_refptr<VP8Picture> & golden_frame,const scoped_refptr<VP8Picture> & alt_frame)2419 bool V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::SubmitDecode(
2420     const scoped_refptr<VP8Picture>& pic,
2421     const Vp8FrameHeader* frame_hdr,
2422     const scoped_refptr<VP8Picture>& last_frame,
2423     const scoped_refptr<VP8Picture>& golden_frame,
2424     const scoped_refptr<VP8Picture>& alt_frame) {
2425   struct v4l2_ctrl_vp8_frame_hdr v4l2_frame_hdr;
2426   memset(&v4l2_frame_hdr, 0, sizeof(v4l2_frame_hdr));
2427 
2428 #define FHDR_TO_V4L2_FHDR(a) v4l2_frame_hdr.a = frame_hdr->a
2429   FHDR_TO_V4L2_FHDR(key_frame);
2430   FHDR_TO_V4L2_FHDR(version);
2431   FHDR_TO_V4L2_FHDR(width);
2432   FHDR_TO_V4L2_FHDR(horizontal_scale);
2433   FHDR_TO_V4L2_FHDR(height);
2434   FHDR_TO_V4L2_FHDR(vertical_scale);
2435   FHDR_TO_V4L2_FHDR(sign_bias_golden);
2436   FHDR_TO_V4L2_FHDR(sign_bias_alternate);
2437   FHDR_TO_V4L2_FHDR(prob_skip_false);
2438   FHDR_TO_V4L2_FHDR(prob_intra);
2439   FHDR_TO_V4L2_FHDR(prob_last);
2440   FHDR_TO_V4L2_FHDR(prob_gf);
2441   FHDR_TO_V4L2_FHDR(bool_dec_range);
2442   FHDR_TO_V4L2_FHDR(bool_dec_value);
2443   FHDR_TO_V4L2_FHDR(bool_dec_count);
2444 #undef FHDR_TO_V4L2_FHDR
2445 
2446 #define SET_V4L2_FRM_HDR_FLAG_IF(cond, flag) \
2447   v4l2_frame_hdr.flags |= ((frame_hdr->cond) ? (flag) : 0)
2448   SET_V4L2_FRM_HDR_FLAG_IF(is_experimental,
2449                            V4L2_VP8_FRAME_HDR_FLAG_EXPERIMENTAL);
2450   SET_V4L2_FRM_HDR_FLAG_IF(show_frame, V4L2_VP8_FRAME_HDR_FLAG_SHOW_FRAME);
2451   SET_V4L2_FRM_HDR_FLAG_IF(mb_no_skip_coeff,
2452                            V4L2_VP8_FRAME_HDR_FLAG_MB_NO_SKIP_COEFF);
2453 #undef SET_V4L2_FRM_HDR_FLAG_IF
2454 
2455   FillV4L2SegmentationHeader(frame_hdr->segmentation_hdr,
2456                              &v4l2_frame_hdr.sgmnt_hdr);
2457 
2458   FillV4L2LoopfilterHeader(frame_hdr->loopfilter_hdr, &v4l2_frame_hdr.lf_hdr);
2459 
2460   FillV4L2QuantizationHeader(frame_hdr->quantization_hdr,
2461                              &v4l2_frame_hdr.quant_hdr);
2462 
2463   FillV4L2Vp8EntropyHeader(frame_hdr->entropy_hdr, &v4l2_frame_hdr.entropy_hdr);
2464 
2465   v4l2_frame_hdr.first_part_size =
2466       base::checked_cast<__u32>(frame_hdr->first_part_size);
2467   v4l2_frame_hdr.first_part_offset =
2468       base::checked_cast<__u32>(frame_hdr->first_part_offset);
2469   v4l2_frame_hdr.macroblock_bit_offset =
2470       base::checked_cast<__u32>(frame_hdr->macroblock_bit_offset);
2471   v4l2_frame_hdr.num_dct_parts = frame_hdr->num_of_dct_partitions;
2472 
2473   static_assert(arraysize(v4l2_frame_hdr.dct_part_sizes) ==
2474                     arraysize(frame_hdr->dct_partition_sizes),
2475                 "DCT partition size arrays must have equal number of elements");
2476   for (size_t i = 0; i < frame_hdr->num_of_dct_partitions &&
2477                      i < arraysize(v4l2_frame_hdr.dct_part_sizes);
2478        ++i)
2479     v4l2_frame_hdr.dct_part_sizes[i] = frame_hdr->dct_partition_sizes[i];
2480 
2481   scoped_refptr<V4L2DecodeSurface> dec_surface =
2482       VP8PictureToV4L2DecodeSurface(pic);
2483   std::vector<scoped_refptr<V4L2DecodeSurface>> ref_surfaces;
2484 
2485   if (last_frame) {
2486     scoped_refptr<V4L2DecodeSurface> last_frame_surface =
2487         VP8PictureToV4L2DecodeSurface(last_frame);
2488     v4l2_frame_hdr.last_frame = last_frame_surface->output_record();
2489     ref_surfaces.push_back(last_frame_surface);
2490   } else {
2491     v4l2_frame_hdr.last_frame = VIDEO_MAX_FRAME;
2492   }
2493 
2494   if (golden_frame) {
2495     scoped_refptr<V4L2DecodeSurface> golden_frame_surface =
2496         VP8PictureToV4L2DecodeSurface(golden_frame);
2497     v4l2_frame_hdr.golden_frame = golden_frame_surface->output_record();
2498     ref_surfaces.push_back(golden_frame_surface);
2499   } else {
2500     v4l2_frame_hdr.golden_frame = VIDEO_MAX_FRAME;
2501   }
2502 
2503   if (alt_frame) {
2504     scoped_refptr<V4L2DecodeSurface> alt_frame_surface =
2505         VP8PictureToV4L2DecodeSurface(alt_frame);
2506     v4l2_frame_hdr.alt_frame = alt_frame_surface->output_record();
2507     ref_surfaces.push_back(alt_frame_surface);
2508   } else {
2509     v4l2_frame_hdr.alt_frame = VIDEO_MAX_FRAME;
2510   }
2511 
2512   struct v4l2_ext_control ctrl;
2513   memset(&ctrl, 0, sizeof(ctrl));
2514   ctrl.id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HDR;
2515   ctrl.size = sizeof(v4l2_frame_hdr);
2516   ctrl.p_vp8_frame_hdr = &v4l2_frame_hdr;
2517 
2518   struct v4l2_ext_controls ext_ctrls;
2519   memset(&ext_ctrls, 0, sizeof(ext_ctrls));
2520   ext_ctrls.count = 1;
2521   ext_ctrls.controls = &ctrl;
2522   ext_ctrls.config_store = dec_surface->config_store();
2523 
2524   if (!v4l2_dec_->SubmitExtControls(&ext_ctrls))
2525     return false;
2526 
2527   dec_surface->SetReferenceSurfaces(ref_surfaces);
2528 
2529   if (!v4l2_dec_->SubmitSlice(dec_surface->input_record(), frame_hdr->data,
2530                               frame_hdr->frame_size))
2531     return false;
2532 
2533   v4l2_dec_->DecodeSurface(dec_surface);
2534   return true;
2535 }
2536 
OutputPicture(const scoped_refptr<VP8Picture> & pic)2537 bool V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::OutputPicture(
2538     const scoped_refptr<VP8Picture>& pic) {
2539   scoped_refptr<V4L2DecodeSurface> dec_surface =
2540       VP8PictureToV4L2DecodeSurface(pic);
2541 
2542   v4l2_dec_->SurfaceReady(dec_surface);
2543   return true;
2544 }
2545 
2546 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
2547 V4L2SliceVideoDecodeAccelerator::V4L2VP8Accelerator::
VP8PictureToV4L2DecodeSurface(const scoped_refptr<VP8Picture> & pic)2548     VP8PictureToV4L2DecodeSurface(const scoped_refptr<VP8Picture>& pic) {
2549   V4L2VP8Picture* v4l2_pic = pic->AsV4L2VP8Picture();
2550   CHECK(v4l2_pic);
2551   return v4l2_pic->dec_surface();
2552 }
2553 
V4L2VP9Accelerator(V4L2SliceVideoDecodeAccelerator * v4l2_dec)2554 V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::V4L2VP9Accelerator(
2555     V4L2SliceVideoDecodeAccelerator* v4l2_dec)
2556     : v4l2_dec_(v4l2_dec) {
2557   DCHECK(v4l2_dec_);
2558 
2559   device_needs_frame_context_ =
2560       v4l2_dec_->IsCtrlExposed(V4L2_CID_MPEG_VIDEO_VP9_ENTROPY);
2561   DVLOG_IF(1, device_needs_frame_context_)
2562       << "Device requires frame context parsing";
2563 }
2564 
~V4L2VP9Accelerator()2565 V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::~V4L2VP9Accelerator() {}
2566 
2567 scoped_refptr<VP9Picture>
CreateVP9Picture()2568 V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::CreateVP9Picture() {
2569   scoped_refptr<V4L2DecodeSurface> dec_surface = v4l2_dec_->CreateSurface();
2570   if (!dec_surface)
2571     return nullptr;
2572 
2573   return new V4L2VP9Picture(dec_surface);
2574 }
2575 
FillV4L2VP9LoopFilterParams(const Vp9LoopFilterParams & vp9_lf_params,struct v4l2_vp9_loop_filter_params * v4l2_lf_params)2576 static void FillV4L2VP9LoopFilterParams(
2577     const Vp9LoopFilterParams& vp9_lf_params,
2578     struct v4l2_vp9_loop_filter_params* v4l2_lf_params) {
2579 #define SET_LF_PARAMS_FLAG_IF(cond, flag) \
2580   v4l2_lf_params->flags |= ((vp9_lf_params.cond) ? (flag) : 0)
2581   SET_LF_PARAMS_FLAG_IF(delta_enabled, V4L2_VP9_LOOP_FLTR_FLAG_DELTA_ENABLED);
2582   SET_LF_PARAMS_FLAG_IF(delta_update, V4L2_VP9_LOOP_FLTR_FLAG_DELTA_UPDATE);
2583 #undef SET_LF_PARAMS_FLAG_IF
2584 
2585   v4l2_lf_params->level = vp9_lf_params.level;
2586   v4l2_lf_params->sharpness = vp9_lf_params.sharpness;
2587 
2588   ARRAY_MEMCPY_CHECKED(v4l2_lf_params->deltas, vp9_lf_params.ref_deltas);
2589   ARRAY_MEMCPY_CHECKED(v4l2_lf_params->mode_deltas, vp9_lf_params.mode_deltas);
2590   ARRAY_MEMCPY_CHECKED(v4l2_lf_params->lvl_lookup, vp9_lf_params.lvl);
2591 }
2592 
FillV4L2VP9QuantizationParams(const Vp9QuantizationParams & vp9_quant_params,struct v4l2_vp9_quantization_params * v4l2_q_params)2593 static void FillV4L2VP9QuantizationParams(
2594     const Vp9QuantizationParams& vp9_quant_params,
2595     struct v4l2_vp9_quantization_params* v4l2_q_params) {
2596 #define SET_Q_PARAMS_FLAG_IF(cond, flag) \
2597   v4l2_q_params->flags |= ((vp9_quant_params.cond) ? (flag) : 0)
2598   SET_Q_PARAMS_FLAG_IF(IsLossless(), V4L2_VP9_QUANT_PARAMS_FLAG_LOSSLESS);
2599 #undef SET_Q_PARAMS_FLAG_IF
2600 
2601 #define Q_PARAMS_TO_V4L2_Q_PARAMS(a) v4l2_q_params->a = vp9_quant_params.a
2602   Q_PARAMS_TO_V4L2_Q_PARAMS(base_q_idx);
2603   Q_PARAMS_TO_V4L2_Q_PARAMS(delta_q_y_dc);
2604   Q_PARAMS_TO_V4L2_Q_PARAMS(delta_q_uv_dc);
2605   Q_PARAMS_TO_V4L2_Q_PARAMS(delta_q_uv_ac);
2606 #undef Q_PARAMS_TO_V4L2_Q_PARAMS
2607 }
2608 
FillV4L2VP9SegmentationParams(const Vp9SegmentationParams & vp9_segm_params,struct v4l2_vp9_segmentation_params * v4l2_segm_params)2609 static void FillV4L2VP9SegmentationParams(
2610     const Vp9SegmentationParams& vp9_segm_params,
2611     struct v4l2_vp9_segmentation_params* v4l2_segm_params) {
2612 #define SET_SEG_PARAMS_FLAG_IF(cond, flag) \
2613   v4l2_segm_params->flags |= ((vp9_segm_params.cond) ? (flag) : 0)
2614   SET_SEG_PARAMS_FLAG_IF(enabled, V4L2_VP9_SGMNT_PARAM_FLAG_ENABLED);
2615   SET_SEG_PARAMS_FLAG_IF(update_map, V4L2_VP9_SGMNT_PARAM_FLAG_UPDATE_MAP);
2616   SET_SEG_PARAMS_FLAG_IF(temporal_update,
2617                          V4L2_VP9_SGMNT_PARAM_FLAG_TEMPORAL_UPDATE);
2618   SET_SEG_PARAMS_FLAG_IF(update_data, V4L2_VP9_SGMNT_PARAM_FLAG_UPDATE_DATA);
2619   SET_SEG_PARAMS_FLAG_IF(abs_or_delta_update,
2620                          V4L2_VP9_SGMNT_PARAM_FLAG_ABS_OR_DELTA_UPDATE);
2621 #undef SET_SEG_PARAMS_FLAG_IF
2622 
2623   ARRAY_MEMCPY_CHECKED(v4l2_segm_params->tree_probs,
2624                        vp9_segm_params.tree_probs);
2625   ARRAY_MEMCPY_CHECKED(v4l2_segm_params->pred_probs,
2626                        vp9_segm_params.pred_probs);
2627   ARRAY_MEMCPY_CHECKED(v4l2_segm_params->feature_data,
2628                        vp9_segm_params.feature_data);
2629 
2630   static_assert(arraysize(v4l2_segm_params->feature_enabled) ==
2631                         arraysize(vp9_segm_params.feature_enabled) &&
2632                     arraysize(v4l2_segm_params->feature_enabled[0]) ==
2633                         arraysize(vp9_segm_params.feature_enabled[0]),
2634                 "feature_enabled arrays must be of same size");
2635   for (size_t i = 0; i < arraysize(v4l2_segm_params->feature_enabled); ++i) {
2636     for (size_t j = 0; j < arraysize(v4l2_segm_params->feature_enabled[i]);
2637          ++j) {
2638       v4l2_segm_params->feature_enabled[i][j] =
2639           vp9_segm_params.feature_enabled[i][j];
2640     }
2641   }
2642 }
2643 
FillV4L2Vp9EntropyContext(const Vp9FrameContext & vp9_frame_ctx,struct v4l2_vp9_entropy_ctx * v4l2_entropy_ctx)2644 static void FillV4L2Vp9EntropyContext(
2645     const Vp9FrameContext& vp9_frame_ctx,
2646     struct v4l2_vp9_entropy_ctx* v4l2_entropy_ctx) {
2647 #define ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(a) \
2648   ARRAY_MEMCPY_CHECKED(v4l2_entropy_ctx->a, vp9_frame_ctx.a)
2649   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(tx_probs_8x8);
2650   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(tx_probs_16x16);
2651   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(tx_probs_32x32);
2652 
2653   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(coef_probs);
2654   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(skip_prob);
2655   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(inter_mode_probs);
2656   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(interp_filter_probs);
2657   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(is_inter_prob);
2658 
2659   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(comp_mode_prob);
2660   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(single_ref_prob);
2661   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(comp_ref_prob);
2662 
2663   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(y_mode_probs);
2664   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(uv_mode_probs);
2665 
2666   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(partition_probs);
2667 
2668   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_joint_probs);
2669   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_sign_prob);
2670   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class_probs);
2671   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class0_bit_prob);
2672   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_bits_prob);
2673   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class0_fr_probs);
2674   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_fr_probs);
2675   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_class0_hp_prob);
2676   ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR(mv_hp_prob);
2677 #undef ARRAY_MEMCPY_CHECKED_FRM_CTX_TO_V4L2_ENTR
2678 }
2679 
SubmitDecode(const scoped_refptr<VP9Picture> & pic,const Vp9SegmentationParams & segm_params,const Vp9LoopFilterParams & lf_params,const std::vector<scoped_refptr<VP9Picture>> & ref_pictures,const base::Closure & done_cb)2680 bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::SubmitDecode(
2681     const scoped_refptr<VP9Picture>& pic,
2682     const Vp9SegmentationParams& segm_params,
2683     const Vp9LoopFilterParams& lf_params,
2684     const std::vector<scoped_refptr<VP9Picture>>& ref_pictures,
2685     const base::Closure& done_cb) {
2686   const Vp9FrameHeader* frame_hdr = pic->frame_hdr.get();
2687   DCHECK(frame_hdr);
2688 
2689   struct v4l2_ctrl_vp9_frame_hdr v4l2_frame_hdr;
2690   memset(&v4l2_frame_hdr, 0, sizeof(v4l2_frame_hdr));
2691 
2692 #define FHDR_TO_V4L2_FHDR(a) v4l2_frame_hdr.a = frame_hdr->a
2693   FHDR_TO_V4L2_FHDR(profile);
2694   FHDR_TO_V4L2_FHDR(frame_type);
2695 
2696   FHDR_TO_V4L2_FHDR(bit_depth);
2697   FHDR_TO_V4L2_FHDR(color_range);
2698   FHDR_TO_V4L2_FHDR(subsampling_x);
2699   FHDR_TO_V4L2_FHDR(subsampling_y);
2700 
2701   FHDR_TO_V4L2_FHDR(frame_width);
2702   FHDR_TO_V4L2_FHDR(frame_height);
2703   FHDR_TO_V4L2_FHDR(render_width);
2704   FHDR_TO_V4L2_FHDR(render_height);
2705 
2706   FHDR_TO_V4L2_FHDR(reset_frame_context);
2707 
2708   FHDR_TO_V4L2_FHDR(interpolation_filter);
2709   FHDR_TO_V4L2_FHDR(frame_context_idx);
2710 
2711   FHDR_TO_V4L2_FHDR(tile_cols_log2);
2712   FHDR_TO_V4L2_FHDR(tile_rows_log2);
2713 
2714   FHDR_TO_V4L2_FHDR(header_size_in_bytes);
2715 #undef FHDR_TO_V4L2_FHDR
2716   v4l2_frame_hdr.color_space = static_cast<uint8_t>(frame_hdr->color_space);
2717 
2718   FillV4L2VP9QuantizationParams(frame_hdr->quant_params,
2719                                 &v4l2_frame_hdr.quant_params);
2720 
2721 #define SET_V4L2_FRM_HDR_FLAG_IF(cond, flag) \
2722   v4l2_frame_hdr.flags |= ((frame_hdr->cond) ? (flag) : 0)
2723   SET_V4L2_FRM_HDR_FLAG_IF(show_frame, V4L2_VP9_FRAME_HDR_FLAG_SHOW_FRAME);
2724   SET_V4L2_FRM_HDR_FLAG_IF(error_resilient_mode,
2725                            V4L2_VP9_FRAME_HDR_FLAG_ERR_RES);
2726   SET_V4L2_FRM_HDR_FLAG_IF(intra_only, V4L2_VP9_FRAME_HDR_FLAG_FRAME_INTRA);
2727   SET_V4L2_FRM_HDR_FLAG_IF(allow_high_precision_mv,
2728                            V4L2_VP9_FRAME_HDR_ALLOW_HIGH_PREC_MV);
2729   SET_V4L2_FRM_HDR_FLAG_IF(refresh_frame_context,
2730                            V4L2_VP9_FRAME_HDR_REFRESH_FRAME_CTX);
2731   SET_V4L2_FRM_HDR_FLAG_IF(frame_parallel_decoding_mode,
2732                            V4L2_VP9_FRAME_HDR_PARALLEL_DEC_MODE);
2733 #undef SET_V4L2_FRM_HDR_FLAG_IF
2734 
2735   FillV4L2VP9LoopFilterParams(lf_params, &v4l2_frame_hdr.lf_params);
2736   FillV4L2VP9SegmentationParams(segm_params, &v4l2_frame_hdr.sgmnt_params);
2737 
2738   std::vector<struct v4l2_ext_control> ctrls;
2739 
2740   struct v4l2_ext_control ctrl;
2741   memset(&ctrl, 0, sizeof(ctrl));
2742   ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_FRAME_HDR;
2743   ctrl.size = sizeof(v4l2_frame_hdr);
2744   ctrl.p_vp9_frame_hdr = &v4l2_frame_hdr;
2745   ctrls.push_back(ctrl);
2746 
2747   struct v4l2_ctrl_vp9_decode_param v4l2_decode_param;
2748   memset(&v4l2_decode_param, 0, sizeof(v4l2_decode_param));
2749   DCHECK_EQ(ref_pictures.size(), arraysize(v4l2_decode_param.ref_frames));
2750 
2751   std::vector<scoped_refptr<V4L2DecodeSurface>> ref_surfaces;
2752   for (size_t i = 0; i < ref_pictures.size(); ++i) {
2753     if (ref_pictures[i]) {
2754       scoped_refptr<V4L2DecodeSurface> ref_surface =
2755           VP9PictureToV4L2DecodeSurface(ref_pictures[i]);
2756 
2757       v4l2_decode_param.ref_frames[i] = ref_surface->output_record();
2758       ref_surfaces.push_back(ref_surface);
2759     } else {
2760       v4l2_decode_param.ref_frames[i] = VIDEO_MAX_FRAME;
2761     }
2762   }
2763 
2764   static_assert(arraysize(v4l2_decode_param.active_ref_frames) ==
2765                     arraysize(frame_hdr->ref_frame_idx),
2766                 "active reference frame array sizes mismatch");
2767 
2768   for (size_t i = 0; i < arraysize(frame_hdr->ref_frame_idx); ++i) {
2769     uint8_t idx = frame_hdr->ref_frame_idx[i];
2770     if (idx >= ref_pictures.size())
2771       return false;
2772 
2773     struct v4l2_vp9_reference_frame* v4l2_ref_frame =
2774         &v4l2_decode_param.active_ref_frames[i];
2775 
2776     scoped_refptr<VP9Picture> ref_pic = ref_pictures[idx];
2777     if (ref_pic) {
2778       scoped_refptr<V4L2DecodeSurface> ref_surface =
2779           VP9PictureToV4L2DecodeSurface(ref_pic);
2780       v4l2_ref_frame->buf_index = ref_surface->output_record();
2781 #define REF_TO_V4L2_REF(a) v4l2_ref_frame->a = ref_pic->frame_hdr->a
2782       REF_TO_V4L2_REF(frame_width);
2783       REF_TO_V4L2_REF(frame_height);
2784       REF_TO_V4L2_REF(bit_depth);
2785       REF_TO_V4L2_REF(subsampling_x);
2786       REF_TO_V4L2_REF(subsampling_y);
2787 #undef REF_TO_V4L2_REF
2788     } else {
2789       v4l2_ref_frame->buf_index = VIDEO_MAX_FRAME;
2790     }
2791   }
2792 
2793   memset(&ctrl, 0, sizeof(ctrl));
2794   ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_DECODE_PARAM;
2795   ctrl.size = sizeof(v4l2_decode_param);
2796   ctrl.p_vp9_decode_param = &v4l2_decode_param;
2797   ctrls.push_back(ctrl);
2798 
2799   // Defined outside of the if() clause below as it must remain valid until
2800   // the call to SubmitExtControls().
2801   struct v4l2_ctrl_vp9_entropy v4l2_entropy;
2802   if (device_needs_frame_context_) {
2803     memset(&v4l2_entropy, 0, sizeof(v4l2_entropy));
2804     FillV4L2Vp9EntropyContext(frame_hdr->initial_frame_context,
2805                               &v4l2_entropy.initial_entropy_ctx);
2806     FillV4L2Vp9EntropyContext(frame_hdr->frame_context,
2807                               &v4l2_entropy.current_entropy_ctx);
2808     v4l2_entropy.tx_mode = frame_hdr->compressed_header.tx_mode;
2809     v4l2_entropy.reference_mode = frame_hdr->compressed_header.reference_mode;
2810 
2811     memset(&ctrl, 0, sizeof(ctrl));
2812     ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_ENTROPY;
2813     ctrl.size = sizeof(v4l2_entropy);
2814     ctrl.p_vp9_entropy = &v4l2_entropy;
2815     ctrls.push_back(ctrl);
2816   }
2817 
2818   scoped_refptr<V4L2DecodeSurface> dec_surface =
2819       VP9PictureToV4L2DecodeSurface(pic);
2820 
2821   struct v4l2_ext_controls ext_ctrls;
2822   memset(&ext_ctrls, 0, sizeof(ext_ctrls));
2823   ext_ctrls.count = ctrls.size();
2824   ext_ctrls.controls = &ctrls[0];
2825   ext_ctrls.config_store = dec_surface->config_store();
2826   if (!v4l2_dec_->SubmitExtControls(&ext_ctrls))
2827     return false;
2828 
2829   dec_surface->SetReferenceSurfaces(ref_surfaces);
2830   dec_surface->SetDecodeDoneCallback(done_cb);
2831 
2832   if (!v4l2_dec_->SubmitSlice(dec_surface->input_record(), frame_hdr->data,
2833                               frame_hdr->frame_size))
2834     return false;
2835 
2836   v4l2_dec_->DecodeSurface(dec_surface);
2837   return true;
2838 }
2839 
OutputPicture(const scoped_refptr<VP9Picture> & pic)2840 bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::OutputPicture(
2841     const scoped_refptr<VP9Picture>& pic) {
2842   scoped_refptr<V4L2DecodeSurface> dec_surface =
2843       VP9PictureToV4L2DecodeSurface(pic);
2844 
2845   v4l2_dec_->SurfaceReady(dec_surface);
2846   return true;
2847 }
2848 
FillVp9FrameContext(struct v4l2_vp9_entropy_ctx & v4l2_entropy_ctx,Vp9FrameContext * vp9_frame_ctx)2849 static void FillVp9FrameContext(struct v4l2_vp9_entropy_ctx& v4l2_entropy_ctx,
2850                                 Vp9FrameContext* vp9_frame_ctx) {
2851 #define ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(a) \
2852   ARRAY_MEMCPY_CHECKED(vp9_frame_ctx->a, v4l2_entropy_ctx.a)
2853   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_8x8);
2854   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_16x16);
2855   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(tx_probs_32x32);
2856 
2857   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(coef_probs);
2858   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(skip_prob);
2859   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(inter_mode_probs);
2860   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(interp_filter_probs);
2861   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(is_inter_prob);
2862 
2863   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(comp_mode_prob);
2864   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(single_ref_prob);
2865   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(comp_ref_prob);
2866 
2867   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(y_mode_probs);
2868   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(uv_mode_probs);
2869 
2870   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(partition_probs);
2871 
2872   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_joint_probs);
2873   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_sign_prob);
2874   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class_probs);
2875   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class0_bit_prob);
2876   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_bits_prob);
2877   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class0_fr_probs);
2878   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_fr_probs);
2879   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_class0_hp_prob);
2880   ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX(mv_hp_prob);
2881 #undef ARRAY_MEMCPY_CHECKED_V4L2_ENTR_TO_FRM_CTX
2882 }
2883 
GetFrameContext(const scoped_refptr<VP9Picture> & pic,Vp9FrameContext * frame_ctx)2884 bool V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::GetFrameContext(
2885     const scoped_refptr<VP9Picture>& pic,
2886     Vp9FrameContext* frame_ctx) {
2887   struct v4l2_ctrl_vp9_entropy v4l2_entropy;
2888   memset(&v4l2_entropy, 0, sizeof(v4l2_entropy));
2889 
2890   struct v4l2_ext_control ctrl;
2891   memset(&ctrl, 0, sizeof(ctrl));
2892   ctrl.id = V4L2_CID_MPEG_VIDEO_VP9_ENTROPY;
2893   ctrl.size = sizeof(v4l2_entropy);
2894   ctrl.p_vp9_entropy = &v4l2_entropy;
2895 
2896   scoped_refptr<V4L2DecodeSurface> dec_surface =
2897       VP9PictureToV4L2DecodeSurface(pic);
2898 
2899   struct v4l2_ext_controls ext_ctrls;
2900   memset(&ext_ctrls, 0, sizeof(ext_ctrls));
2901   ext_ctrls.count = 1;
2902   ext_ctrls.controls = &ctrl;
2903   ext_ctrls.config_store = dec_surface->config_store();
2904 
2905   if (!v4l2_dec_->GetExtControls(&ext_ctrls))
2906     return false;
2907 
2908   FillVp9FrameContext(v4l2_entropy.current_entropy_ctx, frame_ctx);
2909   return true;
2910 }
2911 
2912 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
2913 V4L2SliceVideoDecodeAccelerator::V4L2VP9Accelerator::
VP9PictureToV4L2DecodeSurface(const scoped_refptr<VP9Picture> & pic)2914     VP9PictureToV4L2DecodeSurface(const scoped_refptr<VP9Picture>& pic) {
2915   V4L2VP9Picture* v4l2_pic = pic->AsV4L2VP9Picture();
2916   CHECK(v4l2_pic);
2917   return v4l2_pic->dec_surface();
2918 }
2919 
DecodeSurface(const scoped_refptr<V4L2DecodeSurface> & dec_surface)2920 void V4L2SliceVideoDecodeAccelerator::DecodeSurface(
2921     const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
2922   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2923 
2924   DVLOGF(3) << "Submitting decode for surface: " << dec_surface->ToString();
2925   Enqueue(dec_surface);
2926 }
2927 
SurfaceReady(const scoped_refptr<V4L2DecodeSurface> & dec_surface)2928 void V4L2SliceVideoDecodeAccelerator::SurfaceReady(
2929     const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
2930   DVLOGF(3);
2931   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2932 
2933   decoder_display_queue_.push(dec_surface);
2934   TryOutputSurfaces();
2935 }
2936 
TryOutputSurfaces()2937 void V4L2SliceVideoDecodeAccelerator::TryOutputSurfaces() {
2938   while (!decoder_display_queue_.empty()) {
2939     scoped_refptr<V4L2DecodeSurface> dec_surface =
2940         decoder_display_queue_.front();
2941 
2942     if (!dec_surface->decoded())
2943       break;
2944 
2945     decoder_display_queue_.pop();
2946     OutputSurface(dec_surface);
2947   }
2948 }
2949 
OutputSurface(const scoped_refptr<V4L2DecodeSurface> & dec_surface)2950 void V4L2SliceVideoDecodeAccelerator::OutputSurface(
2951     const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
2952   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2953 
2954   OutputRecord& output_record =
2955       output_buffer_map_[dec_surface->output_record()];
2956 
2957   bool inserted =
2958       surfaces_at_display_
2959           .insert(std::make_pair(output_record.picture_id, dec_surface))
2960           .second;
2961   DCHECK(inserted);
2962 
2963   DCHECK(!output_record.at_client);
2964   DCHECK(!output_record.at_device);
2965   DCHECK_NE(output_record.picture_id, -1);
2966   output_record.at_client = true;
2967 
2968   // TODO(posciak): Use visible size from decoder here instead
2969   // (crbug.com/402760). Passing (0, 0) results in the client using the
2970   // visible size extracted from the container instead.
2971   Picture picture(output_record.picture_id, dec_surface->bitstream_id(),
2972                   Rect(0, 0), false);
2973   DVLOGF(3) << dec_surface->ToString()
2974             << ", bitstream_id: " << picture.bitstream_buffer_id()
2975             << ", picture_id: " << picture.picture_buffer_id();
2976   pending_picture_ready_.push(PictureRecord(output_record.cleared, picture));
2977   SendPictureReady();
2978   output_record.cleared = true;
2979 }
2980 
2981 scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface>
CreateSurface()2982 V4L2SliceVideoDecodeAccelerator::CreateSurface() {
2983   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
2984   DCHECK_EQ(state_, kDecoding);
2985 
2986   if (free_input_buffers_.empty() || free_output_buffers_.empty())
2987     return nullptr;
2988 
2989   int input = free_input_buffers_.front();
2990   free_input_buffers_.pop_front();
2991   int output = free_output_buffers_.front();
2992   free_output_buffers_.pop_front();
2993 
2994   InputRecord& input_record = input_buffer_map_[input];
2995   DCHECK_EQ(input_record.bytes_used, 0u);
2996   DCHECK_EQ(input_record.input_id, -1);
2997   DCHECK(decoder_current_bitstream_buffer_ != nullptr);
2998   input_record.input_id = decoder_current_bitstream_buffer_->input_id;
2999 
3000   scoped_refptr<V4L2DecodeSurface> dec_surface = new V4L2DecodeSurface(
3001       decoder_current_bitstream_buffer_->input_id, input, output,
3002       base::Bind(&V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer,
3003                  base::Unretained(this)));
3004 
3005   DVLOGF(4) << "Created surface " << input << " -> " << output;
3006   return dec_surface;
3007 }
3008 
SendPictureReady()3009 void V4L2SliceVideoDecodeAccelerator::SendPictureReady() {
3010   DVLOGF(3);
3011   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
3012   bool resetting_or_flushing = (decoder_resetting_ || decoder_flushing_);
3013   while (!pending_picture_ready_.empty()) {
3014     bool cleared = pending_picture_ready_.front().cleared;
3015     const Picture& picture = pending_picture_ready_.front().picture;
3016     if (cleared && picture_clearing_count_ == 0) {
3017       DVLOGF(4) << "Posting picture ready to decode task runner for: "
3018                 << picture.picture_buffer_id();
3019       // This picture is cleared. It can be posted to a thread different than
3020       // the main GPU thread to reduce latency. This should be the case after
3021       // all pictures are cleared at the beginning.
3022       decode_task_runner_->PostTask(
3023           FROM_HERE,
3024           base::Bind(&Client::PictureReady, decode_client_, picture));
3025       pending_picture_ready_.pop();
3026     } else if (!cleared || resetting_or_flushing) {
3027       DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared
3028                 << ", decoder_resetting_=" << decoder_resetting_
3029                 << ", decoder_flushing_=" << decoder_flushing_
3030                 << ", picture_clearing_count_=" << picture_clearing_count_;
3031       DVLOGF(4) << "Posting picture ready to GPU for: "
3032                 << picture.picture_buffer_id();
3033       // If the picture is not cleared, post it to the child thread because it
3034       // has to be cleared in the child thread. A picture only needs to be
3035       // cleared once. If the decoder is resetting or flushing, send all
3036       // pictures to ensure PictureReady arrive before reset or flush done.
3037       child_task_runner_->PostTaskAndReply(
3038           FROM_HERE, base::Bind(&Client::PictureReady, client_, picture),
3039           // Unretained is safe. If Client::PictureReady gets to run, |this| is
3040           // alive. Destroy() will wait the decode thread to finish.
3041           base::Bind(&V4L2SliceVideoDecodeAccelerator::PictureCleared,
3042                      base::Unretained(this)));
3043       picture_clearing_count_++;
3044       pending_picture_ready_.pop();
3045     } else {
3046       // This picture is cleared. But some pictures are about to be cleared on
3047       // the child thread. To preserve the order, do not send this until those
3048       // pictures are cleared.
3049       break;
3050     }
3051   }
3052 }
3053 
PictureCleared()3054 void V4L2SliceVideoDecodeAccelerator::PictureCleared() {
3055   DVLOGF(3) << "clearing count=" << picture_clearing_count_;
3056   DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
3057   DCHECK_GT(picture_clearing_count_, 0);
3058   picture_clearing_count_--;
3059   SendPictureReady();
3060 }
3061 
TryToSetupDecodeOnSeparateThread(const base::WeakPtr<Client> & decode_client,const scoped_refptr<base::SingleThreadTaskRunner> & decode_task_runner)3062 bool V4L2SliceVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
3063     const base::WeakPtr<Client>& decode_client,
3064     const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
3065   decode_client_ = decode_client;
3066   decode_task_runner_ = decode_task_runner;
3067   return true;
3068 }
3069 
3070 // static
3071 VideoDecodeAccelerator::SupportedProfiles
GetSupportedProfiles()3072 V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles() {
3073   scoped_refptr<V4L2Device> device(new V4L2Device());
3074   if (!device)
3075     return SupportedProfiles();
3076 
3077   return device->GetSupportedDecodeProfiles(arraysize(supported_input_fourccs_),
3078                                             supported_input_fourccs_);
3079 }
3080 
3081 }  // namespace media
3082