1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdint.h> 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <map> 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <queue> 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/mac/scoped_cftyperef.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/ref_counted.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/memory/weak_ptr.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/message_loop/message_loop.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/threading/thread.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/common/gpu/media/vt.h" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/filters/h264_parser.h" 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "media/video/video_decode_accelerator.h" 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/gfx/geometry/size.h" 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/gl/gl_context_cgl.h" 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace base { 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass SingleThreadTaskRunner; 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace base 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace content { 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// VideoToolbox.framework implementation of the VideoDecodeAccelerator 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// interface for Mac OS X (currently limited to 10.9+). 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class VTVideoDecodeAccelerator 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : public media::VideoDecodeAccelerator, 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public base::NonThreadSafe { 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) explicit VTVideoDecodeAccelerator(CGLContextObj cgl_context); 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~VTVideoDecodeAccelerator(); 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // VideoDecodeAccelerator implementation. 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual bool Initialize( 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::VideoCodecProfile profile, 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Client* client) OVERRIDE; 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void Decode(const media::BitstreamBuffer& bitstream) OVERRIDE; 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void AssignPictureBuffers( 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::vector<media::PictureBuffer>& pictures) OVERRIDE; 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void ReusePictureBuffer(int32_t picture_id) OVERRIDE; 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void Flush() OVERRIDE; 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void Reset() OVERRIDE; 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual void Destroy() OVERRIDE; 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual bool CanDecodeOnIOThread() OVERRIDE; 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Called by OutputThunk() when VideoToolbox finishes decoding a frame. 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void Output( 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int32_t bitstream_id, 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch OSStatus status, 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CVImageBufferRef image_buffer); 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) struct DecodedFrame { 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DecodedFrame(int32_t bitstream_id, CVImageBufferRef image_buffer); 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ~DecodedFrame(); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int32_t bitstream_id; 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::ScopedCFTypeRef<CVImageBufferRef> image_buffer; 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Actions are the possible types of pending operations, which are queued 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // by Flush(), Reset(), and Destroy(). 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci enum Action { 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACTION_FLUSH, 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACTION_RESET, 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ACTION_DESTROY 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // PendingActions contain the |bitstream_id| of a frame that, once decoded and 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // sent, a particular |action| should be completed at. 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci struct PendingAction { 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PendingAction(Action action, int32_t bitstream_id); 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ~PendingAction(); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Action action; 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32_t bitstream_id; 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }; 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Methods for interacting with VideoToolbox. Run on |decoder_thread_|. 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void ConfigureDecoder( 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<const uint8_t*>& nalu_data_ptrs, 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<size_t>& nalu_data_sizes); 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void DecodeTask(const media::BitstreamBuffer); 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void FlushTask(); 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Methods for interacting with |client_|. Run on |gpu_task_runner_|. 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void OutputTask(DecodedFrame frame); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void SizeChangedTask(gfx::Size coded_size); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Send decoded frames up to and including |up_to_bitstream_id|, and return 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the last sent |bitstream_id|. 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32_t SendPictures(int32_t up_to_bitstream_id); 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Since VideoToolbox has no reset feature (only flush), and the VDA API 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // allows Decode() and Flush() calls during a reset operation, it's possible 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to have multiple pending actions at once. We handle the fully general case 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // of an arbitrary sequence of pending actions (in reality, there should 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // probably be at most one reset and one flush at a time). 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void QueueAction(Action action); 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Process queued decoded frames, usually by sending them (unless there 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // is a pending ACTION_RESET or ACTION_DESTROY, in which case they are 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // dropped), completing queued actions along the way. 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void ProcessDecodedFrames(); 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Complete a particular action, by eg. calling NotifyFlushDone(). 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Warning: Deletes |this| if |action| is ACTION_DESTROY. 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void CompleteAction(Action action); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Complete all actions pending for a particular |bitstream_id|. 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Warning: Do not call if there is a pending ACTION_DESTROY. 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void CompleteActions(int32_t bitstream_id); 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // GPU thread state. 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CGLContextObj cgl_context_; 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) media::VideoDecodeAccelerator::Client* client_; 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Size texture_size_; 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::queue<PendingAction> pending_actions_; 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::queue<int32_t> pending_bitstream_ids_; 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Texture IDs of pictures. 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(sandersd): A single map of structs holding picture data. 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::map<int32_t, uint32_t> texture_ids_; 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Pictures ready to be rendered to. 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::queue<int32_t> available_picture_ids_; 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Decoded frames ready to render. 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::queue<DecodedFrame> decoded_frames_; 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Image buffers kept alive while they are bound to pictures. 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_; 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Decoder thread state. 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VTDecompressionOutputCallbackRecord callback_; 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ScopedCFTypeRef<CMFormatDescriptionRef> format_; 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ScopedCFTypeRef<VTDecompressionSessionRef> session_; 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media::H264Parser parser_; 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Size coded_size_; 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Shared state (set up and torn down on GPU thread). 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This WeakPtrFactory does not need to be last as its pointers are bound to 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the same thread it is destructed on (the GPU thread). 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_; 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Declared last to ensure that all decoder thread tasks complete before any 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // state is destructed. 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Thread decoder_thread_; 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator); 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace content 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ 170