2
* gstvaapidecoder.c - VA decoder abstraction
4
* Copyright (C) 2010-2011 Splitted-Desktop Systems
5
* Copyright (C) 2011-2012 Intel Corporation
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public License
9
* as published by the Free Software Foundation; either version 2.1
10
* of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
* Boston, MA 02110-1301 USA
24
* SECTION:gstvaapidecoder
25
* @short_description: VA decoder abstraction
29
#include "gstvaapicompat.h"
30
#include "gstvaapidecoder.h"
31
#include "gstvaapidecoder_priv.h"
32
#include "gstvaapiutils.h"
33
#include "gstvaapi_priv.h"
36
#include "gstvaapidebug.h"
38
G_DEFINE_TYPE(GstVaapiDecoder, gst_vaapi_decoder, G_TYPE_OBJECT);
48
destroy_buffer(GstBuffer *buffer)
50
gst_buffer_unref(buffer);
54
push_buffer(GstVaapiDecoder *decoder, GstBuffer *buffer)
56
GstVaapiDecoderPrivate * const priv = decoder->priv;
59
buffer = gst_buffer_new();
62
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_EOS);
65
GST_DEBUG("queue encoded data buffer %p (%d bytes)",
66
buffer, GST_BUFFER_SIZE(buffer));
68
g_queue_push_tail(priv->buffers, buffer);
73
push_back_buffer(GstVaapiDecoder *decoder, GstBuffer *buffer)
75
GstVaapiDecoderPrivate * const priv = decoder->priv;
77
GST_DEBUG("requeue encoded data buffer %p (%d bytes)",
78
buffer, GST_BUFFER_SIZE(buffer));
80
g_queue_push_head(priv->buffers, buffer);
84
pop_buffer(GstVaapiDecoder *decoder)
86
GstVaapiDecoderPrivate * const priv = decoder->priv;
89
buffer = g_queue_pop_head(priv->buffers);
93
GST_DEBUG("dequeue buffer %p for decoding (%d bytes)",
94
buffer, GST_BUFFER_SIZE(buffer));
99
static GstVaapiDecoderStatus
100
decode_step(GstVaapiDecoder *decoder)
102
GstVaapiDecoderPrivate * const priv = decoder->priv;
103
GstVaapiDecoderStatus status;
106
/* Decoding will fail if there is no surface left */
108
gst_vaapi_context_get_surface_count(priv->context) == 0)
109
return GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE;
112
buffer = pop_buffer(decoder);
114
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
116
status = GST_VAAPI_DECODER_GET_CLASS(decoder)->decode(decoder, buffer);
117
GST_DEBUG("decode frame (status = %d)", status);
118
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS && GST_BUFFER_IS_EOS(buffer))
119
status = GST_VAAPI_DECODER_STATUS_END_OF_STREAM;
120
gst_buffer_unref(buffer);
121
} while (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA);
126
push_surface(GstVaapiDecoder *decoder, GstVaapiSurfaceProxy *proxy)
128
GstVaapiDecoderPrivate * const priv = decoder->priv;
130
GST_DEBUG("queue decoded surface %" GST_VAAPI_ID_FORMAT,
131
GST_VAAPI_ID_ARGS(gst_vaapi_surface_proxy_get_surface_id(proxy)));
133
g_queue_push_tail(priv->surfaces, proxy);
136
static inline GstVaapiSurfaceProxy *
137
pop_surface(GstVaapiDecoder *decoder)
139
GstVaapiDecoderPrivate * const priv = decoder->priv;
141
return g_queue_pop_head(priv->surfaces);
145
set_codec_data(GstVaapiDecoder *decoder, GstBuffer *codec_data)
147
GstVaapiDecoderPrivate * const priv = decoder->priv;
149
if (priv->codec_data) {
150
gst_buffer_unref(priv->codec_data);
151
priv->codec_data = NULL;
155
priv->codec_data = gst_buffer_ref(codec_data);
159
set_caps(GstVaapiDecoder *decoder, GstCaps *caps)
161
GstVaapiDecoderPrivate * const priv = decoder->priv;
162
GstStructure * const structure = gst_caps_get_structure(caps, 0);
163
GstVaapiProfile profile;
164
const GValue *v_codec_data;
167
profile = gst_vaapi_profile_from_caps(caps);
171
priv->caps = gst_caps_copy(caps);
173
priv->codec = gst_vaapi_profile_get_codec(profile);
177
if (gst_structure_get_int(structure, "width", &v1))
179
if (gst_structure_get_int(structure, "height", &v2))
182
if (gst_structure_get_fraction(structure, "framerate", &v1, &v2)) {
187
if (gst_structure_get_fraction(structure, "pixel-aspect-ratio", &v1, &v2)) {
192
v_codec_data = gst_structure_get_value(structure, "codec_data");
194
set_codec_data(decoder, gst_value_get_buffer(v_codec_data));
198
clear_queue(GQueue *q, GDestroyNotify destroy)
200
while (!g_queue_is_empty(q))
201
destroy(g_queue_pop_head(q));
205
gst_vaapi_decoder_finalize(GObject *object)
207
GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(object);
208
GstVaapiDecoderPrivate * const priv = decoder->priv;
210
set_codec_data(decoder, NULL);
213
gst_caps_unref(priv->caps);
218
g_object_unref(priv->context);
219
priv->context = NULL;
220
priv->va_context = VA_INVALID_ID;
224
clear_queue(priv->buffers, (GDestroyNotify)destroy_buffer);
225
g_queue_free(priv->buffers);
226
priv->buffers = NULL;
229
if (priv->surfaces) {
230
clear_queue(priv->surfaces, (GDestroyNotify)g_object_unref);
231
g_queue_free(priv->surfaces);
232
priv->surfaces = NULL;
236
g_object_unref(priv->display);
237
priv->display = NULL;
238
priv->va_display = NULL;
241
G_OBJECT_CLASS(gst_vaapi_decoder_parent_class)->finalize(object);
245
gst_vaapi_decoder_set_property(
252
GstVaapiDecoder * const decoder = GST_VAAPI_DECODER(object);
253
GstVaapiDecoderPrivate * const priv = decoder->priv;
257
priv->display = g_object_ref(g_value_get_object(value));
259
priv->va_display = gst_vaapi_display_get_display(priv->display);
261
priv->va_display = NULL;
264
set_caps(decoder, g_value_get_pointer(value));
267
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
273
gst_vaapi_decoder_get_property(
280
GstVaapiDecoderPrivate * const priv = GST_VAAPI_DECODER(object)->priv;
284
g_value_set_object(value, priv->display);
287
gst_value_set_caps(value, priv->caps);
290
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
296
gst_vaapi_decoder_class_init(GstVaapiDecoderClass *klass)
298
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
300
g_type_class_add_private(klass, sizeof(GstVaapiDecoderPrivate));
302
object_class->finalize = gst_vaapi_decoder_finalize;
303
object_class->set_property = gst_vaapi_decoder_set_property;
304
object_class->get_property = gst_vaapi_decoder_get_property;
307
* GstVaapiDecoder:display:
309
* The #GstVaapiDisplay this decoder is bound to.
311
g_object_class_install_property
314
g_param_spec_object("display",
316
"The GstVaapiDisplay this decoder is bound to",
317
GST_VAAPI_TYPE_DISPLAY,
318
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
320
g_object_class_install_property
323
g_param_spec_pointer("caps",
326
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
330
gst_vaapi_decoder_init(GstVaapiDecoder *decoder)
332
GstVaapiDecoderPrivate *priv = GST_VAAPI_DECODER_GET_PRIVATE(decoder);
334
decoder->priv = priv;
335
priv->display = NULL;
336
priv->va_display = NULL;
337
priv->context = NULL;
338
priv->va_context = VA_INVALID_ID;
341
priv->codec_data = NULL;
348
priv->buffers = g_queue_new();
349
priv->surfaces = g_queue_new();
353
* gst_vaapi_decoder_get_caps:
354
* @decoder: a #GstVaapiDecoder
356
* Retrieves the @decoder caps. The deocder owns the returned caps, so
357
* use gst_caps_ref() whenever necessary.
359
* Return value: the @decoder caps
362
gst_vaapi_decoder_get_caps(GstVaapiDecoder *decoder)
364
return decoder->priv->caps;
368
* gst_vaapi_decoder_put_buffer:
369
* @decoder: a #GstVaapiDecoder
372
* Queues a #GstBuffer to the HW decoder. The decoder holds a
375
* Caller can notify an End-Of-Stream with @buf set to %NULL.
377
* Return value: %TRUE on success
380
gst_vaapi_decoder_put_buffer(GstVaapiDecoder *decoder, GstBuffer *buf)
382
g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), FALSE);
384
return push_buffer(decoder, buf ? gst_buffer_ref(buf) : NULL);
388
* gst_vaapi_decoder_get_surface:
389
* @decoder: a #GstVaapiDecoder
390
* @pstatus: return location for the decoder status, or %NULL
392
* Flushes encoded buffers to the decoder and returns a decoded
395
* Return value: a #GstVaapiSurfaceProxy holding the decoded surface,
396
* or %NULL if none is available (e.g. an error). Caller owns the
397
* returned object. g_object_unref() after usage.
399
GstVaapiSurfaceProxy *
400
gst_vaapi_decoder_get_surface(
401
GstVaapiDecoder *decoder,
402
GstVaapiDecoderStatus *pstatus
405
GstVaapiSurfaceProxy *proxy;
406
GstVaapiDecoderStatus status;
409
*pstatus = GST_VAAPI_DECODER_STATUS_ERROR_UNKNOWN;
411
g_return_val_if_fail(GST_VAAPI_IS_DECODER(decoder), NULL);
413
proxy = pop_surface(decoder);
416
status = decode_step(decoder);
417
} while (status == GST_VAAPI_DECODER_STATUS_SUCCESS);
418
proxy = pop_surface(decoder);
422
status = GST_VAAPI_DECODER_STATUS_SUCCESS;
430
gst_vaapi_decoder_set_picture_size(
431
GstVaapiDecoder *decoder,
436
GstVaapiDecoderPrivate * const priv = decoder->priv;
437
gboolean size_changed = FALSE;
439
if (priv->width != width) {
440
GST_DEBUG("picture width changed to %d", width);
442
gst_caps_set_simple(priv->caps, "width", G_TYPE_INT, width, NULL);
446
if (priv->height != height) {
447
GST_DEBUG("picture height changed to %d", height);
448
priv->height = height;
449
gst_caps_set_simple(priv->caps, "height", G_TYPE_INT, height, NULL);
454
g_object_notify(G_OBJECT(decoder), "caps");
458
gst_vaapi_decoder_set_framerate(
459
GstVaapiDecoder *decoder,
464
GstVaapiDecoderPrivate * const priv = decoder->priv;
466
if (!fps_n || !fps_d)
469
if (priv->fps_n != fps_n || priv->fps_d != fps_d) {
470
GST_DEBUG("framerate changed to %u/%u", fps_n, fps_d);
475
"framerate", GST_TYPE_FRACTION, fps_n, fps_d,
478
g_object_notify(G_OBJECT(decoder), "caps");
483
gst_vaapi_decoder_set_pixel_aspect_ratio(
484
GstVaapiDecoder *decoder,
489
GstVaapiDecoderPrivate * const priv = decoder->priv;
491
if (!par_n || !par_d)
494
if (priv->par_n != par_n || priv->par_d != par_d) {
495
GST_DEBUG("pixel-aspect-ratio changed to %u/%u", par_n, par_d);
500
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d,
503
g_object_notify(G_OBJECT(decoder), "caps");
508
gst_vaapi_decoder_ensure_context(
509
GstVaapiDecoder *decoder,
510
GstVaapiProfile profile,
511
GstVaapiEntrypoint entrypoint,
516
GstVaapiDecoderPrivate * const priv = decoder->priv;
518
gst_vaapi_decoder_set_picture_size(decoder, width, height);
521
return gst_vaapi_context_reset(priv->context,
522
profile, entrypoint, width, height);
524
priv->context = gst_vaapi_context_new(
534
priv->va_context = gst_vaapi_context_get_id(priv->context);
539
gst_vaapi_decoder_push_buffer_sub(
540
GstVaapiDecoder *decoder,
546
GstBuffer *subbuffer;
548
subbuffer = gst_buffer_create_sub(buffer, offset, size);
552
push_back_buffer(decoder, subbuffer);
557
gst_vaapi_decoder_push_surface_proxy(
558
GstVaapiDecoder *decoder,
559
GstVaapiSurfaceProxy *proxy
562
return push_surface(decoder, proxy);