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); |
}; |