1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/gpu/v4l2/v4l2_video_decoder_backend_stateless.h"
6 
7 #include <fcntl.h>
8 #include <linux/media.h>
9 #include <sys/ioctl.h>
10 
11 #include <memory>
12 
13 #include "base/bind.h"
14 #include "base/callback_helpers.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "base/sequenced_task_runner.h"
17 #include "media/base/decode_status.h"
18 #include "media/base/video_codecs.h"
19 #include "media/base/video_frame.h"
20 #include "media/gpu/accelerated_video_decoder.h"
21 #include "media/gpu/chromeos/dmabuf_video_frame_pool.h"
22 #include "media/gpu/macros.h"
23 #include "media/gpu/v4l2/v4l2_device.h"
24 #include "media/gpu/v4l2/v4l2_h264_accelerator.h"
25 #include "media/gpu/v4l2/v4l2_h264_accelerator_legacy.h"
26 #include "media/gpu/v4l2/v4l2_vp8_accelerator.h"
27 #include "media/gpu/v4l2/v4l2_vp8_accelerator_legacy.h"
28 #include "media/gpu/v4l2/v4l2_vp9_accelerator_legacy.h"
29 
30 namespace media {
31 
32 namespace {
33 
34 // Size of the timestamp cache, needs to be large enough for frame-reordering.
35 constexpr size_t kTimestampCacheSize = 128;
36 // Number of requests to allocate for submitting input buffers, if requests
37 // are used.
38 
39 }  // namespace
40 
41 struct V4L2StatelessVideoDecoderBackend::OutputRequest {
Surfacemedia::V4L2StatelessVideoDecoderBackend::OutputRequest42   static OutputRequest Surface(scoped_refptr<V4L2DecodeSurface> s,
43                                base::TimeDelta t) {
44     return OutputRequest(std::move(s), t);
45   }
46 
FlushFencemedia::V4L2StatelessVideoDecoderBackend::OutputRequest47   static OutputRequest FlushFence() { return OutputRequest(kFlushFence); }
48 
ChangeResolutionFencemedia::V4L2StatelessVideoDecoderBackend::OutputRequest49   static OutputRequest ChangeResolutionFence() {
50     return OutputRequest(kChangeResolutionFence);
51   }
52 
IsReadymedia::V4L2StatelessVideoDecoderBackend::OutputRequest53   bool IsReady() const {
54     return (type != OutputRequestType::kSurface) || surface->decoded();
55   }
56 
57   // Allow move, but not copy.
58   OutputRequest(OutputRequest&&) = default;
59 
60   enum OutputRequestType {
61     // The surface to be outputted.
62     kSurface,
63     // The fence to indicate the flush request.
64     kFlushFence,
65     // The fence to indicate resolution change request.
66     kChangeResolutionFence,
67   };
68 
69   // The type of the request.
70   const OutputRequestType type;
71   // The surface to be outputted.
72   scoped_refptr<V4L2DecodeSurface> surface;
73   // The timestamp of the output frame. Because a surface might be outputted
74   // multiple times with different timestamp, we need to store timestamp out of
75   // surface.
76   base::TimeDelta timestamp;
77 
78  private:
OutputRequestmedia::V4L2StatelessVideoDecoderBackend::OutputRequest79   OutputRequest(scoped_refptr<V4L2DecodeSurface> s, base::TimeDelta t)
80       : type(kSurface), surface(std::move(s)), timestamp(t) {}
OutputRequestmedia::V4L2StatelessVideoDecoderBackend::OutputRequest81   explicit OutputRequest(OutputRequestType t) : type(t) {}
82 
83   DISALLOW_COPY_AND_ASSIGN(OutputRequest);
84 };
85 
DecodeRequest(scoped_refptr<DecoderBuffer> buf,VideoDecoder::DecodeCB cb,int32_t id)86 V4L2StatelessVideoDecoderBackend::DecodeRequest::DecodeRequest(
87     scoped_refptr<DecoderBuffer> buf,
88     VideoDecoder::DecodeCB cb,
89     int32_t id)
90     : buffer(std::move(buf)), decode_cb(std::move(cb)), bitstream_id(id) {}
91 
92 V4L2StatelessVideoDecoderBackend::DecodeRequest::DecodeRequest(
93     DecodeRequest&&) = default;
94 V4L2StatelessVideoDecoderBackend::DecodeRequest&
95 V4L2StatelessVideoDecoderBackend::DecodeRequest::operator=(DecodeRequest&&) =
96     default;
97 
98 V4L2StatelessVideoDecoderBackend::DecodeRequest::~DecodeRequest() = default;
99 
V4L2StatelessVideoDecoderBackend(Client * const client,scoped_refptr<V4L2Device> device,VideoCodecProfile profile,scoped_refptr<base::SequencedTaskRunner> task_runner)100 V4L2StatelessVideoDecoderBackend::V4L2StatelessVideoDecoderBackend(
101     Client* const client,
102     scoped_refptr<V4L2Device> device,
103     VideoCodecProfile profile,
104     scoped_refptr<base::SequencedTaskRunner> task_runner)
105     : V4L2VideoDecoderBackend(client, std::move(device)),
106       profile_(profile),
107       bitstream_id_to_timestamp_(kTimestampCacheSize),
108       task_runner_(task_runner) {
109   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
110 
111   weak_this_ = weak_this_factory_.GetWeakPtr();
112 }
113 
~V4L2StatelessVideoDecoderBackend()114 V4L2StatelessVideoDecoderBackend::~V4L2StatelessVideoDecoderBackend() {
115   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
116   DCHECK(surfaces_at_device_.empty());
117 
118   if (!output_request_queue_.empty() || flush_cb_ || current_decode_request_ ||
119       !decode_request_queue_.empty()) {
120     VLOGF(1) << "Should not destroy backend during pending decode!";
121   }
122 }
123 
Initialize()124 bool V4L2StatelessVideoDecoderBackend::Initialize() {
125   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
126 
127   if (!IsSupportedProfile(profile_)) {
128     VLOGF(1) << "Unsupported profile " << GetProfileName(profile_);
129     return false;
130   }
131 
132   if (!CreateAvd())
133     return false;
134 
135   if (input_queue_->SupportsRequests()) {
136     requests_queue_ = device_->GetRequestsQueue();
137     if (requests_queue_ == nullptr)
138       return false;
139   }
140 
141   return true;
142 }
143 
144 // static
ReuseOutputBufferThunk(scoped_refptr<base::SequencedTaskRunner> task_runner,base::Optional<base::WeakPtr<V4L2StatelessVideoDecoderBackend>> weak_this,V4L2ReadableBufferRef buffer)145 void V4L2StatelessVideoDecoderBackend::ReuseOutputBufferThunk(
146     scoped_refptr<base::SequencedTaskRunner> task_runner,
147     base::Optional<base::WeakPtr<V4L2StatelessVideoDecoderBackend>> weak_this,
148     V4L2ReadableBufferRef buffer) {
149   DVLOGF(3);
150   DCHECK(weak_this);
151 
152   if (task_runner->RunsTasksInCurrentSequence()) {
153     if (*weak_this) {
154       (*weak_this)->ReuseOutputBuffer(std::move(buffer));
155     }
156   } else {
157     task_runner->PostTask(
158         FROM_HERE,
159         base::BindOnce(&V4L2StatelessVideoDecoderBackend::ReuseOutputBuffer,
160                        *weak_this, std::move(buffer)));
161   }
162 }
163 
ReuseOutputBuffer(V4L2ReadableBufferRef buffer)164 void V4L2StatelessVideoDecoderBackend::ReuseOutputBuffer(
165     V4L2ReadableBufferRef buffer) {
166   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
167   DVLOGF(3) << "Reuse output surface #" << buffer->BufferId();
168 
169   // Resume decoding in case of ran out of surface.
170   if (pause_reason_ == PauseReason::kRanOutOfSurfaces) {
171     pause_reason_ = PauseReason::kNone;
172     task_runner_->PostTask(
173         FROM_HERE,
174         base::BindOnce(&V4L2StatelessVideoDecoderBackend::DoDecodeWork,
175                        weak_this_));
176   }
177 }
178 
OnOutputBufferDequeued(V4L2ReadableBufferRef dequeued_buffer)179 void V4L2StatelessVideoDecoderBackend::OnOutputBufferDequeued(
180     V4L2ReadableBufferRef dequeued_buffer) {
181   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
182 
183   // Mark the output buffer decoded, and try to output surface.
184   DCHECK(!surfaces_at_device_.empty());
185   auto surface = std::move(surfaces_at_device_.front());
186   DCHECK_EQ(static_cast<size_t>(surface->output_record()),
187             dequeued_buffer->BufferId());
188   surfaces_at_device_.pop();
189 
190   surface->SetDecoded();
191 
192   auto reuse_buffer_cb =
193       base::BindOnce(&V4L2StatelessVideoDecoderBackend::ReuseOutputBufferThunk,
194                      task_runner_, weak_this_, std::move(dequeued_buffer));
195   if (output_queue_->GetMemoryType() == V4L2_MEMORY_MMAP) {
196     // Keep a reference to the V4L2 buffer until the frame is reused, because
197     // the frame is backed up by the V4L2 buffer's memory.
198     surface->video_frame()->AddDestructionObserver(std::move(reuse_buffer_cb));
199   } else {
200     // Keep a reference to the V4L2 buffer until the buffer is reused. The
201     // reason for this is that the config store uses V4L2 buffer IDs to
202     // reference frames, therefore we cannot reuse the same V4L2 buffer ID for
203     // another decode operation until all references to that frame are gone.
204     // Request API does not have this limitation, so we can probably remove this
205     // after config store is gone.
206     surface->SetReleaseCallback(std::move(reuse_buffer_cb));
207   }
208 
209   PumpOutputSurfaces();
210 
211   // If we were waiting for an output buffer to be available, schedule a
212   // decode task.
213   if (pause_reason_ == PauseReason::kWaitSubFrameDecoded) {
214     pause_reason_ = PauseReason::kNone;
215     task_runner_->PostTask(
216         FROM_HERE,
217         base::BindOnce(&V4L2StatelessVideoDecoderBackend::DoDecodeWork,
218                        weak_this_));
219   }
220 }
221 
222 scoped_refptr<V4L2DecodeSurface>
CreateSurface()223 V4L2StatelessVideoDecoderBackend::CreateSurface() {
224   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
225   DVLOGF(4);
226 
227   // Request V4L2 input and output buffers.
228   auto input_buf = input_queue_->GetFreeBuffer();
229   auto output_buf = output_queue_->GetFreeBuffer();
230   if (!input_buf || !output_buf) {
231     DVLOGF(3) << "There is no free V4L2 buffer.";
232     return nullptr;
233   }
234 
235   DmabufVideoFramePool* pool = client_->GetVideoFramePool();
236   scoped_refptr<VideoFrame> frame;
237   if (!pool) {
238     // Get VideoFrame from the V4L2 buffer because now we allocate from V4L2
239     // driver via MMAP. The VideoFrame received from V4L2 buffer will remain
240     // until deallocating V4L2Queue. But we need to know when the buffer is not
241     // used by the client. So we wrap the frame here.
242     scoped_refptr<VideoFrame> origin_frame = output_buf->GetVideoFrame();
243     frame = VideoFrame::WrapVideoFrame(origin_frame, origin_frame->format(),
244                                        origin_frame->visible_rect(),
245                                        origin_frame->natural_size());
246   } else {
247     // Try to get VideoFrame from the pool.
248     frame = pool->GetFrame();
249     if (!frame) {
250       // We allocate the same number of output buffer slot in V4L2 device and
251       // the output VideoFrame. If there is free output buffer slot but no free
252       // VideoFrame, it means the VideoFrame is not released at client
253       // side. Post DoDecodeWork when the pool has available frames.
254       DVLOGF(3) << "There is no available VideoFrame.";
255       pool->NotifyWhenFrameAvailable(base::BindOnce(
256           base::IgnoreResult(&base::SequencedTaskRunner::PostTask),
257           task_runner_, FROM_HERE,
258           base::BindOnce(&V4L2StatelessVideoDecoderBackend::DoDecodeWork,
259                          weak_this_)));
260       return nullptr;
261     }
262   }
263 
264   scoped_refptr<V4L2DecodeSurface> dec_surface;
265   if (input_queue_->SupportsRequests()) {
266     base::Optional<V4L2RequestRef> request_ref =
267         requests_queue_->GetFreeRequest();
268     if (!request_ref) {
269       DVLOGF(1) << "Could not get free request.";
270       return nullptr;
271     }
272 
273     dec_surface = new V4L2RequestDecodeSurface(
274         std::move(*input_buf), std::move(*output_buf), std::move(frame),
275         std::move(*request_ref));
276   } else {
277     dec_surface = new V4L2ConfigStoreDecodeSurface(
278         std::move(*input_buf), std::move(*output_buf), std::move(frame));
279   }
280 
281   return dec_surface;
282 }
283 
SubmitSlice(V4L2DecodeSurface * dec_surface,const uint8_t * data,size_t size)284 bool V4L2StatelessVideoDecoderBackend::SubmitSlice(
285     V4L2DecodeSurface* dec_surface,
286     const uint8_t* data,
287     size_t size) {
288   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
289   DVLOGF(3);
290 
291   size_t plane_size = dec_surface->input_buffer().GetPlaneSize(0);
292   size_t bytes_used = dec_surface->input_buffer().GetPlaneBytesUsed(0);
293   if (size > plane_size - bytes_used) {
294     VLOGF(1) << "The size of submitted slice(" << size
295              << ") is larger than the remaining buffer size("
296              << plane_size - bytes_used << "). Plane size is " << plane_size;
297     client_->OnBackendError();
298     return false;
299   }
300 
301   void* mapping = dec_surface->input_buffer().GetPlaneMapping(0);
302   memcpy(reinterpret_cast<uint8_t*>(mapping) + bytes_used, data, size);
303   dec_surface->input_buffer().SetPlaneBytesUsed(0, bytes_used + size);
304   return true;
305 }
306 
DecodeSurface(scoped_refptr<V4L2DecodeSurface> dec_surface)307 void V4L2StatelessVideoDecoderBackend::DecodeSurface(
308     scoped_refptr<V4L2DecodeSurface> dec_surface) {
309   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
310   DVLOGF(3);
311 
312   if (!dec_surface->Submit()) {
313     VLOGF(1) << "Error while submitting frame for decoding!";
314     client_->OnBackendError();
315     return;
316   }
317 
318   surfaces_at_device_.push(std::move(dec_surface));
319 }
320 
SurfaceReady(scoped_refptr<V4L2DecodeSurface> dec_surface,int32_t bitstream_id,const gfx::Rect & visible_rect,const VideoColorSpace &)321 void V4L2StatelessVideoDecoderBackend::SurfaceReady(
322     scoped_refptr<V4L2DecodeSurface> dec_surface,
323     int32_t bitstream_id,
324     const gfx::Rect& visible_rect,
325     const VideoColorSpace& /* color_space */) {
326   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
327   DVLOGF(3);
328 
329   // Find the timestamp associated with |bitstream_id|. It's possible that a
330   // surface is output multiple times for different |bitstream_id|s (e.g. VP9
331   // show_existing_frame feature). This means we need to output the same frame
332   // again with a different timestamp.
333   // On some rare occasions it's also possible that a single DecoderBuffer
334   // produces multiple surfaces with the same |bitstream_id|, so we shouldn't
335   // remove the timestamp from the cache.
336   const auto it = bitstream_id_to_timestamp_.Peek(bitstream_id);
337   DCHECK(it != bitstream_id_to_timestamp_.end());
338   base::TimeDelta timestamp = it->second;
339 
340   dec_surface->SetVisibleRect(visible_rect);
341   output_request_queue_.push(
342       OutputRequest::Surface(std::move(dec_surface), timestamp));
343   PumpOutputSurfaces();
344 }
345 
EnqueueDecodeTask(scoped_refptr<DecoderBuffer> buffer,VideoDecoder::DecodeCB decode_cb,int32_t bitstream_id)346 void V4L2StatelessVideoDecoderBackend::EnqueueDecodeTask(
347     scoped_refptr<DecoderBuffer> buffer,
348     VideoDecoder::DecodeCB decode_cb,
349     int32_t bitstream_id) {
350   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
351 
352   if (!buffer->end_of_stream()) {
353     bitstream_id_to_timestamp_.Put(bitstream_id, buffer->timestamp());
354   }
355 
356   decode_request_queue_.push(
357       DecodeRequest(std::move(buffer), std::move(decode_cb), bitstream_id));
358 
359   // If we are already decoding, then we don't need to pump again.
360   if (!current_decode_request_)
361     DoDecodeWork();
362 }
363 
DoDecodeWork()364 void V4L2StatelessVideoDecoderBackend::DoDecodeWork() {
365   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
366 
367   if (!client_->IsDecoding())
368     return;
369 
370   if (!PumpDecodeTask())
371     client_->OnBackendError();
372 }
373 
PumpDecodeTask()374 bool V4L2StatelessVideoDecoderBackend::PumpDecodeTask() {
375   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
376   DVLOGF(3) << " Number of Decode requests: " << decode_request_queue_.size();
377 
378   pause_reason_ = PauseReason::kNone;
379   while (true) {
380     switch (avd_->Decode()) {
381       case AcceleratedVideoDecoder::kConfigChange:
382         if (profile_ != avd_->GetProfile()) {
383           DVLOGF(3) << "Profile is changed: " << profile_ << " -> "
384                     << avd_->GetProfile();
385           if (!IsSupportedProfile(avd_->GetProfile())) {
386             VLOGF(2) << "Unsupported profile: " << avd_->GetProfile();
387             return false;
388           }
389 
390           profile_ = avd_->GetProfile();
391         }
392 
393         if (pic_size_ == avd_->GetPicSize()) {
394           // There is no need to do anything in V4L2 API when only a profile is
395           // changed.
396           DVLOGF(3) << "Only profile is changed. No need to do anything.";
397           continue;
398         }
399 
400         DVLOGF(3) << "Need to change resolution. Pause decoding.";
401         client_->InitiateFlush();
402 
403         output_request_queue_.push(OutputRequest::ChangeResolutionFence());
404         PumpOutputSurfaces();
405         return true;
406 
407       case AcceleratedVideoDecoder::kRanOutOfStreamData:
408         // Current decode request is finished processing.
409         if (current_decode_request_) {
410           DCHECK(current_decode_request_->decode_cb);
411           std::move(current_decode_request_->decode_cb).Run(DecodeStatus::OK);
412           current_decode_request_ = base::nullopt;
413         }
414 
415         // Process next decode request.
416         if (decode_request_queue_.empty())
417           return true;
418         current_decode_request_ = std::move(decode_request_queue_.front());
419         decode_request_queue_.pop();
420 
421         if (current_decode_request_->buffer->end_of_stream()) {
422           if (!avd_->Flush()) {
423             VLOGF(1) << "Failed flushing the decoder.";
424             return false;
425           }
426           // Put the decoder in an idle state, ready to resume.
427           avd_->Reset();
428 
429           client_->InitiateFlush();
430           DCHECK(!flush_cb_);
431           flush_cb_ = std::move(current_decode_request_->decode_cb);
432 
433           output_request_queue_.push(OutputRequest::FlushFence());
434           PumpOutputSurfaces();
435           current_decode_request_ = base::nullopt;
436           return true;
437         }
438 
439         avd_->SetStream(current_decode_request_->bitstream_id,
440                         *current_decode_request_->buffer);
441         break;
442 
443       case AcceleratedVideoDecoder::kRanOutOfSurfaces:
444         DVLOGF(3) << "Ran out of surfaces. Resume when buffer is returned.";
445         pause_reason_ = PauseReason::kRanOutOfSurfaces;
446         return true;
447 
448       case AcceleratedVideoDecoder::kNeedContextUpdate:
449         DVLOGF(3) << "Awaiting context update";
450         pause_reason_ = PauseReason::kWaitSubFrameDecoded;
451         return true;
452 
453       case AcceleratedVideoDecoder::kDecodeError:
454         DVLOGF(3) << "Error decoding stream";
455         return false;
456 
457       case AcceleratedVideoDecoder::kTryAgain:
458         NOTREACHED() << "Should not reach here unless this class accepts "
459                         "encrypted streams.";
460         DVLOGF(4) << "No key for decoding stream.";
461         return false;
462     }
463   }
464 }
465 
PumpOutputSurfaces()466 void V4L2StatelessVideoDecoderBackend::PumpOutputSurfaces() {
467   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
468   DVLOGF(3) << "Number of display surfaces: " << output_request_queue_.size();
469 
470   bool resume_decode = false;
471   while (!output_request_queue_.empty()) {
472     if (!output_request_queue_.front().IsReady()) {
473       DVLOGF(3) << "The first surface is not ready yet.";
474       break;
475     }
476 
477     OutputRequest request = std::move(output_request_queue_.front());
478     output_request_queue_.pop();
479     switch (request.type) {
480       case OutputRequest::kFlushFence:
481         DCHECK(output_request_queue_.empty());
482         DVLOGF(2) << "Flush finished.";
483         std::move(flush_cb_).Run(DecodeStatus::OK);
484         resume_decode = true;
485         break;
486 
487       case OutputRequest::kChangeResolutionFence:
488         DCHECK(output_request_queue_.empty());
489         ChangeResolution();
490         break;
491 
492       case OutputRequest::kSurface:
493         scoped_refptr<V4L2DecodeSurface> surface = std::move(request.surface);
494 
495         DCHECK(surface->video_frame());
496         client_->OutputFrame(surface->video_frame(), surface->visible_rect(),
497                              request.timestamp);
498         break;
499     }
500   }
501 
502   if (resume_decode) {
503     client_->CompleteFlush();
504     task_runner_->PostTask(
505         FROM_HERE,
506         base::BindOnce(&V4L2StatelessVideoDecoderBackend::DoDecodeWork,
507                        weak_this_));
508   }
509 }
510 
ChangeResolution()511 void V4L2StatelessVideoDecoderBackend::ChangeResolution() {
512   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
513   // We change resolution after outputting all pending surfaces, there should
514   // be no V4L2DecodeSurface left.
515   DCHECK(surfaces_at_device_.empty());
516   DCHECK(output_request_queue_.empty());
517 
518   size_t num_output_frames = avd_->GetRequiredNumOfPictures();
519   gfx::Rect visible_rect = avd_->GetVisibleRect();
520   gfx::Size pic_size = avd_->GetPicSize();
521   // Set output format with the new resolution.
522   DCHECK(!pic_size.IsEmpty());
523   DVLOGF(3) << "Change resolution to " << pic_size.ToString();
524   client_->ChangeResolution(pic_size, visible_rect, num_output_frames);
525 }
526 
ApplyResolution(const gfx::Size & pic_size,const gfx::Rect & visible_rect,const size_t num_output_frames)527 bool V4L2StatelessVideoDecoderBackend::ApplyResolution(
528     const gfx::Size& pic_size,
529     const gfx::Rect& visible_rect,
530     const size_t num_output_frames) {
531   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
532   DCHECK_EQ(input_queue_->QueuedBuffersCount(), 0u);
533 
534   auto ret = input_queue_->GetFormat().first;
535   if (!ret) {
536     VPLOGF(1) << "Failed getting OUTPUT format";
537     return false;
538   }
539   struct v4l2_format format = std::move(*ret);
540 
541   format.fmt.pix_mp.width = pic_size.width();
542   format.fmt.pix_mp.height = pic_size.height();
543   if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0) {
544     VPLOGF(1) << "Failed setting OUTPUT format";
545     return false;
546   }
547 
548   return true;
549 }
550 
OnChangeResolutionDone(bool success)551 void V4L2StatelessVideoDecoderBackend::OnChangeResolutionDone(bool success) {
552   if (!success) {
553     client_->OnBackendError();
554     return;
555   }
556 
557   pic_size_ = avd_->GetPicSize();
558   client_->CompleteFlush();
559   task_runner_->PostTask(
560       FROM_HERE, base::BindOnce(&V4L2StatelessVideoDecoderBackend::DoDecodeWork,
561                                 weak_this_));
562 }
563 
OnStreamStopped(bool stop_input_queue)564 void V4L2StatelessVideoDecoderBackend::OnStreamStopped(bool stop_input_queue) {
565   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
566   DVLOGF(3);
567 
568   // The V4L2 stream has been stopped stopped, so all surfaces on the device
569   // have been returned to the client.
570   surfaces_at_device_ = {};
571 }
572 
ClearPendingRequests(DecodeStatus status)573 void V4L2StatelessVideoDecoderBackend::ClearPendingRequests(
574     DecodeStatus status) {
575   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
576   DVLOGF(3);
577 
578   if (avd_) {
579     // If we reset during resolution change, re-create AVD. Then the new AVD
580     // will trigger resolution change again after reset.
581     if (pic_size_ != avd_->GetPicSize()) {
582       CreateAvd();
583     } else {
584       avd_->Reset();
585     }
586   }
587 
588   // Clear output_request_queue_.
589   while (!output_request_queue_.empty())
590     output_request_queue_.pop();
591 
592   if (flush_cb_)
593     std::move(flush_cb_).Run(status);
594 
595   // Clear current_decode_request_ and decode_request_queue_.
596   if (current_decode_request_) {
597     std::move(current_decode_request_->decode_cb).Run(status);
598     current_decode_request_ = base::nullopt;
599   }
600 
601   while (!decode_request_queue_.empty()) {
602     auto request = std::move(decode_request_queue_.front());
603     decode_request_queue_.pop();
604     std::move(request.decode_cb).Run(status);
605   }
606 }
607 
StopInputQueueOnResChange() const608 bool V4L2StatelessVideoDecoderBackend::StopInputQueueOnResChange() const {
609   return true;
610 }
611 
IsSupportedProfile(VideoCodecProfile profile)612 bool V4L2StatelessVideoDecoderBackend::IsSupportedProfile(
613     VideoCodecProfile profile) {
614   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
615   DCHECK(device_);
616   if (supported_profiles_.empty()) {
617     constexpr uint32_t kSupportedInputFourccs[] = {
618         V4L2_PIX_FMT_H264_SLICE,
619         V4L2_PIX_FMT_VP8_FRAME,
620         V4L2_PIX_FMT_VP9_FRAME,
621     };
622     scoped_refptr<V4L2Device> device = V4L2Device::Create();
623     VideoDecodeAccelerator::SupportedProfiles profiles =
624         device->GetSupportedDecodeProfiles(base::size(kSupportedInputFourccs),
625                                            kSupportedInputFourccs);
626     for (const auto& profile : profiles)
627       supported_profiles_.push_back(profile.profile);
628   }
629   return std::find(supported_profiles_.begin(), supported_profiles_.end(),
630                    profile) != supported_profiles_.end();
631 }
632 
CreateAvd()633 bool V4L2StatelessVideoDecoderBackend::CreateAvd() {
634   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
635   DVLOGF(3);
636 
637   pic_size_ = gfx::Size();
638 
639   if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) {
640     if (input_queue_->SupportsRequests()) {
641       avd_ = std::make_unique<H264Decoder>(
642           std::make_unique<V4L2H264Accelerator>(this, device_.get()), profile_);
643     } else {
644       avd_ = std::make_unique<H264Decoder>(
645           std::make_unique<V4L2LegacyH264Accelerator>(this, device_.get()),
646           profile_);
647     }
648   } else if (profile_ >= VP8PROFILE_MIN && profile_ <= VP8PROFILE_MAX) {
649     if (input_queue_->SupportsRequests()) {
650       avd_ = std::make_unique<VP8Decoder>(
651           std::make_unique<V4L2VP8Accelerator>(this, device_.get()));
652     } else {
653       avd_ = std::make_unique<VP8Decoder>(
654           std::make_unique<V4L2LegacyVP8Accelerator>(this, device_.get()));
655     }
656   } else if (profile_ >= VP9PROFILE_MIN && profile_ <= VP9PROFILE_MAX) {
657     avd_ = std::make_unique<VP9Decoder>(
658         std::make_unique<V4L2LegacyVP9Accelerator>(this, device_.get()),
659         profile_);
660   } else {
661     VLOGF(1) << "Unsupported profile " << GetProfileName(profile_);
662     return false;
663   }
664   return true;
665 }
666 
667 }  // namespace media
668