]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - libavcodec/vaapi.c
frsh: Export information about the last RTP contract and VRES
[frescor/ffmpeg.git] / libavcodec / vaapi.c
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 =
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]));
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_picture(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
142 uint8_t *ff_vaapi_alloc_bitplane(struct vaapi_context *vactx, uint32_t size)
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 =
161         av_fast_realloc(vactx->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
178 int ff_vaapi_common_end_frame(MpegEncContext *s)
179 {
180     struct vaapi_context * const vactx = s->avctx->hwaccel_context;
181     int ret = -1;
182
183     dprintf(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) {
188         if (render_picture(vactx, ff_vaapi_get_surface(s->current_picture_ptr)) < 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 /* @} */