2 * gstvaapidecoder_objects.c - VA decoder objects helpers
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6 * Copyright (C) 2011-2013 Intel Corporation
7 * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * This library 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 this library; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301 USA
27 #include <gst/vaapi/gstvaapicontext.h>
28 #include "gstvaapidecoder_objects.h"
29 #include "gstvaapidecoder_priv.h"
30 #include "gstvaapisurfaceproxy_priv.h"
31 #include "gstvaapicompat.h"
32 #include "gstvaapiutils.h"
35 #include "gstvaapidebug.h"
37 #define GET_DECODER(obj) GST_VAAPI_DECODER_CAST((obj)->parent_instance.codec)
38 #define GET_CONTEXT(obj) GET_DECODER(obj)->context
39 #define GET_VA_DISPLAY(obj) GET_DECODER(obj)->va_display
40 #define GET_VA_CONTEXT(obj) GET_DECODER(obj)->va_context
43 gst_video_codec_frame_clear(GstVideoCodecFrame **frame_ptr)
47 gst_video_codec_frame_unref(*frame_ptr);
51 /* ------------------------------------------------------------------------- */
52 /* --- Pictures --- */
53 /* ------------------------------------------------------------------------- */
55 GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiPicture, gst_vaapi_picture);
58 GST_VAAPI_CREATE_PICTURE_FLAG_CLONE = 1 << 0,
59 GST_VAAPI_CREATE_PICTURE_FLAG_FIELD = 1 << 1,
63 destroy_slice_cb(gpointer data, gpointer user_data)
65 GstVaapiMiniObject * const object = data;
67 gst_vaapi_mini_object_unref(object);
71 gst_vaapi_picture_destroy(GstVaapiPicture *picture)
73 if (picture->slices) {
74 g_ptr_array_foreach(picture->slices, destroy_slice_cb, NULL);
75 g_ptr_array_free(picture->slices, TRUE);
76 picture->slices = NULL;
79 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)&picture->iq_matrix,
81 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)&picture->huf_table,
83 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)&picture->bitplane,
87 gst_vaapi_surface_proxy_unref(picture->proxy);
88 picture->proxy = NULL;
90 picture->surface_id = VA_INVALID_ID;
91 picture->surface = NULL;
93 vaapi_destroy_buffer(GET_VA_DISPLAY(picture), &picture->param_id);
94 picture->param = NULL;
96 gst_video_codec_frame_clear(&picture->frame);
97 gst_vaapi_picture_replace(&picture->parent_picture, NULL);
101 gst_vaapi_picture_create(
102 GstVaapiPicture *picture,
103 const GstVaapiCodecObjectConstructorArgs *args
108 picture->param_id = VA_INVALID_ID;
110 if (args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_CLONE) {
111 GstVaapiPicture * const parent_picture = GST_VAAPI_PICTURE(args->data);
113 picture->parent_picture = gst_vaapi_picture_ref(parent_picture);
115 picture->proxy = gst_vaapi_surface_proxy_ref(parent_picture->proxy);
116 picture->type = parent_picture->type;
117 picture->pts = parent_picture->pts;
118 picture->poc = parent_picture->poc;
120 // Copy all picture flags but "output"
121 GST_VAAPI_PICTURE_FLAG_SET(
123 GST_VAAPI_PICTURE_FLAGS(parent_picture) &
124 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
125 GST_VAAPI_PICTURE_FLAG_REFERENCE |
126 GST_VAAPI_PICTURE_FLAG_INTERLACED |
127 GST_VAAPI_PICTURE_FLAG_FF |
128 GST_VAAPI_PICTURE_FLAG_TFF)
131 picture->structure = parent_picture->structure;
132 if ((args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_FIELD) &&
133 GST_VAAPI_PICTURE_IS_INTERLACED(picture)) {
134 switch (picture->structure) {
135 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
136 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
138 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
139 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
142 GST_VAAPI_PICTURE_FLAG_UNSET(picture, GST_VAAPI_PICTURE_FLAG_FF);
145 if (parent_picture->has_crop_rect) {
146 picture->has_crop_rect = TRUE;
147 picture->crop_rect = parent_picture->crop_rect;
151 picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
152 picture->pts = GST_CLOCK_TIME_NONE;
155 gst_vaapi_context_get_surface_proxy(GET_CONTEXT(picture));
159 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
160 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_FF);
162 picture->surface = GST_VAAPI_SURFACE_PROXY_SURFACE(picture->proxy);
163 picture->surface_id = GST_VAAPI_SURFACE_PROXY_SURFACE_ID(picture->proxy);
165 success = vaapi_create_buffer(
166 GET_VA_DISPLAY(picture),
167 GET_VA_CONTEXT(picture),
168 VAPictureParameterBufferType,
176 picture->param_size = args->param_size;
178 picture->slices = g_ptr_array_new();
179 if (!picture->slices)
182 picture->frame = gst_video_codec_frame_ref(
183 GST_VAAPI_DECODER_CODEC_FRAME(GET_DECODER(picture)));
188 gst_vaapi_picture_new(
189 GstVaapiDecoder *decoder,
194 GstVaapiCodecObject *object;
196 object = gst_vaapi_codec_object_new(
197 &GstVaapiPictureClass,
198 GST_VAAPI_CODEC_BASE(decoder),
205 return GST_VAAPI_PICTURE_CAST(object);
209 gst_vaapi_picture_new_field(GstVaapiPicture *picture)
211 GstVaapiDecoder * const decoder = GET_DECODER(picture);
212 GstVaapiCodecObject *object;
214 object = gst_vaapi_codec_object_new(
215 gst_vaapi_codec_object_get_class(&picture->parent_instance),
216 GST_VAAPI_CODEC_BASE(decoder),
217 NULL, picture->param_size,
219 (GST_VAAPI_CREATE_PICTURE_FLAG_CLONE|
220 GST_VAAPI_CREATE_PICTURE_FLAG_FIELD)
224 return GST_VAAPI_PICTURE_CAST(object);
228 gst_vaapi_picture_add_slice(GstVaapiPicture *picture, GstVaapiSlice *slice)
230 g_return_if_fail(GST_VAAPI_IS_PICTURE(picture));
231 g_return_if_fail(GST_VAAPI_IS_SLICE(slice));
233 g_ptr_array_add(picture->slices, slice);
237 do_decode(VADisplay dpy, VAContextID ctx, VABufferID *buf_id, void **buf_ptr)
241 vaapi_unmap_buffer(dpy, *buf_id, buf_ptr);
243 status = vaRenderPicture(dpy, ctx, buf_id, 1);
244 if (!vaapi_check_status(status, "vaRenderPicture()"))
247 /* XXX: vaRenderPicture() is meant to destroy the VA buffer implicitly */
248 vaapi_destroy_buffer(dpy, buf_id);
253 gst_vaapi_picture_decode(GstVaapiPicture *picture)
255 GstVaapiIqMatrix *iq_matrix;
256 GstVaapiBitPlane *bitplane;
257 GstVaapiHuffmanTable *huf_table;
258 VADisplay va_display;
259 VAContextID va_context;
263 g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
265 va_display = GET_VA_DISPLAY(picture);
266 va_context = GET_VA_CONTEXT(picture);
268 GST_DEBUG("decode picture 0x%08x", picture->surface_id);
270 status = vaBeginPicture(va_display, va_context, picture->surface_id);
271 if (!vaapi_check_status(status, "vaBeginPicture()"))
274 if (!do_decode(va_display, va_context, &picture->param_id, &picture->param))
277 iq_matrix = picture->iq_matrix;
278 if (iq_matrix && !do_decode(va_display, va_context,
279 &iq_matrix->param_id, &iq_matrix->param))
282 bitplane = picture->bitplane;
283 if (bitplane && !do_decode(va_display, va_context,
284 &bitplane->data_id, (void **)&bitplane->data))
287 huf_table = picture->huf_table;
288 if (huf_table && !do_decode(va_display, va_context,
289 &huf_table->param_id,
290 (void **)&huf_table->param))
293 for (i = 0; i < picture->slices->len; i++) {
294 GstVaapiSlice * const slice = g_ptr_array_index(picture->slices, i);
295 VABufferID va_buffers[2];
297 huf_table = slice->huf_table;
298 if (huf_table && !do_decode(va_display, va_context,
299 &huf_table->param_id, (void **)&huf_table->param))
302 vaapi_unmap_buffer(va_display, slice->param_id, NULL);
303 va_buffers[0] = slice->param_id;
304 va_buffers[1] = slice->data_id;
306 status = vaRenderPicture(va_display, va_context, va_buffers, 2);
307 if (!vaapi_check_status(status, "vaRenderPicture()"))
310 vaapi_destroy_buffer(va_display, &slice->param_id);
311 vaapi_destroy_buffer(va_display, &slice->data_id);
314 status = vaEndPicture(va_display, va_context);
315 if (!vaapi_check_status(status, "vaEndPicture()"))
321 do_output(GstVaapiPicture *picture)
323 GstVideoCodecFrame * const out_frame = picture->frame;
324 GstVaapiSurfaceProxy *proxy;
327 if (GST_VAAPI_PICTURE_IS_OUTPUT(picture))
333 proxy = gst_vaapi_surface_proxy_ref(picture->proxy);
335 if (picture->has_crop_rect)
336 gst_vaapi_surface_proxy_set_crop_rect(proxy, &picture->crop_rect);
338 gst_video_codec_frame_set_user_data(out_frame,
339 proxy, (GDestroyNotify)gst_vaapi_mini_object_unref);
341 out_frame->pts = picture->pts;
343 if (GST_VAAPI_PICTURE_IS_SKIPPED(picture))
344 GST_VIDEO_CODEC_FRAME_FLAG_SET(out_frame,
345 GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY);
347 if (GST_VAAPI_PICTURE_IS_INTERLACED(picture)) {
348 flags |= GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED;
349 if (GST_VAAPI_PICTURE_IS_TFF(picture))
350 flags |= GST_VAAPI_SURFACE_PROXY_FLAG_TFF;
352 GST_VAAPI_SURFACE_PROXY_FLAG_SET(proxy, flags);
354 gst_vaapi_decoder_push_frame(GET_DECODER(picture), out_frame);
355 gst_video_codec_frame_clear(&picture->frame);
357 GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_OUTPUT);
362 gst_vaapi_picture_output(GstVaapiPicture *picture)
364 g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
366 if (G_UNLIKELY(picture->parent_picture)) {
367 /* Emit the first field to GstVideoDecoder so that to release
368 the underlying GstVideoCodecFrame. However, mark this
369 picture as skipped so that to not display it */
370 GstVaapiPicture * const parent_picture = picture->parent_picture;
372 if (!GST_VAAPI_PICTURE_IS_INTERLACED(parent_picture))
374 if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD(parent_picture))
376 GST_VAAPI_PICTURE_FLAG_SET(parent_picture,
377 GST_VAAPI_PICTURE_FLAG_SKIPPED);
378 if (!do_output(parent_picture))
382 return do_output(picture);
386 gst_vaapi_picture_set_crop_rect(GstVaapiPicture *picture,
387 const GstVaapiRectangle *crop_rect)
389 g_return_if_fail(GST_VAAPI_IS_PICTURE(picture));
391 picture->has_crop_rect = crop_rect != NULL;
392 if (picture->has_crop_rect)
393 picture->crop_rect = *crop_rect;
396 /* ------------------------------------------------------------------------- */
398 /* ------------------------------------------------------------------------- */
400 GST_VAAPI_CODEC_DEFINE_TYPE(GstVaapiSlice, gst_vaapi_slice);
403 gst_vaapi_slice_destroy(GstVaapiSlice *slice)
405 VADisplay const va_display = GET_VA_DISPLAY(slice);
407 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)&slice->huf_table,
410 vaapi_destroy_buffer(va_display, &slice->data_id);
411 vaapi_destroy_buffer(va_display, &slice->param_id);
416 gst_vaapi_slice_create(
417 GstVaapiSlice *slice,
418 const GstVaapiCodecObjectConstructorArgs *args
421 VASliceParameterBufferBase *slice_param;
424 slice->param_id = VA_INVALID_ID;
425 slice->data_id = VA_INVALID_ID;
427 success = vaapi_create_buffer(
428 GET_VA_DISPLAY(slice),
429 GET_VA_CONTEXT(slice),
430 VASliceDataBufferType,
439 success = vaapi_create_buffer(
440 GET_VA_DISPLAY(slice),
441 GET_VA_CONTEXT(slice),
442 VASliceParameterBufferType,
451 slice_param = slice->param;
452 slice_param->slice_data_size = args->data_size;
453 slice_param->slice_data_offset = 0;
454 slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
460 GstVaapiDecoder *decoder,
467 GstVaapiCodecObject *object;
469 object = gst_vaapi_codec_object_new(
471 GST_VAAPI_CODEC_BASE(decoder),
476 return GST_VAAPI_SLICE_CAST(object);