| Index: content/common/gpu/media/vt_video_decode_accelerator.h
|
| diff --git a/content/common/gpu/media/vt_video_decode_accelerator.h b/content/common/gpu/media/vt_video_decode_accelerator.h
|
| index 5aa4f7051c7cabb40c36587263e72cff71f86c41..6dc50feac8e8970022c86f96431115bc8b282774 100644
|
| --- a/content/common/gpu/media/vt_video_decode_accelerator.h
|
| +++ b/content/common/gpu/media/vt_video_decode_accelerator.h
|
| @@ -11,10 +11,11 @@
|
| #include <queue>
|
|
|
| #include "base/mac/scoped_cftyperef.h"
|
| -#include "base/memory/ref_counted.h"
|
| +#include "base/memory/linked_ptr.h"
|
| #include "base/memory/weak_ptr.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/threading/thread.h"
|
| +#include "base/threading/thread_checker.h"
|
| #include "content/common/gpu/media/vt.h"
|
| #include "media/filters/h264_parser.h"
|
| #include "media/video/video_decode_accelerator.h"
|
| @@ -29,9 +30,7 @@ namespace content {
|
|
|
| // VideoToolbox.framework implementation of the VideoDecodeAccelerator
|
| // interface for Mac OS X (currently limited to 10.9+).
|
| -class VTVideoDecodeAccelerator
|
| - : public media::VideoDecodeAccelerator,
|
| - public base::NonThreadSafe {
|
| +class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator {
|
| public:
|
| explicit VTVideoDecodeAccelerator(
|
| CGLContextObj cgl_context,
|
| @@ -51,85 +50,76 @@ class VTVideoDecodeAccelerator
|
|
|
| // Called by OutputThunk() when VideoToolbox finishes decoding a frame.
|
| void Output(
|
| - int32_t bitstream_id,
|
| + void* source_frame_refcon,
|
| OSStatus status,
|
| CVImageBufferRef image_buffer);
|
|
|
| private:
|
| - struct DecodedFrame {
|
| - DecodedFrame(int32_t bitstream_id, CVImageBufferRef image_buffer);
|
| - ~DecodedFrame();
|
| -
|
| - int32_t bitstream_id;
|
| - base::ScopedCFTypeRef<CVImageBufferRef> image_buffer;
|
| + enum State {
|
| + STATE_DECODING,
|
| + STATE_ERROR,
|
| + STATE_DESTROYING,
|
| };
|
|
|
| - // Actions are the possible types of pending operations, which are queued
|
| - // by Flush(), Reset(), and Destroy().
|
| - enum Action {
|
| - ACTION_FLUSH,
|
| - ACTION_RESET,
|
| - ACTION_DESTROY
|
| + enum TaskType {
|
| + TASK_FRAME,
|
| + TASK_FLUSH,
|
| + TASK_RESET,
|
| + TASK_DESTROY,
|
| };
|
|
|
| - // PendingActions contain the |bitstream_id| of a frame that, once decoded and
|
| - // sent, a particular |action| should be completed at.
|
| - struct PendingAction {
|
| - PendingAction(Action action, int32_t bitstream_id);
|
| - ~PendingAction();
|
| + struct Frame {
|
| + Frame(int32_t bitstream_id);
|
| + ~Frame();
|
|
|
| - Action action;
|
| int32_t bitstream_id;
|
| + base::ScopedCFTypeRef<CVImageBufferRef> image;
|
| + // TODO(sandersd): visible_rect.
|
| + gfx::Size coded_size;
|
| + };
|
| +
|
| + struct Task {
|
| + Task(TaskType type);
|
| + ~Task();
|
| +
|
| + TaskType type;
|
| + linked_ptr<Frame> frame;
|
| };
|
|
|
| + //
|
| // Methods for interacting with VideoToolbox. Run on |decoder_thread_|.
|
| - bool ConfigureDecoder(
|
| - const std::vector<const uint8_t*>& nalu_data_ptrs,
|
| - const std::vector<size_t>& nalu_data_sizes);
|
| - void DecodeTask(const media::BitstreamBuffer&);
|
| - void FlushTask();
|
| - void DropBitstream(int32_t bitstream_id);
|
| + //
|
| + // Set up VideoToolbox using the current SPS and PPS. Returns true or calls
|
| + // NotifyError() before returning false.
|
| + bool ConfigureDecoder();
|
| +
|
| + // Wait for VideoToolbox to output all pending frames. Returns true or calls
|
| + // NotifyError() before returning false.
|
| + bool FinishDelayedFrames();
|
| +
|
| + // |frame| is owned by |pending_frames_|.
|
| + void DecodeTask(const media::BitstreamBuffer&, Frame* frame);
|
| + void DecodeDone(Frame* frame);
|
|
|
| + //
|
| // Methods for interacting with |client_|. Run on |gpu_task_runner_|.
|
| - void OutputTask(DecodedFrame frame);
|
| + //
|
| void NotifyError(Error error);
|
|
|
| - // Send decoded frames up to and including |up_to_bitstream_id|, and return
|
| - // the last sent |bitstream_id|.
|
| - int32_t SendPictures(int32_t up_to_bitstream_id);
|
| -
|
| - // Internal helper for SendPictures(): Drop frames with no image data up to
|
| - // a particular bitstream ID, so that if there is still a frame in the queue
|
| - // when this function returns, it is guaranteed to have image data, and thus
|
| - // it is time to set up the GPU context. Returns the last bitstream ID that
|
| - // was dropped, or |last_sent_bitstream_id| if no frames were dropped.
|
| - int32_t ProcessDroppedFrames(
|
| - int32_t last_sent_bitstream_id,
|
| - int32_t up_to_bitstream_id);
|
| -
|
| - // Internal helper for SendPictures(): Check if the next frame has a size
|
| - // different from the current picture buffers, and request new ones if so.
|
| - void ProcessSizeChangeIfNeeded();
|
| -
|
| - // Since VideoToolbox has no reset feature (only flush), and the VDA API
|
| - // allows Decode() and Flush() calls during a reset operation, it's possible
|
| - // to have multiple pending actions at once. We handle the fully general case
|
| - // of an arbitrary sequence of pending actions (in reality, there should
|
| - // probably be at most one reset and one flush at a time).
|
| - void QueueAction(Action action);
|
| -
|
| - // Process queued decoded frames, usually by sending them (unless there
|
| - // is a pending ACTION_RESET or ACTION_DESTROY, in which case they are
|
| - // dropped), completing queued actions along the way.
|
| - void ProcessDecodedFrames();
|
| -
|
| - // Complete a particular action, by eg. calling NotifyFlushDone().
|
| - // Warning: Deletes |this| if |action| is ACTION_DESTROY.
|
| - void CompleteAction(Action action);
|
| -
|
| - // Complete all actions pending for a particular |bitstream_id|.
|
| - // Warning: Do not call if there is a pending ACTION_DESTROY.
|
| - void CompleteActions(int32_t bitstream_id);
|
| + // |type| is the type of task that the flush will complete, one of TASK_FLUSH,
|
| + // TASK_RESET, or TASK_DESTROY.
|
| + void QueueFlush(TaskType type);
|
| + void FlushTask(TaskType type);
|
| + void FlushDone(TaskType type);
|
| +
|
| + // Attempt to make progress on |pending_tasks_|.
|
| + void ProcessTasks();
|
| +
|
| + // These methods returns true if the task was completed, false if it couldn't
|
| + // be completed yet.
|
| + bool ProcessTask(const Task& task);
|
| + bool ProcessFrame(const Frame& frame);
|
| + bool SendFrame(const Frame& frame);
|
|
|
| //
|
| // GPU thread state.
|
| @@ -137,21 +127,24 @@ class VTVideoDecodeAccelerator
|
| CGLContextObj cgl_context_;
|
| base::Callback<bool(void)> make_context_current_;
|
| media::VideoDecodeAccelerator::Client* client_;
|
| + State state_;
|
| +
|
| + // Queue of pending flush tasks. This is used to drop frames when a reset
|
| + // is pending.
|
| + std::queue<TaskType> pending_flush_tasks_;
|
|
|
| - // client_->NotifyError() called.
|
| - bool has_error_;
|
| + // Queue of tasks to complete in the GPU thread.
|
| + std::queue<Task> pending_tasks_;
|
|
|
| // Size of assigned picture buffers.
|
| gfx::Size picture_size_;
|
|
|
| - // Queue of actions so that we can quickly discover what the next action will
|
| - // be; this is useful because we are dropping all frames when the next action
|
| - // is ACTION_RESET or ACTION_DESTROY.
|
| - std::queue<PendingAction> pending_actions_;
|
| + // Queue of frames that have not yet been decoded; maintains ownership of the
|
| + // Frame objects while they flow through VideoToolbox.
|
| + std::queue<linked_ptr<Frame>> pending_frames_;
|
|
|
| - // Queue of bitstreams that have not yet been decoded. This is mostly needed
|
| - // to be sure we free them all in Destroy().
|
| - std::queue<int32_t> pending_bitstream_ids_;
|
| + // Set of assigned bitstream IDs, so that Destroy() can release them all.
|
| + std::set<int32_t> assigned_bitstream_ids_;
|
|
|
| // All picture buffers assigned to us. Used to check if reused picture buffers
|
| // should be added back to the available list or released. (They are not
|
| @@ -164,9 +157,6 @@ class VTVideoDecodeAccelerator
|
| // Pictures ready to be rendered to.
|
| std::vector<int32_t> available_picture_ids_;
|
|
|
| - // Decoded frames ready to render.
|
| - std::queue<DecodedFrame> decoded_frames_;
|
| -
|
| // Image buffers kept alive while they are bound to pictures.
|
| std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_;
|
|
|
| @@ -177,6 +167,7 @@ class VTVideoDecodeAccelerator
|
| base::ScopedCFTypeRef<CMFormatDescriptionRef> format_;
|
| base::ScopedCFTypeRef<VTDecompressionSessionRef> session_;
|
| media::H264Parser parser_;
|
| + gfx::Size coded_size_;
|
|
|
| std::vector<uint8_t> last_sps_;
|
| std::vector<uint8_t> last_spsext_;
|
| @@ -186,15 +177,14 @@ class VTVideoDecodeAccelerator
|
| // Shared state (set up and torn down on GPU thread).
|
| //
|
| scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
|
| + base::ThreadChecker gpu_thread_checker_;
|
| + base::WeakPtr<VTVideoDecodeAccelerator> weak_this_;
|
| + base::Thread decoder_thread_;
|
|
|
| - // This WeakPtrFactory does not need to be last as its pointers are bound to
|
| - // the same thread it is destructed on (the GPU thread).
|
| + // Declared last to ensure that all weak pointers are invalidated before
|
| + // other destructors run.
|
| base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_;
|
|
|
| - // Declared last to ensure that all decoder thread tasks complete before any
|
| - // state is destructed.
|
| - base::Thread decoder_thread_;
|
| -
|
| DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator);
|
| };
|
|
|
|
|