| Index: content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
|
| diff --git a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
|
| index d4b0e2e7e027a66ebd2a0a1183240ff44dc6b4cd..f917e1a4e3bcc7a3cefb63412bb9fe8c7553d14f 100644
|
| --- a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
|
| +++ b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
|
| @@ -11,6 +11,7 @@
|
|
|
| #include <memory>
|
| #include <queue>
|
| +#include <utility>
|
| #include <vector>
|
|
|
| #include "base/macros.h"
|
| @@ -49,6 +50,9 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
|
| void AssignPictureBuffers(
|
| const std::vector<media::PictureBuffer>& buffers) override;
|
| + void ImportBufferForPicture(int32_t picture_buffer_id,
|
| + const std::vector<gfx::GpuMemoryBufferHandle>&
|
| + gpu_memory_buffer_handles) override;
|
| void ReusePictureBuffer(int32_t picture_buffer_id) override;
|
| void Flush() override;
|
| void Reset() override;
|
| @@ -57,6 +61,7 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| const base::WeakPtr<Client>& decode_client,
|
| const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
|
| override;
|
| + media::VideoPixelFormat GetOutputFormat() const override;
|
|
|
| static media::VideoDecodeAccelerator::SupportedProfiles
|
| GetSupportedProfiles();
|
| @@ -81,8 +86,10 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| bool at_device;
|
| bool at_client;
|
| int32_t picture_id;
|
| + GLuint texture_id;
|
| EGLImageKHR egl_image;
|
| EGLSyncKHR egl_sync;
|
| + std::vector<base::ScopedFD> dmabuf_fds;
|
| bool cleared;
|
| };
|
|
|
| @@ -158,28 +165,31 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
|
|
| // Dismiss all |picture_buffer_ids| via Client::DismissPictureBuffer()
|
| // and signal |done| after finishing.
|
| - void DismissPictures(std::vector<int32_t> picture_buffer_ids,
|
| + void DismissPictures(const std::vector<int32_t>& picture_buffer_ids,
|
| base::WaitableEvent* done);
|
|
|
| // Task to finish initialization on decoder_thread_.
|
| void InitializeTask();
|
|
|
| - // Surface set change (resolution change) flow.
|
| - // If we have no surfaces allocated, just allocate them and return.
|
| - // Otherwise mark us as pending for surface set change.
|
| - void InitiateSurfaceSetChange();
|
| - // If a surface set change is pending and we are ready, stop the device,
|
| - // destroy outputs, releasing resources and dismissing pictures as required,
|
| - // followed by allocating a new set for the new resolution/DPB size
|
| - // as provided by decoder. Finally, try to resume decoding.
|
| - void FinishSurfaceSetChangeIfNeeded();
|
| -
|
| void NotifyError(Error error);
|
| void DestroyTask();
|
|
|
| // Sets the state to kError and notifies client if needed.
|
| void SetErrorState(Error error);
|
|
|
| + // Event handling. Events include flush, reset and resolution change and are
|
| + // processed while in kIdle state.
|
| +
|
| + // Surface set change (resolution change) flow.
|
| + // If we have no surfaces allocated, start it immediately, otherwise mark
|
| + // ourselves as pending for surface set change.
|
| + void InitiateSurfaceSetChange();
|
| + // If a surface set change is pending and we are ready, stop the device,
|
| + // destroy outputs, releasing resources and dismissing pictures as required,
|
| + // followed by starting the flow to allocate a new set for the current
|
| + // resolution/DPB size, as provided by decoder.
|
| + bool FinishSurfaceSetChange();
|
| +
|
| // Flush flow when requested by client.
|
| // When Flush() is called, it posts a FlushTask, which checks the input queue.
|
| // If nothing is pending for decode on decoder_input_queue_, we call
|
| @@ -190,22 +200,78 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| // Tell the decoder to flush all frames, reset it and mark us as scheduled
|
| // for flush, so that we can finish it once all pending decodes are finished.
|
| void InitiateFlush();
|
| - // If all pending frames are decoded and we are waiting to flush, perform it.
|
| - // This will send all pending pictures to client and notify the client that
|
| - // flush is complete and puts us in a state ready to resume.
|
| - void FinishFlushIfNeeded();
|
| + // To be called if decoder_flushing_ is true. If not all pending frames are
|
| + // decoded, return false, requesting the caller to try again later.
|
| + // Otherwise perform flush by sending all pending pictures to the client,
|
| + // notify it that flush is finished and return true, informing the caller
|
| + // that further progress can be made.
|
| + bool FinishFlush();
|
|
|
| // Reset flow when requested by client.
|
| - // Drop all inputs and reset the decoder and mark us as pending for reset.
|
| + // Drop all inputs, reset the decoder and mark us as pending for reset.
|
| void ResetTask();
|
| - // If all pending frames are decoded and we are waiting to reset, perform it.
|
| - // This drops all pending outputs (client is not interested anymore),
|
| - // notifies the client we are done and puts us in a state ready to resume.
|
| - void FinishResetIfNeeded();
|
| -
|
| - // Process pending events if any.
|
| + // To be called if decoder_resetting_ is true. If not all pending frames are
|
| + // decoded, return false, requesting the caller to try again later.
|
| + // Otherwise perform reset by dropping all pending outputs (client is not
|
| + // interested anymore), notifying it that reset is finished, and return true,
|
| + // informing the caller that further progress can be made.
|
| + bool FinishReset();
|
| +
|
| + // Called when a new event is pended. Transitions us into kIdle state (if not
|
| + // already in it), if possible. Also starts processing events.
|
| + void NewEventPending();
|
| +
|
| + // Called after all events are processed successfully (i.e. all Finish*()
|
| + // methods return true) to return to decoding state.
|
| + bool FinishEventProcessing();
|
| +
|
| + // Process pending events, if any.
|
| void ProcessPendingEventsIfNeeded();
|
|
|
| +
|
| + // Allocate V4L2 buffers and assign them to |buffers| provided by the client
|
| + // via AssignPictureBuffers() on decoder thread.
|
| + void AssignPictureBuffersTask(
|
| + const std::vector<media::PictureBuffer>& buffers);
|
| +
|
| + // Use buffer backed by dmabuf file descriptors in |passed_dmabuf_fds| for the
|
| + // OutputRecord associated with |picture_buffer_id|, taking ownership of the
|
| + // file descriptors.
|
| + void ImportBufferForPictureTask(
|
| + int32_t picture_buffer_id,
|
| + // TODO(posciak): (crbug.com/561749) we should normally be able to pass
|
| + // the vector by itself via std::move, but it's not possible to do this
|
| + // if this method is used as a callback.
|
| + std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds);
|
| +
|
| + // Create an EGLImage for the buffer associated with V4L2 |buffer_index| and
|
| + // for |picture_buffer_id|, backed by dmabuf file descriptors in
|
| + // |passed_dmabuf_fds|, taking ownership of them.
|
| + // The buffer should be bound to |texture_id| and is of |size| and format
|
| + // described by |fourcc|.
|
| + void CreateEGLImageFor(
|
| + size_t buffer_index,
|
| + int32_t picture_buffer_id,
|
| + // TODO(posciak): (crbug.com/561749) we should normally be able to pass
|
| + // the vector by itself via std::move, but it's not possible to do this
|
| + // if this method is used as a callback.
|
| + std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds,
|
| + GLuint texture_id,
|
| + const gfx::Size& size,
|
| + uint32_t fourcc);
|
| +
|
| + // Take the EGLImage |egl_image|, created for |picture_buffer_id|, and use it
|
| + // for OutputRecord at |buffer_index|. The buffer is backed by
|
| + // |passed_dmabuf_fds|, and the OutputRecord takes ownership of them.
|
| + void AssignEGLImage(
|
| + size_t buffer_index,
|
| + int32_t picture_buffer_id,
|
| + EGLImageKHR egl_image,
|
| + // TODO(posciak): (crbug.com/561749) we should normally be able to pass
|
| + // the vector by itself via std::move, but it's not possible to do this
|
| + // if this method is used as a callback.
|
| + std::unique_ptr<std::vector<base::ScopedFD>> passed_dmabuf_fds);
|
| +
|
| // Performed on decoder_thread_ as a consequence of poll() on decoder_thread_
|
| // returning an event.
|
| void ServiceDeviceTask();
|
| @@ -232,6 +298,9 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| // Transitional state when we are not decoding any more stream, but are
|
| // performing flush, reset, resolution change or are destroying ourselves.
|
| kIdle,
|
| + // Requested new PictureBuffers via ProvidePictureBuffers(), awaiting
|
| + // AssignPictureBuffers().
|
| + kAwaitingPictureBuffers,
|
| // Error state, set when sending NotifyError to client.
|
| kError,
|
| };
|
| @@ -347,6 +416,8 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| // Decoder state.
|
| State state_;
|
|
|
| + Config::OutputMode output_mode_;
|
| +
|
| // If any of these are true, we are waiting for the device to finish decoding
|
| // all previously-queued frames, so we can finish the flush/reset/surface
|
| // change flows. These can stack.
|
| @@ -380,10 +451,6 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| // The number of pictures that are sent to PictureReady and will be cleared.
|
| int picture_clearing_count_;
|
|
|
| - // Used by the decoder thread to wait for AssignPictureBuffers to arrive
|
| - // to avoid races with potential Reset requests.
|
| - base::WaitableEvent pictures_assigned_;
|
| -
|
| // EGL state
|
| EGLDisplay egl_display_;
|
|
|
|
|