FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vaapi.c
Go to the documentation of this file.
1 /*
2  * Video Acceleration API (video decoding)
3  * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1
4  *
5  * Copyright (C) 2008-2009 Splitted-Desktop Systems
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include "vaapi_internal.h"
25 
26 /**
27  * @addtogroup VAAPI_Decoding
28  *
29  * @{
30  */
31 
32 static void destroy_buffers(VADisplay display, VABufferID *buffers, unsigned int n_buffers)
33 {
34  unsigned int i;
35  for (i = 0; i < n_buffers; i++) {
36  if (buffers[i]) {
37  vaDestroyBuffer(display, buffers[i]);
38  buffers[i] = 0;
39  }
40  }
41 }
42 
43 static int render_picture(struct vaapi_context *vactx, VASurfaceID surface)
44 {
45  VABufferID va_buffers[3];
46  unsigned int n_va_buffers = 0;
47 
48  vaUnmapBuffer(vactx->display, vactx->pic_param_buf_id);
49  va_buffers[n_va_buffers++] = vactx->pic_param_buf_id;
50 
51  if (vactx->iq_matrix_buf_id) {
52  vaUnmapBuffer(vactx->display, vactx->iq_matrix_buf_id);
53  va_buffers[n_va_buffers++] = vactx->iq_matrix_buf_id;
54  }
55 
56  if (vactx->bitplane_buf_id) {
57  vaUnmapBuffer(vactx->display, vactx->bitplane_buf_id);
58  va_buffers[n_va_buffers++] = vactx->bitplane_buf_id;
59  }
60 
61  if (vaBeginPicture(vactx->display, vactx->context_id,
62  surface) != VA_STATUS_SUCCESS)
63  return -1;
64 
65  if (vaRenderPicture(vactx->display, vactx->context_id,
66  va_buffers, n_va_buffers) != VA_STATUS_SUCCESS)
67  return -1;
68 
69  if (vaRenderPicture(vactx->display, vactx->context_id,
70  vactx->slice_buf_ids,
71  vactx->n_slice_buf_ids) != VA_STATUS_SUCCESS)
72  return -1;
73 
74  if (vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS)
75  return -1;
76 
77  return 0;
78 }
79 
80 static int commit_slices(struct vaapi_context *vactx)
81 {
82  VABufferID *slice_buf_ids;
83  VABufferID slice_param_buf_id, slice_data_buf_id;
84 
85  if (vactx->slice_count == 0)
86  return 0;
87 
88  slice_buf_ids =
90  &vactx->slice_buf_ids_alloc,
91  (vactx->n_slice_buf_ids + 2) * sizeof(slice_buf_ids[0]));
92  if (!slice_buf_ids)
93  return -1;
94  vactx->slice_buf_ids = slice_buf_ids;
95 
96  slice_param_buf_id = 0;
97  if (vaCreateBuffer(vactx->display, vactx->context_id,
98  VASliceParameterBufferType,
99  vactx->slice_param_size,
100  vactx->slice_count, vactx->slice_params,
101  &slice_param_buf_id) != VA_STATUS_SUCCESS)
102  return -1;
103  vactx->slice_count = 0;
104 
105  slice_data_buf_id = 0;
106  if (vaCreateBuffer(vactx->display, vactx->context_id,
107  VASliceDataBufferType,
108  vactx->slice_data_size,
109  1, (void *)vactx->slice_data,
110  &slice_data_buf_id) != VA_STATUS_SUCCESS)
111  return -1;
112  vactx->slice_data = NULL;
113  vactx->slice_data_size = 0;
114 
115  slice_buf_ids[vactx->n_slice_buf_ids++] = slice_param_buf_id;
116  slice_buf_ids[vactx->n_slice_buf_ids++] = slice_data_buf_id;
117  return 0;
118 }
119 
120 static void *alloc_buffer(struct vaapi_context *vactx, int type, unsigned int size, uint32_t *buf_id)
121 {
122  void *data = NULL;
123 
124  *buf_id = 0;
125  if (vaCreateBuffer(vactx->display, vactx->context_id,
126  type, size, 1, NULL, buf_id) == VA_STATUS_SUCCESS)
127  vaMapBuffer(vactx->display, *buf_id, &data);
128 
129  return data;
130 }
131 
132 void *ff_vaapi_alloc_pic_param(struct vaapi_context *vactx, unsigned int size)
133 {
134  return alloc_buffer(vactx, VAPictureParameterBufferType, size, &vactx->pic_param_buf_id);
135 }
136 
137 void *ff_vaapi_alloc_iq_matrix(struct vaapi_context *vactx, unsigned int size)
138 {
139  return alloc_buffer(vactx, VAIQMatrixBufferType, size, &vactx->iq_matrix_buf_id);
140 }
141 
143 {
144  return alloc_buffer(vactx, VABitPlaneBufferType, size, &vactx->bitplane_buf_id);
145 }
146 
147 VASliceParameterBufferBase *ff_vaapi_alloc_slice(struct vaapi_context *vactx, const uint8_t *buffer, uint32_t size)
148 {
149  uint8_t *slice_params;
150  VASliceParameterBufferBase *slice_param;
151 
152  if (!vactx->slice_data)
153  vactx->slice_data = buffer;
154  if (vactx->slice_data + vactx->slice_data_size != buffer) {
155  if (commit_slices(vactx) < 0)
156  return NULL;
157  vactx->slice_data = buffer;
158  }
159 
160  slice_params =
162  &vactx->slice_params_alloc,
163  (vactx->slice_count + 1) * vactx->slice_param_size);
164  if (!slice_params)
165  return NULL;
166  vactx->slice_params = slice_params;
167 
168  slice_param = (VASliceParameterBufferBase *)(slice_params + vactx->slice_count * vactx->slice_param_size);
169  slice_param->slice_data_size = size;
170  slice_param->slice_data_offset = vactx->slice_data_size;
171  slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
172 
173  vactx->slice_count++;
174  vactx->slice_data_size += size;
175  return slice_param;
176 }
177 
179 {
180  struct vaapi_context * const vactx = s->avctx->hwaccel_context;
181  int ret = -1;
182 
183  av_dlog(s->avctx, "ff_vaapi_common_end_frame()\n");
184 
185  if (commit_slices(vactx) < 0)
186  goto done;
187  if (vactx->n_slice_buf_ids > 0) {
189  goto done;
190  ff_draw_horiz_band(s, 0, s->avctx->height);
191  }
192  ret = 0;
193 
194 done:
195  destroy_buffers(vactx->display, &vactx->pic_param_buf_id, 1);
196  destroy_buffers(vactx->display, &vactx->iq_matrix_buf_id, 1);
197  destroy_buffers(vactx->display, &vactx->bitplane_buf_id, 1);
198  destroy_buffers(vactx->display, vactx->slice_buf_ids, vactx->n_slice_buf_ids);
199  av_freep(&vactx->slice_buf_ids);
200  av_freep(&vactx->slice_params);
201  vactx->n_slice_buf_ids = 0;
202  vactx->slice_buf_ids_alloc = 0;
203  vactx->slice_count = 0;
204  vactx->slice_params_alloc = 0;
205  return ret;
206 }
207 
208 /* @} */