9225
|
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 if (vaCreateBuffer(vactx->display, vactx->context_id,
|
|
49 VAPictureParameterBufferType,
|
|
50 vactx->pic_param_size,
|
|
51 1, &vactx->pic_param,
|
|
52 &vactx->pic_param_buf_id) != VA_STATUS_SUCCESS)
|
|
53 return -1;
|
|
54 va_buffers[n_va_buffers++] = vactx->pic_param_buf_id;
|
|
55
|
|
56 if (vactx->iq_matrix_present) {
|
|
57 if (vaCreateBuffer(vactx->display, vactx->context_id,
|
|
58 VAIQMatrixBufferType,
|
|
59 vactx->iq_matrix_size,
|
|
60 1, &vactx->iq_matrix,
|
|
61 &vactx->iq_matrix_buf_id) != VA_STATUS_SUCCESS)
|
|
62 return -1;
|
|
63 va_buffers[n_va_buffers++] = vactx->iq_matrix_buf_id;
|
|
64 }
|
|
65
|
|
66 if (vactx->bitplane_buffer) {
|
|
67 if (vaCreateBuffer(vactx->display, vactx->context_id,
|
|
68 VABitPlaneBufferType,
|
|
69 vactx->bitplane_buffer_size,
|
|
70 1, vactx->bitplane_buffer,
|
|
71 &vactx->bitplane_buf_id) != VA_STATUS_SUCCESS)
|
|
72 return -1;
|
|
73 va_buffers[n_va_buffers++] = vactx->bitplane_buf_id;
|
|
74 }
|
|
75
|
|
76 if (vaBeginPicture(vactx->display, vactx->context_id,
|
|
77 surface) != VA_STATUS_SUCCESS)
|
|
78 return -1;
|
|
79
|
|
80 if (vaRenderPicture(vactx->display, vactx->context_id,
|
|
81 va_buffers, n_va_buffers) != VA_STATUS_SUCCESS)
|
|
82 return -1;
|
|
83
|
|
84 if (vaRenderPicture(vactx->display, vactx->context_id,
|
|
85 vactx->slice_buf_ids,
|
|
86 vactx->n_slice_buf_ids) != VA_STATUS_SUCCESS)
|
|
87 return -1;
|
|
88
|
|
89 if (vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS)
|
|
90 return -1;
|
|
91
|
|
92 return 0;
|
|
93 }
|
|
94
|
|
95 static int commit_slices(struct vaapi_context *vactx)
|
|
96 {
|
|
97 VABufferID *slice_buf_ids;
|
|
98 VABufferID slice_param_buf_id, slice_data_buf_id;
|
|
99
|
|
100 if (vactx->slice_count == 0)
|
|
101 return 0;
|
|
102
|
|
103 slice_buf_ids =
|
|
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]));
|
|
107 if (!slice_buf_ids)
|
|
108 return -1;
|
|
109 vactx->slice_buf_ids = slice_buf_ids;
|
|
110
|
|
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)
|
|
117 return -1;
|
|
118 vactx->slice_count = 0;
|
|
119
|
|
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)
|
|
126 return -1;
|
|
127 vactx->slice_data = NULL;
|
|
128 vactx->slice_data_size = 0;
|
|
129
|
|
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;
|
|
132 return 0;
|
|
133 }
|
|
134
|
|
135 VASliceParameterBufferBase *ff_vaapi_alloc_slice(struct vaapi_context *vactx, const uint8_t *buffer, uint32_t size)
|
|
136 {
|
|
137 uint8_t *slice_params;
|
|
138 VASliceParameterBufferBase *slice_param;
|
|
139
|
|
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)
|
|
144 return NULL;
|
|
145 vactx->slice_data = buffer;
|
|
146 }
|
|
147
|
|
148 slice_params =
|
|
149 av_fast_realloc(vactx->slice_params,
|
|
150 &vactx->slice_params_alloc,
|
|
151 (vactx->slice_count + 1) * vactx->slice_param_size);
|
|
152 if (!slice_params)
|
|
153 return NULL;
|
|
154 vactx->slice_params = slice_params;
|
|
155
|
|
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;
|
|
160
|
|
161 vactx->slice_count++;
|
|
162 vactx->slice_data_size += size;
|
|
163 return slice_param;
|
|
164 }
|
|
165
|
|
166 int ff_vaapi_common_end_frame(MpegEncContext *s)
|
|
167 {
|
|
168 struct vaapi_context * const vactx = s->avctx->hwaccel_context;
|
|
169 int ret = -1;
|
|
170
|
|
171 dprintf(s->avctx, "ff_vaapi_common_end_frame()\n");
|
|
172
|
|
173 if (commit_slices(vactx) < 0)
|
|
174 goto done;
|
|
175 if (vactx->n_slice_buf_ids > 0) {
|
|
176 if (render_picture(vactx, ff_vaapi_get_surface(s->current_picture_ptr)) < 0)
|
|
177 goto done;
|
|
178 ff_draw_horiz_band(s, 0, s->avctx->height);
|
|
179 }
|
|
180 ret = 0;
|
|
181
|
|
182 done:
|
|
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;
|
|
194 return ret;
|
|
195 }
|
|
196
|
|
197 /* @} */
|