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-2014 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);
59 GST_VAAPI_CREATE_PICTURE_FLAG_CLONE = 1 << 0,
60 GST_VAAPI_CREATE_PICTURE_FLAG_FIELD = 1 << 1,
64 gst_vaapi_picture_destroy (GstVaapiPicture * picture)
66 if (picture->slices) {
67 g_ptr_array_unref (picture->slices);
68 picture->slices = NULL;
71 gst_vaapi_codec_object_replace (&picture->iq_matrix, NULL);
72 gst_vaapi_codec_object_replace (&picture->huf_table, NULL);
73 gst_vaapi_codec_object_replace (&picture->bitplane, NULL);
74 gst_vaapi_codec_object_replace (&picture->prob_table, NULL);
77 gst_vaapi_surface_proxy_unref (picture->proxy);
78 picture->proxy = NULL;
80 picture->surface_id = VA_INVALID_ID;
81 picture->surface = NULL;
83 vaapi_destroy_buffer (GET_VA_DISPLAY (picture), &picture->param_id);
84 picture->param = NULL;
86 gst_video_codec_frame_clear (&picture->frame);
87 gst_vaapi_picture_replace (&picture->parent_picture, NULL);
91 gst_vaapi_picture_create (GstVaapiPicture * picture,
92 const GstVaapiCodecObjectConstructorArgs * args)
96 picture->param_id = VA_INVALID_ID;
98 if (args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_CLONE) {
99 GstVaapiPicture *const parent_picture = GST_VAAPI_PICTURE (args->data);
101 picture->parent_picture = gst_vaapi_picture_ref (parent_picture);
103 picture->proxy = gst_vaapi_surface_proxy_ref (parent_picture->proxy);
104 picture->type = parent_picture->type;
105 picture->pts = parent_picture->pts;
106 picture->poc = parent_picture->poc;
107 picture->voc = parent_picture->voc;
108 picture->view_id = parent_picture->view_id;
110 // Copy all picture flags but "output"
111 GST_VAAPI_PICTURE_FLAG_SET (picture,
112 GST_VAAPI_PICTURE_FLAGS (parent_picture) &
113 (GST_VAAPI_PICTURE_FLAG_SKIPPED |
114 GST_VAAPI_PICTURE_FLAG_REFERENCE |
115 GST_VAAPI_PICTURE_FLAG_INTERLACED |
116 GST_VAAPI_PICTURE_FLAG_FF | GST_VAAPI_PICTURE_FLAG_TFF |
117 GST_VAAPI_PICTURE_FLAG_MVC));
119 picture->structure = parent_picture->structure;
120 if ((args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_FIELD) &&
121 GST_VAAPI_PICTURE_IS_INTERLACED (picture)) {
122 switch (picture->structure) {
123 case GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD:
124 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD;
126 case GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD:
127 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD;
130 GST_VAAPI_PICTURE_FLAG_UNSET (picture, GST_VAAPI_PICTURE_FLAG_FF);
133 if (parent_picture->has_crop_rect) {
134 picture->has_crop_rect = TRUE;
135 picture->crop_rect = parent_picture->crop_rect;
138 picture->type = GST_VAAPI_PICTURE_TYPE_NONE;
139 picture->pts = GST_CLOCK_TIME_NONE;
142 gst_vaapi_context_get_surface_proxy (GET_CONTEXT (picture));
146 picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME;
147 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_FF);
149 picture->surface = GST_VAAPI_SURFACE_PROXY_SURFACE (picture->proxy);
150 picture->surface_id = GST_VAAPI_SURFACE_PROXY_SURFACE_ID (picture->proxy);
152 success = vaapi_create_buffer (GET_VA_DISPLAY (picture),
153 GET_VA_CONTEXT (picture), VAPictureParameterBufferType,
154 args->param_size, args->param, &picture->param_id, &picture->param);
157 picture->param_size = args->param_size;
159 picture->slices = g_ptr_array_new_with_free_func ((GDestroyNotify)
160 gst_vaapi_mini_object_unref);
161 if (!picture->slices)
165 gst_video_codec_frame_ref (GST_VAAPI_DECODER_CODEC_FRAME (GET_DECODER
171 gst_vaapi_picture_new (GstVaapiDecoder * decoder,
172 gconstpointer param, guint param_size)
174 GstVaapiCodecObject *object;
176 object = gst_vaapi_codec_object_new (&GstVaapiPictureClass,
177 GST_VAAPI_CODEC_BASE (decoder), param, param_size, NULL, 0, 0);
180 return GST_VAAPI_PICTURE_CAST (object);
184 gst_vaapi_picture_new_field (GstVaapiPicture * picture)
186 GstVaapiDecoder *const decoder = GET_DECODER (picture);
187 GstVaapiCodecObject *object;
189 object = gst_vaapi_codec_object_new (gst_vaapi_codec_object_get_class
190 (&picture->parent_instance), GST_VAAPI_CODEC_BASE (decoder), NULL,
191 picture->param_size, picture, 0,
192 (GST_VAAPI_CREATE_PICTURE_FLAG_CLONE |
193 GST_VAAPI_CREATE_PICTURE_FLAG_FIELD));
196 return GST_VAAPI_PICTURE_CAST (object);
200 gst_vaapi_picture_add_slice (GstVaapiPicture * picture, GstVaapiSlice * slice)
202 g_return_if_fail (GST_VAAPI_IS_PICTURE (picture));
203 g_return_if_fail (GST_VAAPI_IS_SLICE (slice));
205 g_ptr_array_add (picture->slices, slice);
209 do_decode (VADisplay dpy, VAContextID ctx, VABufferID * buf_id, void **buf_ptr)
213 vaapi_unmap_buffer (dpy, *buf_id, buf_ptr);
215 status = vaRenderPicture (dpy, ctx, buf_id, 1);
216 if (!vaapi_check_status (status, "vaRenderPicture()"))
219 /* XXX: vaRenderPicture() is meant to destroy the VA buffer implicitly */
220 vaapi_destroy_buffer (dpy, buf_id);
225 gst_vaapi_picture_decode (GstVaapiPicture * picture)
227 GstVaapiIqMatrix *iq_matrix;
228 GstVaapiBitPlane *bitplane;
229 GstVaapiHuffmanTable *huf_table;
230 GstVaapiProbabilityTable *prob_table;
231 VADisplay va_display;
232 VAContextID va_context;
236 g_return_val_if_fail (GST_VAAPI_IS_PICTURE (picture), FALSE);
238 va_display = GET_VA_DISPLAY (picture);
239 va_context = GET_VA_CONTEXT (picture);
241 GST_DEBUG ("decode picture 0x%08x", picture->surface_id);
243 status = vaBeginPicture (va_display, va_context, picture->surface_id);
244 if (!vaapi_check_status (status, "vaBeginPicture()"))
247 if (!do_decode (va_display, va_context, &picture->param_id, &picture->param))
250 iq_matrix = picture->iq_matrix;
251 if (iq_matrix && !do_decode (va_display, va_context,
252 &iq_matrix->param_id, &iq_matrix->param))
255 bitplane = picture->bitplane;
256 if (bitplane && !do_decode (va_display, va_context,
257 &bitplane->data_id, (void **) &bitplane->data))
260 huf_table = picture->huf_table;
261 if (huf_table && !do_decode (va_display, va_context,
262 &huf_table->param_id, (void **) &huf_table->param))
265 prob_table = picture->prob_table;
266 if (prob_table && !do_decode (va_display, va_context,
267 &prob_table->param_id, (void **) &prob_table->param))
270 for (i = 0; i < picture->slices->len; i++) {
271 GstVaapiSlice *const slice = g_ptr_array_index (picture->slices, i);
272 VABufferID va_buffers[2];
274 huf_table = slice->huf_table;
275 if (huf_table && !do_decode (va_display, va_context,
276 &huf_table->param_id, (void **) &huf_table->param))
279 vaapi_unmap_buffer (va_display, slice->param_id, NULL);
280 va_buffers[0] = slice->param_id;
281 va_buffers[1] = slice->data_id;
283 status = vaRenderPicture (va_display, va_context, va_buffers, 2);
284 if (!vaapi_check_status (status, "vaRenderPicture()"))
287 vaapi_destroy_buffer (va_display, &slice->param_id);
288 vaapi_destroy_buffer (va_display, &slice->data_id);
291 status = vaEndPicture (va_display, va_context);
292 if (!vaapi_check_status (status, "vaEndPicture()"))
297 /* Mark picture as output for internal purposes only. Don't push frame out */
299 do_output_internal (GstVaapiPicture * picture)
301 if (GST_VAAPI_PICTURE_IS_OUTPUT (picture))
304 gst_video_codec_frame_clear (&picture->frame);
305 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_OUTPUT);
309 do_output (GstVaapiPicture * picture)
311 GstVideoCodecFrame *const out_frame = picture->frame;
312 GstVaapiSurfaceProxy *proxy;
315 if (GST_VAAPI_PICTURE_IS_OUTPUT (picture))
321 proxy = gst_vaapi_surface_proxy_ref (picture->proxy);
323 if (picture->has_crop_rect)
324 gst_vaapi_surface_proxy_set_crop_rect (proxy, &picture->crop_rect);
326 gst_video_codec_frame_set_user_data (out_frame,
327 proxy, (GDestroyNotify) gst_vaapi_mini_object_unref);
329 out_frame->pts = picture->pts;
331 if (GST_VAAPI_PICTURE_IS_SKIPPED (picture))
332 GST_VIDEO_CODEC_FRAME_FLAG_SET (out_frame,
333 GST_VIDEO_CODEC_FRAME_FLAG_DECODE_ONLY);
335 if (GST_VAAPI_PICTURE_IS_INTERLACED (picture)) {
336 flags |= GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED;
337 if (GST_VAAPI_PICTURE_IS_TFF (picture))
338 flags |= GST_VAAPI_SURFACE_PROXY_FLAG_TFF;
339 if (GST_VAAPI_PICTURE_IS_ONEFIELD (picture))
340 flags |= GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD;
342 GST_VAAPI_SURFACE_PROXY_FLAG_SET (proxy, flags);
344 gst_vaapi_decoder_push_frame (GET_DECODER (picture), out_frame);
345 gst_video_codec_frame_clear (&picture->frame);
347 GST_VAAPI_PICTURE_FLAG_SET (picture, GST_VAAPI_PICTURE_FLAG_OUTPUT);
352 gst_vaapi_picture_output (GstVaapiPicture * picture)
354 g_return_val_if_fail (GST_VAAPI_IS_PICTURE (picture), FALSE);
356 if (G_UNLIKELY (picture->parent_picture)) {
357 /* Emit the first field to GstVideoDecoder so that to release
358 the underlying GstVideoCodecFrame. However, mark this
359 picture as skipped so that to not display it */
360 GstVaapiPicture *const parent_picture = picture->parent_picture;
362 if (!GST_VAAPI_PICTURE_IS_INTERLACED (parent_picture))
364 if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD (parent_picture))
366 if (parent_picture->frame == picture->frame)
367 do_output_internal (parent_picture);
369 GST_VAAPI_PICTURE_FLAG_SET (parent_picture,
370 GST_VAAPI_PICTURE_FLAG_SKIPPED);
371 if (!do_output (parent_picture))
376 return do_output (picture);
380 gst_vaapi_picture_set_crop_rect (GstVaapiPicture * picture,
381 const GstVaapiRectangle * crop_rect)
383 g_return_if_fail (GST_VAAPI_IS_PICTURE (picture));
385 picture->has_crop_rect = crop_rect != NULL;
386 if (picture->has_crop_rect)
387 picture->crop_rect = *crop_rect;
390 /* ------------------------------------------------------------------------- */
392 /* ------------------------------------------------------------------------- */
394 GST_VAAPI_CODEC_DEFINE_TYPE (GstVaapiSlice, gst_vaapi_slice);
397 gst_vaapi_slice_destroy (GstVaapiSlice * slice)
399 VADisplay const va_display = GET_VA_DISPLAY (slice);
401 gst_vaapi_codec_object_replace (&slice->huf_table, NULL);
403 vaapi_destroy_buffer (va_display, &slice->data_id);
404 vaapi_destroy_buffer (va_display, &slice->param_id);
409 gst_vaapi_slice_create (GstVaapiSlice * slice,
410 const GstVaapiCodecObjectConstructorArgs * args)
412 VASliceParameterBufferBase *slice_param;
415 slice->param_id = VA_INVALID_ID;
416 slice->data_id = VA_INVALID_ID;
418 success = vaapi_create_buffer (GET_VA_DISPLAY (slice), GET_VA_CONTEXT (slice),
419 VASliceDataBufferType, args->data_size, args->data, &slice->data_id,
424 success = vaapi_create_buffer (GET_VA_DISPLAY (slice), GET_VA_CONTEXT (slice),
425 VASliceParameterBufferType, args->param_size, args->param,
426 &slice->param_id, &slice->param);
430 slice_param = slice->param;
431 slice_param->slice_data_size = args->data_size;
432 slice_param->slice_data_offset = 0;
433 slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
438 gst_vaapi_slice_new (GstVaapiDecoder * decoder,
439 gconstpointer param, guint param_size, const guchar * data, guint data_size)
441 GstVaapiCodecObject *object;
443 object = gst_vaapi_codec_object_new (&GstVaapiSliceClass,
444 GST_VAAPI_CODEC_BASE (decoder), param, param_size, data, data_size, 0);
445 return GST_VAAPI_SLICE_CAST (object);