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 if (vaCreateBuffer(vactx
->display
, vactx
->context_id
,
49 VAPictureParameterBufferType
,
50 vactx
->pic_param_size
,
52 &vactx
->pic_param_buf_id
) != VA_STATUS_SUCCESS
)
54 va_buffers
[n_va_buffers
++] = vactx
->pic_param_buf_id
;
56 if (vactx
->iq_matrix_present
) {
57 if (vaCreateBuffer(vactx
->display
, vactx
->context_id
,
59 vactx
->iq_matrix_size
,
61 &vactx
->iq_matrix_buf_id
) != VA_STATUS_SUCCESS
)
63 va_buffers
[n_va_buffers
++] = vactx
->iq_matrix_buf_id
;
66 if (vactx
->bitplane_buffer
) {
67 if (vaCreateBuffer(vactx
->display
, vactx
->context_id
,
69 vactx
->bitplane_buffer_size
,
70 1, vactx
->bitplane_buffer
,
71 &vactx
->bitplane_buf_id
) != VA_STATUS_SUCCESS
)
73 va_buffers
[n_va_buffers
++] = vactx
->bitplane_buf_id
;
76 if (vaBeginPicture(vactx
->display
, vactx
->context_id
,
77 surface
) != VA_STATUS_SUCCESS
)
80 if (vaRenderPicture(vactx
->display
, vactx
->context_id
,
81 va_buffers
, n_va_buffers
) != VA_STATUS_SUCCESS
)
84 if (vaRenderPicture(vactx
->display
, vactx
->context_id
,
86 vactx
->n_slice_buf_ids
) != VA_STATUS_SUCCESS
)
89 if (vaEndPicture(vactx
->display
, vactx
->context_id
) != VA_STATUS_SUCCESS
)
95 static int commit_slices(struct vaapi_context
*vactx
)
97 VABufferID
*slice_buf_ids
;
98 VABufferID slice_param_buf_id
, slice_data_buf_id
;
100 if (vactx
->slice_count
== 0)
104 av_fast_realloc(vactx
->slice_buf_ids
,
105 &vactx
->slice_buf_ids_alloc
,
106 (vactx
->n_slice_buf_ids
+ 2) * sizeof(slice_buf_ids
[0]));
109 vactx
->slice_buf_ids
= slice_buf_ids
;
111 slice_param_buf_id
= 0;
112 if (vaCreateBuffer(vactx
->display
, vactx
->context_id
,
113 VASliceParameterBufferType
,
114 vactx
->slice_param_size
,
115 vactx
->slice_count
, vactx
->slice_params
,
116 &slice_param_buf_id
) != VA_STATUS_SUCCESS
)
118 vactx
->slice_count
= 0;
120 slice_data_buf_id
= 0;
121 if (vaCreateBuffer(vactx
->display
, vactx
->context_id
,
122 VASliceDataBufferType
,
123 vactx
->slice_data_size
,
124 1, (void *)vactx
->slice_data
,
125 &slice_data_buf_id
) != VA_STATUS_SUCCESS
)
127 vactx
->slice_data
= NULL
;
128 vactx
->slice_data_size
= 0;
130 slice_buf_ids
[vactx
->n_slice_buf_ids
++] = slice_param_buf_id
;
131 slice_buf_ids
[vactx
->n_slice_buf_ids
++] = slice_data_buf_id
;
135 VASliceParameterBufferBase
*ff_vaapi_alloc_slice(struct vaapi_context
*vactx
, const uint8_t *buffer
, uint32_t size
)
137 uint8_t *slice_params
;
138 VASliceParameterBufferBase
*slice_param
;
140 if (!vactx
->slice_data
)
141 vactx
->slice_data
= buffer
;
142 if (vactx
->slice_data
+ vactx
->slice_data_size
!= buffer
) {
143 if (commit_slices(vactx
) < 0)
145 vactx
->slice_data
= buffer
;
149 av_fast_realloc(vactx
->slice_params
,
150 &vactx
->slice_params_alloc
,
151 (vactx
->slice_count
+ 1) * vactx
->slice_param_size
);
154 vactx
->slice_params
= slice_params
;
156 slice_param
= (VASliceParameterBufferBase
*)(slice_params
+ vactx
->slice_count
* vactx
->slice_param_size
);
157 slice_param
->slice_data_size
= size
;
158 slice_param
->slice_data_offset
= vactx
->slice_data_size
;
159 slice_param
->slice_data_flag
= VA_SLICE_DATA_FLAG_ALL
;
161 vactx
->slice_count
++;
162 vactx
->slice_data_size
+= size
;
166 int ff_vaapi_common_end_frame(MpegEncContext
*s
)
168 struct vaapi_context
* const vactx
= s
->avctx
->hwaccel_context
;
171 dprintf(s
->avctx
, "ff_vaapi_common_end_frame()\n");
173 if (commit_slices(vactx
) < 0)
175 if (vactx
->n_slice_buf_ids
> 0) {
176 if (render_picture(vactx
, ff_vaapi_get_surface(s
->current_picture_ptr
)) < 0)
178 ff_draw_horiz_band(s
, 0, s
->avctx
->height
);
183 destroy_buffers(vactx
->display
, &vactx
->pic_param_buf_id
, 1);
184 destroy_buffers(vactx
->display
, &vactx
->iq_matrix_buf_id
, 1);
185 destroy_buffers(vactx
->display
, &vactx
->bitplane_buf_id
, 1);
186 destroy_buffers(vactx
->display
, vactx
->slice_buf_ids
, vactx
->n_slice_buf_ids
);
187 av_freep(&vactx
->bitplane_buffer
);
188 av_freep(&vactx
->slice_buf_ids
);
189 av_freep(&vactx
->slice_params
);
190 vactx
->n_slice_buf_ids
= 0;
191 vactx
->slice_buf_ids_alloc
= 0;
192 vactx
->slice_count
= 0;
193 vactx
->slice_params_alloc
= 0;