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