| 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
|
| deleted file mode 100644
|
| index f917e1a4e3bcc7a3cefb63412bb9fe8c7553d14f..0000000000000000000000000000000000000000
|
| --- a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
|
| +++ /dev/null
|
| @@ -1,473 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#ifndef CONTENT_COMMON_GPU_MEDIA_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
|
| -#define CONTENT_COMMON_GPU_MEDIA_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
|
| -
|
| -#include <linux/videodev2.h>
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include <memory>
|
| -#include <queue>
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/macros.h"
|
| -#include "base/memory/linked_ptr.h"
|
| -#include "base/memory/ref_counted.h"
|
| -#include "base/memory/weak_ptr.h"
|
| -#include "base/synchronization/waitable_event.h"
|
| -#include "base/threading/thread.h"
|
| -#include "content/common/content_export.h"
|
| -#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
|
| -#include "content/common/gpu/media/h264_decoder.h"
|
| -#include "content/common/gpu/media/v4l2_device.h"
|
| -#include "content/common/gpu/media/vp8_decoder.h"
|
| -#include "media/video/video_decode_accelerator.h"
|
| -
|
| -namespace content {
|
| -
|
| -// An implementation of VideoDecodeAccelerator that utilizes the V4L2 slice
|
| -// level codec API for decoding. The slice level API provides only a low-level
|
| -// decoding functionality and requires userspace to provide support for parsing
|
| -// the input stream and managing decoder state across frames.
|
| -class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
|
| - : public media::VideoDecodeAccelerator {
|
| - public:
|
| - class V4L2DecodeSurface;
|
| -
|
| - V4L2SliceVideoDecodeAccelerator(
|
| - const scoped_refptr<V4L2Device>& device,
|
| - EGLDisplay egl_display,
|
| - const GetGLContextCallback& get_gl_context_cb,
|
| - const MakeGLContextCurrentCallback& make_context_current_cb);
|
| - ~V4L2SliceVideoDecodeAccelerator() override;
|
| -
|
| - // media::VideoDecodeAccelerator implementation.
|
| - bool Initialize(const Config& config, Client* client) override;
|
| - 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;
|
| - void Destroy() override;
|
| - bool TryToSetupDecodeOnSeparateThread(
|
| - 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();
|
| -
|
| - private:
|
| - class V4L2H264Accelerator;
|
| - class V4L2VP8Accelerator;
|
| -
|
| - // Record for input buffers.
|
| - struct InputRecord {
|
| - InputRecord();
|
| - int32_t input_id;
|
| - void* address;
|
| - size_t length;
|
| - size_t bytes_used;
|
| - bool at_device;
|
| - };
|
| -
|
| - // Record for output buffers.
|
| - struct OutputRecord {
|
| - OutputRecord();
|
| - 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;
|
| - };
|
| -
|
| - // See http://crbug.com/255116.
|
| - // Input bitstream buffer size for up to 1080p streams.
|
| - const size_t kInputBufferMaxSizeFor1080p = 1024 * 1024;
|
| - // Input bitstream buffer size for up to 4k streams.
|
| - const size_t kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p;
|
| - const size_t kNumInputBuffers = 16;
|
| -
|
| - // Input format V4L2 fourccs this class supports.
|
| - static const uint32_t supported_input_fourccs_[];
|
| -
|
| - //
|
| - // Below methods are used by accelerator implementations.
|
| - //
|
| - // Append slice data in |data| of size |size| to pending hardware
|
| - // input buffer with |index|. This buffer will be submitted for decode
|
| - // on the next DecodeSurface(). Return true on success.
|
| - bool SubmitSlice(int index, const uint8_t* data, size_t size);
|
| -
|
| - // Submit controls in |ext_ctrls| to hardware. Return true on success.
|
| - bool SubmitExtControls(struct v4l2_ext_controls* ext_ctrls);
|
| -
|
| - // Decode of |dec_surface| is ready to be submitted and all codec-specific
|
| - // settings are set in hardware.
|
| - void DecodeSurface(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
|
| -
|
| - // |dec_surface| is ready to be outputted once decode is finished.
|
| - // This can be called before decode is actually done in hardware, and this
|
| - // method is responsible for maintaining the ordering, i.e. the surfaces will
|
| - // be outputted in the same order as SurfaceReady calls. To do so, the
|
| - // surfaces are put on decoder_display_queue_ and sent to output in that
|
| - // order once all preceding surfaces are sent.
|
| - void SurfaceReady(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
|
| -
|
| - //
|
| - // Internal methods of this class.
|
| - //
|
| - // Recycle a V4L2 input buffer with |index| after dequeuing from device.
|
| - void ReuseInputBuffer(int index);
|
| -
|
| - // Recycle V4L2 output buffer with |index|. Used as surface release callback.
|
| - void ReuseOutputBuffer(int index);
|
| -
|
| - // Queue a |dec_surface| to device for decoding.
|
| - void Enqueue(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
|
| -
|
| - // Dequeue any V4L2 buffers available and process.
|
| - void Dequeue();
|
| -
|
| - // V4L2 QBUF helpers.
|
| - bool EnqueueInputRecord(int index, uint32_t config_store);
|
| - bool EnqueueOutputRecord(int index);
|
| -
|
| - // Set input and output formats in hardware.
|
| - bool SetupFormats();
|
| -
|
| - // Create input and output buffers.
|
| - bool CreateInputBuffers();
|
| - bool CreateOutputBuffers();
|
| -
|
| - // Destroy input buffers.
|
| - void DestroyInputBuffers();
|
| -
|
| - // Destroy output buffers and release associated resources (textures,
|
| - // EGLImages). If |dismiss| is true, also dismissing the associated
|
| - // PictureBuffers.
|
| - bool DestroyOutputs(bool dismiss);
|
| -
|
| - // Used by DestroyOutputs.
|
| - bool DestroyOutputBuffers();
|
| -
|
| - // Dismiss all |picture_buffer_ids| via Client::DismissPictureBuffer()
|
| - // and signal |done| after finishing.
|
| - void DismissPictures(const std::vector<int32_t>& picture_buffer_ids,
|
| - base::WaitableEvent* done);
|
| -
|
| - // Task to finish initialization on decoder_thread_.
|
| - void InitializeTask();
|
| -
|
| - 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
|
| - // InitiateFlush() directly. Otherwise, we push a dummy BitstreamBufferRef
|
| - // onto the decoder_input_queue_ to schedule a flush. When we reach it later
|
| - // on, we call InitiateFlush() to perform it at the correct time.
|
| - void FlushTask();
|
| - // 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();
|
| - // 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, reset the decoder and mark us as pending for reset.
|
| - void ResetTask();
|
| - // 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();
|
| -
|
| - // Schedule poll if we have any buffers queued and the poll thread
|
| - // is not stopped (on surface set change).
|
| - void SchedulePollIfNeeded();
|
| -
|
| - // Attempt to start/stop device_poll_thread_.
|
| - bool StartDevicePoll();
|
| - bool StopDevicePoll(bool keep_input_state);
|
| -
|
| - // Ran on device_poll_thread_ to wait for device events.
|
| - void DevicePollTask(bool poll_device);
|
| -
|
| - enum State {
|
| - // We are in this state until Initialize() returns successfully.
|
| - // We can't post errors to the client in this state yet.
|
| - kUninitialized,
|
| - // Initialize() returned successfully.
|
| - kInitialized,
|
| - // This state allows making progress decoding more input stream.
|
| - kDecoding,
|
| - // 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,
|
| - };
|
| -
|
| - // Buffer id for flush buffer, queued by FlushTask().
|
| - const int kFlushBufferId = -2;
|
| -
|
| - // Handler for Decode() on decoder_thread_.
|
| - void DecodeTask(const media::BitstreamBuffer& bitstream_buffer);
|
| -
|
| - // Schedule a new DecodeBufferTask if we are decoding.
|
| - void ScheduleDecodeBufferTaskIfNeeded();
|
| -
|
| - // Main decoder loop. Keep decoding the current buffer in decoder_, asking
|
| - // for more stream via TrySetNewBistreamBuffer() if decoder_ requests so,
|
| - // and handle other returns from it appropriately.
|
| - void DecodeBufferTask();
|
| -
|
| - // Check decoder_input_queue_ for any available buffers to decode and
|
| - // set the decoder_current_bitstream_buffer_ to the next buffer if one is
|
| - // available, taking it off the queue. Also set the current stream pointer
|
| - // in decoder_, and return true.
|
| - // Return false if no buffers are pending on decoder_input_queue_.
|
| - bool TrySetNewBistreamBuffer();
|
| -
|
| - // Auto-destruction reference for EGLSync (for message-passing).
|
| - struct EGLSyncKHRRef;
|
| - void ReusePictureBufferTask(int32_t picture_buffer_id,
|
| - std::unique_ptr<EGLSyncKHRRef> egl_sync_ref);
|
| -
|
| - // Called to actually send |dec_surface| to the client, after it is decoded
|
| - // preserving the order in which it was scheduled via SurfaceReady().
|
| - void OutputSurface(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
|
| -
|
| - // Goes over the |decoder_display_queue_| and sends all buffers from the
|
| - // front of the queue that are already decoded to the client, in order.
|
| - void TryOutputSurfaces();
|
| -
|
| - // Creates a new decode surface or returns nullptr if one is not available.
|
| - scoped_refptr<V4L2DecodeSurface> CreateSurface();
|
| -
|
| - // Send decoded pictures to PictureReady.
|
| - void SendPictureReady();
|
| -
|
| - // Callback that indicates a picture has been cleared.
|
| - void PictureCleared();
|
| -
|
| - size_t input_planes_count_;
|
| - size_t output_planes_count_;
|
| -
|
| - // GPU Child thread task runner.
|
| - const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
|
| -
|
| - // Task runner Decode() and PictureReady() run on.
|
| - scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_;
|
| -
|
| - // WeakPtr<> pointing to |this| for use in posting tasks from the decoder or
|
| - // device worker threads back to the child thread.
|
| - base::WeakPtr<V4L2SliceVideoDecodeAccelerator> weak_this_;
|
| -
|
| - // To expose client callbacks from VideoDecodeAccelerator.
|
| - // NOTE: all calls to these objects *MUST* be executed on
|
| - // child_task_runner_.
|
| - std::unique_ptr<base::WeakPtrFactory<VideoDecodeAccelerator::Client>>
|
| - client_ptr_factory_;
|
| - base::WeakPtr<VideoDecodeAccelerator::Client> client_;
|
| - // Callbacks to |decode_client_| must be executed on |decode_task_runner_|.
|
| - base::WeakPtr<Client> decode_client_;
|
| -
|
| - // V4L2 device in use.
|
| - scoped_refptr<V4L2Device> device_;
|
| -
|
| - // Thread to communicate with the device on.
|
| - base::Thread decoder_thread_;
|
| - scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_;
|
| -
|
| - // Thread used to poll the device for events.
|
| - base::Thread device_poll_thread_;
|
| -
|
| - // Input queue state.
|
| - bool input_streamon_;
|
| - // Number of input buffers enqueued to the device.
|
| - int input_buffer_queued_count_;
|
| - // Input buffers ready to use; LIFO since we don't care about ordering.
|
| - std::list<int> free_input_buffers_;
|
| - // Mapping of int index to an input buffer record.
|
| - std::vector<InputRecord> input_buffer_map_;
|
| -
|
| - // Output queue state.
|
| - bool output_streamon_;
|
| - // Number of output buffers enqueued to the device.
|
| - int output_buffer_queued_count_;
|
| - // Output buffers ready to use.
|
| - std::list<int> free_output_buffers_;
|
| - // Mapping of int index to an output buffer record.
|
| - std::vector<OutputRecord> output_buffer_map_;
|
| -
|
| - media::VideoCodecProfile video_profile_;
|
| - uint32_t output_format_fourcc_;
|
| - gfx::Size visible_size_;
|
| - gfx::Size coded_size_;
|
| -
|
| - struct BitstreamBufferRef;
|
| - // Input queue of stream buffers coming from the client.
|
| - std::queue<linked_ptr<BitstreamBufferRef>> decoder_input_queue_;
|
| - // BitstreamBuffer currently being processed.
|
| - std::unique_ptr<BitstreamBufferRef> decoder_current_bitstream_buffer_;
|
| -
|
| - // Queue storing decode surfaces ready to be output as soon as they are
|
| - // decoded. The surfaces must be output in order they are queued.
|
| - std::queue<scoped_refptr<V4L2DecodeSurface>> decoder_display_queue_;
|
| -
|
| - // 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.
|
| - bool decoder_flushing_;
|
| - bool decoder_resetting_;
|
| - bool surface_set_change_pending_;
|
| -
|
| - // Hardware accelerators.
|
| - // TODO(posciak): Try to have a superclass here if possible.
|
| - std::unique_ptr<V4L2H264Accelerator> h264_accelerator_;
|
| - std::unique_ptr<V4L2VP8Accelerator> vp8_accelerator_;
|
| -
|
| - // Codec-specific software decoder in use.
|
| - std::unique_ptr<AcceleratedVideoDecoder> decoder_;
|
| -
|
| - // Surfaces queued to device to keep references to them while decoded.
|
| - using V4L2DecodeSurfaceByOutputId =
|
| - std::map<int, scoped_refptr<V4L2DecodeSurface>>;
|
| - V4L2DecodeSurfaceByOutputId surfaces_at_device_;
|
| -
|
| - // Surfaces sent to client to keep references to them while displayed.
|
| - using V4L2DecodeSurfaceByPictureBufferId =
|
| - std::map<int32_t, scoped_refptr<V4L2DecodeSurface>>;
|
| - V4L2DecodeSurfaceByPictureBufferId surfaces_at_display_;
|
| -
|
| - // Record for decoded pictures that can be sent to PictureReady.
|
| - struct PictureRecord;
|
| - // Pictures that are ready but not sent to PictureReady yet.
|
| - std::queue<PictureRecord> pending_picture_ready_;
|
| -
|
| - // The number of pictures that are sent to PictureReady and will be cleared.
|
| - int picture_clearing_count_;
|
| -
|
| - // EGL state
|
| - EGLDisplay egl_display_;
|
| -
|
| - // Callback to get current GLContext.
|
| - GetGLContextCallback get_gl_context_cb_;
|
| - // Callback to set the correct gl context.
|
| - MakeGLContextCurrentCallback make_context_current_cb_;
|
| -
|
| - // The WeakPtrFactory for |weak_this_|.
|
| - base::WeakPtrFactory<V4L2SliceVideoDecodeAccelerator> weak_this_factory_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(V4L2SliceVideoDecodeAccelerator);
|
| -};
|
| -
|
| -class V4L2H264Picture;
|
| -class V4L2VP8Picture;
|
| -
|
| -} // namespace content
|
| -
|
| -#endif // CONTENT_COMMON_GPU_MEDIA_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
|
|
|