1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_
6#define CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_
7
8#include <stdint.h>
9
10#include <map>
11#include <queue>
12
13#include "base/mac/scoped_cftyperef.h"
14#include "base/memory/ref_counted.h"
15#include "base/memory/weak_ptr.h"
16#include "base/message_loop/message_loop.h"
17#include "base/threading/thread.h"
18#include "content/common/gpu/media/vt.h"
19#include "media/filters/h264_parser.h"
20#include "media/video/video_decode_accelerator.h"
21#include "ui/gfx/geometry/size.h"
22#include "ui/gl/gl_context_cgl.h"
23
24namespace base {
25class SingleThreadTaskRunner;
26}  // namespace base
27
28namespace content {
29
30// VideoToolbox.framework implementation of the VideoDecodeAccelerator
31// interface for Mac OS X (currently limited to 10.9+).
32class VTVideoDecodeAccelerator
33    : public media::VideoDecodeAccelerator,
34      public base::NonThreadSafe {
35 public:
36  explicit VTVideoDecodeAccelerator(CGLContextObj cgl_context);
37  virtual ~VTVideoDecodeAccelerator();
38
39  // VideoDecodeAccelerator implementation.
40  virtual bool Initialize(
41      media::VideoCodecProfile profile,
42      Client* client) OVERRIDE;
43  virtual void Decode(const media::BitstreamBuffer& bitstream) OVERRIDE;
44  virtual void AssignPictureBuffers(
45      const std::vector<media::PictureBuffer>& pictures) OVERRIDE;
46  virtual void ReusePictureBuffer(int32_t picture_id) OVERRIDE;
47  virtual void Flush() OVERRIDE;
48  virtual void Reset() OVERRIDE;
49  virtual void Destroy() OVERRIDE;
50  virtual bool CanDecodeOnIOThread() OVERRIDE;
51
52  // Called by OutputThunk() when VideoToolbox finishes decoding a frame.
53  void Output(
54      int32_t bitstream_id,
55      OSStatus status,
56      CVImageBufferRef image_buffer);
57
58 private:
59  struct DecodedFrame {
60    DecodedFrame(int32_t bitstream_id, CVImageBufferRef image_buffer);
61    ~DecodedFrame();
62
63    int32_t bitstream_id;
64    base::ScopedCFTypeRef<CVImageBufferRef> image_buffer;
65  };
66
67  // Actions are the possible types of pending operations, which are queued
68  // by Flush(), Reset(), and Destroy().
69  enum Action {
70    ACTION_FLUSH,
71    ACTION_RESET,
72    ACTION_DESTROY
73  };
74
75  // PendingActions contain the |bitstream_id| of a frame that, once decoded and
76  // sent, a particular |action| should be completed at.
77  struct PendingAction {
78    PendingAction(Action action, int32_t bitstream_id);
79    ~PendingAction();
80
81    Action action;
82    int32_t bitstream_id;
83  };
84
85  // Methods for interacting with VideoToolbox. Run on |decoder_thread_|.
86  void ConfigureDecoder(
87      const std::vector<const uint8_t*>& nalu_data_ptrs,
88      const std::vector<size_t>& nalu_data_sizes);
89  void DecodeTask(const media::BitstreamBuffer);
90  void FlushTask();
91
92  // Methods for interacting with |client_|. Run on |gpu_task_runner_|.
93  void OutputTask(DecodedFrame frame);
94  void SizeChangedTask(gfx::Size coded_size);
95
96  // Send decoded frames up to and including |up_to_bitstream_id|, and return
97  // the last sent |bitstream_id|.
98  int32_t SendPictures(int32_t up_to_bitstream_id);
99
100  // Since VideoToolbox has no reset feature (only flush), and the VDA API
101  // allows Decode() and Flush() calls during a reset operation, it's possible
102  // to have multiple pending actions at once. We handle the fully general case
103  // of an arbitrary sequence of pending actions (in reality, there should
104  // probably be at most one reset and one flush at a time).
105  void QueueAction(Action action);
106
107  // Process queued decoded frames, usually by sending them (unless there
108  // is a pending ACTION_RESET or ACTION_DESTROY, in which case they are
109  // dropped), completing queued actions along the way.
110  void ProcessDecodedFrames();
111
112  // Complete a particular action, by eg. calling NotifyFlushDone().
113  // Warning: Deletes |this| if |action| is ACTION_DESTROY.
114  void CompleteAction(Action action);
115
116  // Complete all actions pending for a particular |bitstream_id|.
117  // Warning: Do not call if there is a pending ACTION_DESTROY.
118  void CompleteActions(int32_t bitstream_id);
119
120  //
121  // GPU thread state.
122  //
123  CGLContextObj cgl_context_;
124  media::VideoDecodeAccelerator::Client* client_;
125  gfx::Size texture_size_;
126  std::queue<PendingAction> pending_actions_;
127  std::queue<int32_t> pending_bitstream_ids_;
128
129  // Texture IDs of pictures.
130  // TODO(sandersd): A single map of structs holding picture data.
131  std::map<int32_t, uint32_t> texture_ids_;
132
133  // Pictures ready to be rendered to.
134  std::queue<int32_t> available_picture_ids_;
135
136  // Decoded frames ready to render.
137  std::queue<DecodedFrame> decoded_frames_;
138
139  // Image buffers kept alive while they are bound to pictures.
140  std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_;
141
142  //
143  // Decoder thread state.
144  //
145  VTDecompressionOutputCallbackRecord callback_;
146  base::ScopedCFTypeRef<CMFormatDescriptionRef> format_;
147  base::ScopedCFTypeRef<VTDecompressionSessionRef> session_;
148  media::H264Parser parser_;
149  gfx::Size coded_size_;
150
151  //
152  // Shared state (set up and torn down on GPU thread).
153  //
154  scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
155
156  // This WeakPtrFactory does not need to be last as its pointers are bound to
157  // the same thread it is destructed on (the GPU thread).
158  base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_;
159
160  // Declared last to ensure that all decoder thread tasks complete before any
161  // state is destructed.
162  base::Thread decoder_thread_;
163
164  DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator);
165};
166
167}  // namespace content
168
169#endif  // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_
170