2 * Video Acceleration API (video decoding)
3 * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1
5 * Copyright (C) 2008-2009 Splitted-Desktop Systems
7 * This file is part of FFmpeg.
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.
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.
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
24 #include "vaapi_internal.h"
27 * \addtogroup VAAPI_Decoding
32 static void destroy_buffers(VADisplay display
, VABufferID
*buffers
, unsigned int n_buffers
)
35 for (i
= 0; i
< n_buffers
; i
++) {
37 vaDestroyBuffer(display
, buffers
[i
]);
43 static int render_picture(struct vaapi_context
*vactx
, VASurfaceID surface
)
45 VABufferID va_buffers
[3];
46 unsigned int n_va_buffers
= 0;
48 vaUnmapBuffer(vactx
->display
, vactx
->pic_param_buf_id
);
49 va_buffers
[n_va_buffers
++] = vactx
->pic_param_buf_id
;
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
;
56 if (vactx
->bitplane_buf_id
) {
57 vaUnmapBuffer(vactx
->display
, vactx
->bitplane_buf_id
);
58 va_buffers
[n_va_buffers
++] = vactx
->bitplane_buf_id
;
61 if (vaBeginPicture(vactx
->display
, vactx
->context_id
,
62 surface
) != VA_STATUS_SUCCESS
)
65 if (vaRenderPicture(vactx
->display
, vactx
->context_id
,
66 va_buffers
, n_va_buffers
) != VA_STATUS_SUCCESS
)
69 if (vaRenderPicture(vactx
->display
, vactx
->context_id
,
71 vactx
->n_slice_buf_ids
) != VA_STATUS_SUCCESS
)
74 if (vaEndPicture(vactx
->display
, vactx
->context_id
) != VA_STATUS_SUCCESS
)
80 static int commit_slices(struct vaapi_context
*vactx
)
82 VABufferID
*slice_buf_ids
;
83 VABufferID slice_param_buf_id
, slice_data_buf_id
;
85 if (vactx
->slice_count
== 0)
89 av_fast_realloc(vactx
->slice_buf_ids
,
90 &vactx
->slice_buf_ids_alloc
,
91 (vactx
->n_slice_buf_ids
+ 2) * sizeof(slice_buf_ids
[0]));
94 vactx
->slice_buf_ids
= slice_buf_ids
;
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
)
103 vactx
->slice_count
= 0;
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
)
112 vactx
->slice_data
= NULL
;
113 vactx
->slice_data_size
= 0;
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
;
120 static void *alloc_buffer(struct vaapi_context
*vactx
, int type
, unsigned int size
, uint32_t *buf_id
)
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
);
132 void *ff_vaapi_alloc_picture(struct vaapi_context
*vactx
, unsigned int size
)
134 return alloc_buffer(vactx
, VAPictureParameterBufferType
, size
, &vactx
->pic_param_buf_id
);
137 void *ff_vaapi_alloc_iq_matrix(struct vaapi_context
*vactx
, unsigned int size
)
139 return alloc_buffer(vactx
, VAIQMatrixBufferType
, size
, &vactx
->iq_matrix_buf_id
);
142 uint8_t *ff_vaapi_alloc_bitplane(struct vaapi_context
*vactx
, uint32_t size
)
144 return alloc_buffer(vactx
, VABitPlaneBufferType
, size
, &vactx
->bitplane_buf_id
);
147 VASliceParameterBufferBase
*ff_vaapi_alloc_slice(struct vaapi_context
*vactx
, const uint8_t *buffer
, uint32_t size
)
149 uint8_t *slice_params
;
150 VASliceParameterBufferBase
*slice_param
;
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)
157 vactx
->slice_data
= buffer
;
161 av_fast_realloc(vactx
->slice_params
,
162 &vactx
->slice_params_alloc
,
163 (vactx
->slice_count
+ 1) * vactx
->slice_param_size
);
166 vactx
->slice_params
= slice_params
;
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
;
173 vactx
->slice_count
++;
174 vactx
->slice_data_size
+= size
;
178 int ff_vaapi_common_end_frame(MpegEncContext
*s
)
180 struct vaapi_context
* const vactx
= s
->avctx
->hwaccel_context
;
183 dprintf(s
->avctx
, "ff_vaapi_common_end_frame()\n");
185 if (commit_slices(vactx
) < 0)
187 if (vactx
->n_slice_buf_ids
> 0) {
188 if (render_picture(vactx
, ff_vaapi_get_surface(s
->current_picture_ptr
)) < 0)
190 ff_draw_horiz_band(s
, 0, s
->avctx
->height
);
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;