OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 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 // This file contains an implementation of VaapiDelegate, used by | |
6 // VaapiVideoDecodeAccelerator and VaapiH264Decoder to interface | |
7 // with libva (VA-API library for hardware video decode). | |
8 | |
9 #ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_DELEGATE_H_ | |
10 #define CONTENT_COMMON_GPU_MEDIA_VAAPI_DELEGATE_H_ | |
11 | |
12 #include "base/callback.h" | |
13 #include "base/memory/ref_counted.h" | |
14 #include "base/synchronization/lock.h" | |
15 #include "media/base/video_decoder_config.h" | |
16 #include "third_party/libva/va/va.h" | |
17 #include "third_party/libva/va/va_x11.h" | |
18 #include "ui/gfx/size.h" | |
19 | |
20 namespace content { | |
21 | |
22 // This class handles VA-API calls and ensures proper locking of VA-API calls | |
23 // to libva, the userspace shim to the HW decoder driver. libva is not | |
24 // thread-safe, so we have to perform locking ourselves. This class is fully | |
25 // synchronous and its methods can be called from any thread and may wait on | |
26 // the va_lock_ while other, concurrent calls run. | |
27 // | |
28 // This class is responsible for managing VAAPI connection, contexts and state. | |
29 // It is also responsible for managing and freeing VABuffers (not VASurfaces), | |
30 // which are used to queue decode parameters and slice data to the HW decoder, | |
31 // as well as underlying memory for VASurfaces themselves. | |
32 class VaapiDelegate : public base::RefCountedThreadSafe<VaapiDelegate> { | |
Ami GONE FROM CHROMIUM
2013/05/22 23:59:47
please rename to wrapper. Delegate means a differ
Pawel Osciak
2013/05/24 01:46:39
Done. Lunch topic next time I visit KIR? ;)
| |
33 public: | |
34 // |report_error_to_uma_cb| will be used to report errors for UMA purposes, | |
Ami GONE FROM CHROMIUM
2013/05/22 23:59:47
nit: with the gloriously informative new name, thi
Pawel Osciak
2013/05/24 01:46:39
Done.
| |
35 // independently from reporting errors to clients. | |
36 static scoped_refptr<VaapiDelegate> Create( | |
37 media::VideoCodecProfile profile, | |
38 Display* x_display, | |
39 const base::Closure& report_error_to_uma_cb); | |
40 | |
41 // Create |num_surfaces| backing surfaces in driver for VASurfaces, each | |
42 // of size |size|. Returns true when successful, with the created IDs in | |
43 // |va_surfaces| to be managed and later wrapped in VASurfaces. | |
44 // The client must DestroySurfaces() each time before calling this method | |
45 // again to free the allocated surfaces first, but is not required to do so | |
46 // at destruction time, as this will be done automatically from | |
47 // the destructor. | |
48 bool CreateSurfaces(gfx::Size size, | |
49 size_t num_surfaces, | |
50 std::vector<VASurfaceID>* va_surfaces); | |
51 | |
52 // Free all memory allocated in CreateSurfaces. | |
53 void DestroySurfaces(); | |
54 | |
55 // Submit parameters or slice data of |va_buffer_type|, copying them from | |
56 // |buffer| of size |size|, into HW decoder. The data in |buffer| is no | |
57 // longer needed and can be freed after this method returns. | |
58 // Data submitted via this method awaits in the HW decoder until | |
59 // DecodeAndDestroyPendingBuffers is called to execute or | |
60 // DestroyPendingBuffers is used to cancel a pending decode. | |
61 bool SubmitBuffer(VABufferType va_buffer_type, size_t size, void* buffer); | |
62 | |
63 // Cancel and destroy all buffers queued to the HW decoder via SubmitBuffer. | |
64 // Useful when a pending decode is to be cancelled (on reset or error). | |
65 void DestroyPendingBuffers(); | |
66 | |
67 // Execute decode in hardware and destroy pending buffers. | |
Ami GONE FROM CHROMIUM
2013/05/22 23:59:47
what does a false return value mean? more data ne
Pawel Osciak
2013/05/24 01:46:39
Done.
| |
68 bool DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id); | |
69 | |
70 | |
71 // Put data from |va_surface_id| into |x_pixmap| of size |size|, | |
72 // converting/scaling to it. | |
73 bool PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | |
74 Pixmap x_pixmap, | |
75 gfx::Size dest_size); | |
Ami GONE FROM CHROMIUM
2013/05/22 23:59:47
Is it ever the case that the pixmap & the surface
Pawel Osciak
2013/05/24 01:46:39
Not for us, but it's allowed, it'd be scaled then.
| |
76 | |
77 // Do any necessary initialization before the sandbox is enabled. | |
78 static void PreSandboxInitialization(); | |
79 | |
80 private: | |
81 friend class base::RefCountedThreadSafe<VaapiDelegate>; | |
82 VaapiDelegate(); | |
83 ~VaapiDelegate(); | |
84 | |
85 bool Initialize(media::VideoCodecProfile profile, | |
86 Display* x_display, | |
87 const base::Closure& report_error__to_uma_cb); | |
88 void Deinitialize(); | |
89 | |
90 bool SubmitDecode(VASurfaceID va_surface_id); | |
Ami GONE FROM CHROMIUM
2013/05/22 23:59:47
ditto q about meaning of return false.
Pawel Osciak
2013/05/24 01:46:39
Done.
| |
91 | |
92 // Lazily initialize static data after sandbox is enabled. Return false on | |
93 // init failure. | |
94 static bool PostSandboxInitialization(); | |
95 | |
96 // Libva is not thread safe, so we have to do locking for it ourselves. | |
97 // This lock is to be taken for the duration of all VA-API calls and for | |
98 // the entire decode execution sequence in DecodeAndDestroyPendingBuffers(). | |
99 base::Lock va_lock_; | |
100 | |
101 // Allocated ids for VASurfaces. | |
102 std::vector<VASurfaceID> va_surface_ids_; | |
103 | |
104 // VA handles. | |
105 // Both valid after successful Initialize() and until Deinitialize(). | |
106 VADisplay va_display_; | |
107 VAConfigID va_config_id_; | |
108 // Created for the current set of va_surface_ids_ in CreateSurfaces() and | |
109 // valid until DestroySurfaces(). | |
110 VAContextID va_context_id_; | |
111 | |
112 // Data queued up for HW decoder, to be committed on next HW decode. | |
113 std::vector<VABufferID> pending_slice_bufs_; | |
114 std::vector<VABufferID> pending_va_bufs_; | |
115 | |
116 // Called to report decoding errors to UMA. Errors to clients are reported via | |
117 // return values from public methods. | |
118 base::Closure report_error_to_uma_cb_; | |
119 | |
120 // Has static initialization of pre-sandbox components completed successfully? | |
121 static bool pre_sandbox_init_done_; | |
122 | |
123 DISALLOW_COPY_AND_ASSIGN(VaapiDelegate); | |
124 }; | |
125 | |
Ami GONE FROM CHROMIUM
2013/05/22 23:59:47
nit: add an extra \n I think.
Pawel Osciak
2013/05/24 01:46:39
Moved out.
| |
126 // A VA-API-specific decode surface used by VaapiH264Decoder to decode into | |
127 // and use as reference for decoding other surfaces. It is also handed by the | |
128 // decoder to VaapiVideoDecodeAccelerator when the contents of the surface are | |
129 // ready and should be displayed. VAVDA converts the surface contents into an | |
130 // X Pixmap bound to a texture for display and releases its reference to it. | |
131 // Decoder releases its references to the surface when it's done decoding and | |
132 // using it as reference. Note that a surface may still be used for reference | |
133 // after it's been sent to output and also after it is no longer used by VAVDA. | |
134 // Thus, the surface can be in use by both VAVDA and the Decoder at the same | |
135 // time, or by either of them, with the restriction that VAVDA will never get | |
136 // the surface until the contents are ready, and it is guaranteed that the | |
137 // contents will not change after that. | |
138 // When both the decoder and VAVDA release their references to the surface, | |
139 // it is freed and the release callback is executed to put the surface back | |
140 // into available surfaces pool, which is managed externally. | |
141 // | |
142 // VASurfaceID is allocated in VaapiDelegate. | |
143 // | | |
144 // +----->| | |
145 // | v | |
146 // | VASurfaceID is put onto VaapiVideoDecodeAccelerator::available_va_surfaces_ | |
147 // | | list. | |
148 // | v | |
149 // | VASurfaceID is taken off of the VVDA:available_va_surfaces_ when | |
150 // | | VaapiH264Decoder requests more output surfaces, is wrapped into | |
151 // | | a VASurface and passed to VaapiH264Decoder. | |
152 // | v | |
153 // | VASurface is put onto VaapiH264Decoder::available_va_surfaces_, keeping | |
154 // | | the only reference to it until it's needed for decoding. | |
155 // | v | |
156 // | VaapiH264Decoder starts decoding a new frame. It takes a VASurface off of | |
157 // | | VHD::available_va_surfaces_ and assigns it to a DecodeSurface, | |
158 // | | which now keeps the only reference. | |
159 // | v | |
160 // | DecodeSurface is used for decoding, putting data into associated VASurface. | |
161 // | | | |
162 // | |--------------------------------------------------+ | |
163 // | | | | |
164 // | v v | |
165 // | DecodeSurface is to be output. VaapiH264Decoder uses the | |
166 // | VaapiH264Decoder passes the associated DecodeSurface and associated | |
167 // | VASurface to VaapiVideoDecodeAccelerator, VASurface as reference for | |
168 // | which stores it (taking a ref) on decoding more frames. | |
169 // | pending_output_cbs_ queue until an output | | |
170 // | TFPPicture becomes available. v | |
171 // | | Once the DecodeSurface is not | |
172 // | | needed as reference anymore, | |
173 // | v it is released, releasing the | |
174 // | A TFPPicture becomes available after associated VASurface reference. | |
175 // | the client of VVDA returns | | |
176 // | a PictureBuffer associated with it. VVDA | | |
177 // | puts the contents of the VASurface into | | |
178 // | it and releases the reference to VASurface. | | |
179 // | | | | |
180 // | '---------------------------------------' | |
181 // | | | |
182 // | v | |
183 // | Neither VVDA nor VHD hold a reference to VASurface. VASurface is released, | |
184 // | ReleaseCB gets called in its destructor, which puts the associated | |
185 // | VASurfaceID back onto VVDA::available_va_surfaces_. | |
186 // | | | |
187 // '-------------------------------------| | |
188 // | | |
189 // v | |
190 // VaapiDelegate frees VASurfaceID. | |
191 // | |
192 class VASurface : public base::RefCountedThreadSafe<VASurface> { | |
193 public: | |
194 // Provided by user, will be called when all references to the surface | |
195 // are released. | |
196 typedef base::Callback<void(VASurfaceID)> ReleaseCB; | |
197 | |
198 VASurface(VASurfaceID va_surface_id, const ReleaseCB& release_cb); | |
199 | |
200 VASurfaceID id() { | |
201 return va_surface_id_; | |
202 } | |
203 | |
204 private: | |
205 friend class base::RefCountedThreadSafe<VASurface>; | |
206 ~VASurface(); | |
207 | |
208 const VASurfaceID va_surface_id_; | |
209 ReleaseCB release_cb_; | |
210 | |
211 DISALLOW_COPY_AND_ASSIGN(VASurface); | |
212 }; | |
213 | |
214 } // namespace content | |
215 | |
216 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_DELEGATE_H_ | |
OLD | NEW |