Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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 "h264.h" | |
25 | #include "vaapi_internal.h" | |
26 | ||
27 | /** | |
28 | * @addtogroup VAAPI_Decoding | |
29 | * | |
30 | * @{ | |
31 | */ | |
32 | ||
33 | static void destroy_buffers(VADisplay display, VABufferID *buffers, unsigned int n_buffers) | |
34 | { | |
35 | unsigned int i; | |
36 | for (i = 0; i < n_buffers; i++) { | |
37 | if (buffers[i]) { | |
38 | vaDestroyBuffer(display, buffers[i]); | |
39 | buffers[i] = 0; | |
40 | } | |
41 | } | |
42 | } | |
43 | ||
44 | int ff_vaapi_render_picture(struct vaapi_context *vactx, VASurfaceID surface) | |
45 | { | |
46 | VABufferID va_buffers[3]; | |
47 | unsigned int n_va_buffers = 0; | |
48 | ||
49 | if (!vactx->pic_param_buf_id) | |
50 | return 0; | |
51 | ||
52 | vaUnmapBuffer(vactx->display, vactx->pic_param_buf_id); | |
53 | va_buffers[n_va_buffers++] = vactx->pic_param_buf_id; | |
54 | ||
55 | if (vactx->iq_matrix_buf_id) { | |
56 | vaUnmapBuffer(vactx->display, vactx->iq_matrix_buf_id); | |
57 | va_buffers[n_va_buffers++] = vactx->iq_matrix_buf_id; | |
58 | } | |
59 | ||
60 | if (vactx->bitplane_buf_id) { | |
61 | vaUnmapBuffer(vactx->display, vactx->bitplane_buf_id); | |
62 | va_buffers[n_va_buffers++] = vactx->bitplane_buf_id; | |
63 | } | |
64 | ||
65 | if (vaBeginPicture(vactx->display, vactx->context_id, | |
66 | surface) != VA_STATUS_SUCCESS) | |
67 | return -1; | |
68 | ||
69 | if (vaRenderPicture(vactx->display, vactx->context_id, | |
70 | va_buffers, n_va_buffers) != VA_STATUS_SUCCESS) | |
71 | return -1; | |
72 | ||
73 | if (vaRenderPicture(vactx->display, vactx->context_id, | |
74 | vactx->slice_buf_ids, | |
75 | vactx->n_slice_buf_ids) != VA_STATUS_SUCCESS) | |
76 | return -1; | |
77 | ||
78 | if (vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS) | |
79 | return -1; | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
84 | int ff_vaapi_commit_slices(struct vaapi_context *vactx) | |
85 | { | |
86 | VABufferID *slice_buf_ids; | |
87 | VABufferID slice_param_buf_id, slice_data_buf_id; | |
88 | ||
89 | if (vactx->slice_count == 0) | |
90 | return 0; | |
91 | ||
92 | slice_buf_ids = | |
93 | av_fast_realloc(vactx->slice_buf_ids, | |
94 | &vactx->slice_buf_ids_alloc, | |
95 | (vactx->n_slice_buf_ids + 2) * sizeof(slice_buf_ids[0])); | |
96 | if (!slice_buf_ids) | |
97 | return -1; | |
98 | vactx->slice_buf_ids = slice_buf_ids; | |
99 | ||
100 | slice_param_buf_id = 0; | |
101 | if (vaCreateBuffer(vactx->display, vactx->context_id, | |
102 | VASliceParameterBufferType, | |
103 | vactx->slice_param_size, | |
104 | vactx->slice_count, vactx->slice_params, | |
105 | &slice_param_buf_id) != VA_STATUS_SUCCESS) | |
106 | return -1; | |
107 | vactx->slice_count = 0; | |
108 | ||
109 | slice_data_buf_id = 0; | |
110 | if (vaCreateBuffer(vactx->display, vactx->context_id, | |
111 | VASliceDataBufferType, | |
112 | vactx->slice_data_size, | |
113 | 1, (void *)vactx->slice_data, | |
114 | &slice_data_buf_id) != VA_STATUS_SUCCESS) | |
115 | return -1; | |
116 | vactx->slice_data = NULL; | |
117 | vactx->slice_data_size = 0; | |
118 | ||
119 | slice_buf_ids[vactx->n_slice_buf_ids++] = slice_param_buf_id; | |
120 | slice_buf_ids[vactx->n_slice_buf_ids++] = slice_data_buf_id; | |
121 | return 0; | |
122 | } | |
123 | ||
124 | static void *alloc_buffer(struct vaapi_context *vactx, int type, unsigned int size, uint32_t *buf_id) | |
125 | { | |
126 | void *data = NULL; | |
127 | ||
128 | *buf_id = 0; | |
129 | if (vaCreateBuffer(vactx->display, vactx->context_id, | |
130 | type, size, 1, NULL, buf_id) == VA_STATUS_SUCCESS) | |
131 | vaMapBuffer(vactx->display, *buf_id, &data); | |
132 | ||
133 | return data; | |
134 | } | |
135 | ||
136 | void *ff_vaapi_alloc_pic_param(struct vaapi_context *vactx, unsigned int size) | |
137 | { | |
138 | return alloc_buffer(vactx, VAPictureParameterBufferType, size, &vactx->pic_param_buf_id); | |
139 | } | |
140 | ||
141 | void *ff_vaapi_alloc_iq_matrix(struct vaapi_context *vactx, unsigned int size) | |
142 | { | |
143 | return alloc_buffer(vactx, VAIQMatrixBufferType, size, &vactx->iq_matrix_buf_id); | |
144 | } | |
145 | ||
146 | uint8_t *ff_vaapi_alloc_bitplane(struct vaapi_context *vactx, uint32_t size) | |
147 | { | |
148 | return alloc_buffer(vactx, VABitPlaneBufferType, size, &vactx->bitplane_buf_id); | |
149 | } | |
150 | ||
151 | VASliceParameterBufferBase *ff_vaapi_alloc_slice(struct vaapi_context *vactx, const uint8_t *buffer, uint32_t size) | |
152 | { | |
153 | uint8_t *slice_params; | |
154 | VASliceParameterBufferBase *slice_param; | |
155 | ||
156 | if (!vactx->slice_data) | |
157 | vactx->slice_data = buffer; | |
158 | if (vactx->slice_data + vactx->slice_data_size != buffer) { | |
159 | if (ff_vaapi_commit_slices(vactx) < 0) | |
160 | return NULL; | |
161 | vactx->slice_data = buffer; | |
162 | } | |
163 | ||
164 | slice_params = | |
165 | av_fast_realloc(vactx->slice_params, | |
166 | &vactx->slice_params_alloc, | |
167 | (vactx->slice_count + 1) * vactx->slice_param_size); | |
168 | if (!slice_params) | |
169 | return NULL; | |
170 | vactx->slice_params = slice_params; | |
171 | ||
172 | slice_param = (VASliceParameterBufferBase *)(slice_params + vactx->slice_count * vactx->slice_param_size); | |
173 | slice_param->slice_data_size = size; | |
174 | slice_param->slice_data_offset = vactx->slice_data_size; | |
175 | slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; | |
176 | ||
177 | vactx->slice_count++; | |
178 | vactx->slice_data_size += size; | |
179 | return slice_param; | |
180 | } | |
181 | ||
182 | void ff_vaapi_common_end_frame(AVCodecContext *avctx) | |
183 | { | |
184 | struct vaapi_context * const vactx = avctx->hwaccel_context; | |
185 | ||
186 | av_dlog(avctx, "ff_vaapi_common_end_frame()\n"); | |
187 | ||
188 | destroy_buffers(vactx->display, &vactx->pic_param_buf_id, 1); | |
189 | destroy_buffers(vactx->display, &vactx->iq_matrix_buf_id, 1); | |
190 | destroy_buffers(vactx->display, &vactx->bitplane_buf_id, 1); | |
191 | destroy_buffers(vactx->display, vactx->slice_buf_ids, vactx->n_slice_buf_ids); | |
192 | av_freep(&vactx->slice_buf_ids); | |
193 | av_freep(&vactx->slice_params); | |
194 | vactx->n_slice_buf_ids = 0; | |
195 | vactx->slice_buf_ids_alloc = 0; | |
196 | vactx->slice_count = 0; | |
197 | vactx->slice_params_alloc = 0; | |
198 | } | |
199 | ||
200 | /* @} */ |