2 * gstvaapidecode.c - VA-API video decoder
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Copyright (C) 2011-2013 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:gstvaapidecode
25 * @short_description: A VA-API based video decoder
27 * vaapidecode decodes from raw bitstreams to surfaces suitable for
28 * the vaapisink element.
31 #include "gst/vaapi/sysdeps.h"
32 #include <gst/vaapi/gstvaapidisplay.h>
33 #include <gst/video/videocontext.h>
35 #include "gstvaapidecode.h"
36 #include "gstvaapipluginutil.h"
37 #include "gstvaapivideobuffer.h"
38 #if GST_CHECK_VERSION(1,0,0)
39 #include "gstvaapivideobufferpool.h"
40 #include "gstvaapivideomemory.h"
43 #include <gst/vaapi/gstvaapidecoder_h264.h>
44 #include <gst/vaapi/gstvaapidecoder_jpeg.h>
45 #include <gst/vaapi/gstvaapidecoder_mpeg2.h>
46 #include <gst/vaapi/gstvaapidecoder_mpeg4.h>
47 #include <gst/vaapi/gstvaapidecoder_vc1.h>
49 #define GST_PLUGIN_NAME "vaapidecode"
50 #define GST_PLUGIN_DESC "A VA-API based video decoder"
52 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
53 #define GST_CAT_DEFAULT gst_debug_vaapidecode
55 /* Default templates */
56 #define GST_CAPS_CODEC(CODEC) CODEC "; "
58 static const char gst_vaapidecode_sink_caps_str[] =
59 GST_CAPS_CODEC("video/mpeg, mpegversion=2, systemstream=(boolean)false")
60 GST_CAPS_CODEC("video/mpeg, mpegversion=4")
61 GST_CAPS_CODEC("video/x-divx")
62 GST_CAPS_CODEC("video/x-xvid")
63 GST_CAPS_CODEC("video/x-h263")
64 GST_CAPS_CODEC("video/x-h264")
65 GST_CAPS_CODEC("video/x-wmv")
66 GST_CAPS_CODEC("image/jpeg")
69 static const char gst_vaapidecode_src_caps_str[] =
70 GST_VAAPI_SURFACE_CAPS;
72 static GstStaticPadTemplate gst_vaapidecode_sink_factory =
73 GST_STATIC_PAD_TEMPLATE(
77 GST_STATIC_CAPS(gst_vaapidecode_sink_caps_str));
79 static GstStaticPadTemplate gst_vaapidecode_src_factory =
80 GST_STATIC_PAD_TEMPLATE(
84 GST_STATIC_CAPS(gst_vaapidecode_src_caps_str));
86 /* GstImplementsInterface interface */
87 #if !GST_CHECK_VERSION(1,0,0)
89 gst_vaapidecode_implements_interface_supported(
90 GstImplementsInterface *iface,
94 return (type == GST_TYPE_VIDEO_CONTEXT);
98 gst_vaapidecode_implements_iface_init(GstImplementsInterfaceClass *iface)
100 iface->supported = gst_vaapidecode_implements_interface_supported;
104 /* GstVideoContext interface */
106 gst_vaapidecode_set_video_context(GstVideoContext *context, const gchar *type,
109 GstVaapiDecode *decode = GST_VAAPIDECODE (context);
110 gst_vaapi_set_display (type, value, &decode->display);
114 gst_video_context_interface_init(GstVideoContextInterface *iface)
116 iface->set_context = gst_vaapidecode_set_video_context;
119 #define GstVideoContextClass GstVideoContextInterface
120 G_DEFINE_TYPE_WITH_CODE(
123 GST_TYPE_VIDEO_DECODER,
124 #if !GST_CHECK_VERSION(1,0,0)
125 G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
126 gst_vaapidecode_implements_iface_init);
128 G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
129 gst_video_context_interface_init))
132 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
133 GstVideoCodecState *ref_state);
136 gst_vaapi_decoder_notify_caps(GObject *obj, GParamSpec *pspec, void *user_data)
138 GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data);
140 g_assert(decode->decoder == GST_VAAPI_DECODER(obj));
142 gst_vaapidecode_update_src_caps(decode,
143 gst_vaapi_decoder_get_codec_state(decode->decoder));
146 static inline gboolean
147 gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
149 gst_caps_replace(&decode->sinkpad_caps, caps);
154 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
155 GstVideoCodecState *ref_state)
157 GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
158 GstVideoCodecState *state;
159 GstVideoInfo *vi, vis;
161 state = gst_video_decoder_set_output_state(vdec,
162 GST_VIDEO_INFO_FORMAT(&ref_state->info),
163 ref_state->info.width, ref_state->info.height, ref_state);
168 if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
169 gst_video_info_init(&vis);
170 gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_NV12,
171 GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
174 gst_video_codec_state_unref(state);
176 /* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not
177 reconstruct suitable caps for "encoded" video formats */
178 state->caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
182 gst_caps_set_simple(state->caps,
183 "type", G_TYPE_STRING, "vaapi",
184 "opengl", G_TYPE_BOOLEAN, USE_GLX,
185 "width", G_TYPE_INT, vi->width,
186 "height", G_TYPE_INT, vi->height,
187 "framerate", GST_TYPE_FRACTION, vi->fps_n, vi->fps_d,
188 "pixel-aspect-ratio", GST_TYPE_FRACTION, vi->par_n, vi->par_d,
191 if (GST_VIDEO_INFO_IS_INTERLACED(vi)) {
192 GstStructure * const structure =
193 gst_caps_get_structure(state->caps, 0);
194 gst_structure_set_interlaced(structure, TRUE);
196 gst_caps_replace(&decode->srcpad_caps, state->caps);
201 gst_vaapidecode_release(GstVaapiDecode *decode)
203 g_mutex_lock(&decode->decoder_mutex);
204 g_cond_signal(&decode->decoder_ready);
205 g_mutex_unlock(&decode->decoder_mutex);
209 gst_vaapidecode_decode_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
211 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
212 GstVaapiDecoderStatus status;
216 if (!decode->render_time_base)
217 decode->render_time_base = g_get_monotonic_time();
218 end_time = decode->render_time_base;
219 end_time += GST_TIME_AS_USECONDS(decode->last_buffer_time);
220 end_time += G_TIME_SPAN_SECOND;
222 /* Decode current frame */
224 status = gst_vaapi_decoder_decode(decode->decoder, frame);
225 if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
226 gboolean was_signalled;
227 g_mutex_lock(&decode->decoder_mutex);
228 was_signalled = g_cond_wait_until(
229 &decode->decoder_ready,
230 &decode->decoder_mutex,
233 g_mutex_unlock(&decode->decoder_mutex);
236 goto error_decode_timeout;
238 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
245 error_decode_timeout:
247 GST_WARNING("decode timeout. Decoder required a VA surface but none "
248 "got available within one second");
253 GST_ERROR("decode error %d", status);
255 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
256 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
257 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
258 ret = GST_FLOW_NOT_SUPPORTED;
264 gst_video_decoder_drop_frame(vdec, frame);
270 gst_vaapidecode_push_decoded_frames(GstVideoDecoder *vdec)
272 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
273 GstVaapiSurfaceProxy *proxy;
274 GstVaapiDecoderStatus status;
275 GstVaapiVideoMeta *meta;
276 GstVideoCodecFrame *out_frame;
280 /* Output all decoded frames */
282 status = gst_vaapi_decoder_get_frame(decode->decoder, &out_frame);
283 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
286 if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(out_frame)) {
287 proxy = gst_video_codec_frame_get_user_data(out_frame);
289 gst_vaapi_surface_proxy_set_destroy_notify(proxy,
290 (GDestroyNotify)gst_vaapidecode_release, decode);
292 #if GST_CHECK_VERSION(1,0,0)
293 ret = gst_video_decoder_allocate_output_frame(vdec, out_frame);
294 if (ret != GST_FLOW_OK)
295 goto error_create_buffer;
297 meta = gst_buffer_get_vaapi_video_meta(out_frame->output_buffer);
300 gst_vaapi_video_meta_set_surface_proxy(meta, proxy);
302 flags = gst_vaapi_surface_proxy_get_flags(proxy);
303 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) {
304 guint out_flags = GST_VIDEO_BUFFER_FLAG_INTERLACED;
305 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_TFF)
306 out_flags |= GST_VIDEO_BUFFER_FLAG_TFF;
307 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_RFF)
308 out_flags |= GST_VIDEO_BUFFER_FLAG_RFF;
309 if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD)
310 out_flags |= GST_VIDEO_BUFFER_FLAG_ONEFIELD;
311 GST_BUFFER_FLAG_SET(out_frame->output_buffer, out_flags);
314 out_frame->output_buffer =
315 gst_vaapi_video_buffer_new_with_surface_proxy(proxy);
316 if (!out_frame->output_buffer)
317 goto error_create_buffer;
321 ret = gst_video_decoder_finish_frame(vdec, out_frame);
322 if (ret != GST_FLOW_OK)
323 goto error_commit_buffer;
325 if (GST_CLOCK_TIME_IS_VALID(out_frame->pts))
326 decode->last_buffer_time = out_frame->pts;
327 gst_video_codec_frame_unref(out_frame);
334 const GstVaapiID surface_id =
335 gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
337 GST_ERROR("video sink failed to create video buffer for proxy'ed "
338 "surface %" GST_VAAPI_ID_FORMAT,
339 GST_VAAPI_ID_ARGS(surface_id));
340 gst_video_decoder_drop_frame(vdec, out_frame);
341 gst_video_codec_frame_unref(out_frame);
344 #if GST_CHECK_VERSION(1,0,0)
347 GST_ERROR("failed to get vaapi video meta attached to video buffer");
348 gst_video_decoder_drop_frame(vdec, out_frame);
349 gst_video_codec_frame_unref(out_frame);
355 GST_DEBUG("video sink rejected the video buffer (error %d)", ret);
356 gst_video_codec_frame_unref(out_frame);
362 gst_vaapidecode_handle_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
366 /* Purge all pending frames we might have already. This helps
367 release VA surfaces as early as possible for _decode_frame() */
368 ret = gst_vaapidecode_push_decoded_frames(vdec);
369 if (ret != GST_FLOW_OK)
372 ret = gst_vaapidecode_decode_frame(vdec, frame);
373 if (ret != GST_FLOW_OK)
376 /* Purge any pending frame thay may have been decoded already */
377 return gst_vaapidecode_push_decoded_frames(vdec);
381 gst_vaapidecode_finish(GstVideoDecoder *vdec)
383 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
384 GstVaapiDecoderStatus status;
386 status = gst_vaapi_decoder_flush(decode->decoder);
387 if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
389 return gst_vaapidecode_push_decoded_frames(vdec);
394 GST_ERROR("failed to flush decoder (status %d)", status);
399 #if GST_CHECK_VERSION(1,0,0)
401 gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
403 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
404 GstCaps *caps = NULL;
406 GstStructure *config;
408 guint size, min, max;
409 gboolean need_pool, update_pool;
411 gst_query_parse_allocation(query, &caps, &need_pool);
416 gst_video_info_init(&vi);
417 gst_video_info_from_caps(&vi, caps);
418 if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED)
419 gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_NV12,
420 GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
422 g_return_val_if_fail(decode->display != NULL, FALSE);
424 if (gst_query_get_n_allocation_pools(query) > 0) {
425 gst_query_parse_nth_allocation_pool(query, 0, &pool, &size, &min, &max);
426 size = MAX(size, vi.size);
436 if (!pool || !gst_buffer_pool_has_option(pool,
437 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
438 GST_INFO("no pool or doesn't support GstVaapiVideoMeta, "
440 pool = gst_vaapi_video_buffer_pool_new(decode->display);
442 goto error_create_pool;
444 config = gst_buffer_pool_get_config(pool);
445 gst_buffer_pool_config_set_params(config, caps, size, min, max);
446 gst_buffer_pool_config_add_option(config,
447 GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
448 gst_buffer_pool_set_config(pool, config);
452 gst_query_set_nth_allocation_pool(query, 0, pool, size, min, max);
454 gst_query_add_allocation_pool(query, pool, size, min, max);
456 g_object_unref(pool);
462 GST_ERROR("no caps specified");
467 GST_ERROR("failed to create buffer pool");
473 static inline gboolean
474 gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
476 return gst_vaapi_ensure_display(decode, GST_VAAPI_DISPLAY_TYPE_ANY,
481 gst_vaapi_codec_from_caps(GstCaps *caps)
483 return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps));
487 gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
489 GstVaapiDisplay *dpy;
491 if (!gst_vaapidecode_ensure_display(decode))
493 dpy = decode->display;
495 switch (gst_vaapi_codec_from_caps(caps)) {
496 case GST_VAAPI_CODEC_MPEG2:
497 decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
499 case GST_VAAPI_CODEC_MPEG4:
500 case GST_VAAPI_CODEC_H263:
501 decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
503 case GST_VAAPI_CODEC_H264:
504 decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
506 case GST_VAAPI_CODEC_WMV3:
507 case GST_VAAPI_CODEC_VC1:
508 decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
511 case GST_VAAPI_CODEC_JPEG:
512 decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
516 decode->decoder = NULL;
519 if (!decode->decoder)
523 G_OBJECT(decode->decoder),
525 G_CALLBACK(gst_vaapi_decoder_notify_caps),
529 decode->decoder_caps = gst_caps_ref(caps);
534 gst_vaapidecode_destroy(GstVaapiDecode *decode)
536 g_clear_object(&decode->decoder);
537 gst_caps_replace(&decode->decoder_caps, NULL);
538 gst_vaapidecode_release(decode);
542 gst_vaapidecode_reset_full(GstVaapiDecode *decode, GstCaps *caps, gboolean hard)
546 /* Reset timers if hard reset was requested (e.g. seek) */
548 decode->render_time_base = 0;
549 decode->last_buffer_time = 0;
552 /* Only reset decoder if codec type changed */
553 else if (decode->decoder && decode->decoder_caps) {
554 if (gst_caps_is_always_compatible(caps, decode->decoder_caps))
556 codec = gst_vaapi_codec_from_caps(caps);
557 if (codec == gst_vaapi_decoder_get_codec(decode->decoder))
561 gst_vaapidecode_destroy(decode);
562 return gst_vaapidecode_create(decode, caps);
566 gst_vaapidecode_finalize(GObject *object)
568 GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
570 gst_vaapidecode_destroy(decode);
572 gst_caps_replace(&decode->sinkpad_caps, NULL);
573 gst_caps_replace(&decode->srcpad_caps, NULL);
574 gst_caps_replace(&decode->allowed_caps, NULL);
576 g_clear_object(&decode->display);
578 g_cond_clear(&decode->decoder_ready);
579 g_mutex_clear(&decode->decoder_mutex);
581 G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
585 gst_vaapidecode_open(GstVideoDecoder *vdec)
587 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
588 GstVaapiDisplay * const old_display = decode->display;
591 /* Let GstVideoContext ask for a proper display to its neighbours */
592 /* Note: steal old display that may be allocated from get_caps()
593 so that to retain a reference to it, thus avoiding extra
594 initialization steps if we turn out to simply re-use the
595 existing (cached) VA display */
596 decode->display = NULL;
597 success = gst_vaapidecode_ensure_display(decode);
598 g_clear_object(&old_display);
603 gst_vaapidecode_close(GstVideoDecoder *vdec)
605 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
607 gst_vaapidecode_destroy(decode);
608 g_clear_object(&decode->display);
613 gst_vaapidecode_reset(GstVideoDecoder *vdec, gboolean hard)
615 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
617 return gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, hard);
621 gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state)
623 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
625 if (!gst_vaapidecode_update_sink_caps(decode, state->caps))
627 if (!gst_vaapidecode_update_src_caps(decode, state))
629 if (!gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, FALSE))
635 gst_vaapidecode_parse(GstVideoDecoder *vdec,
636 GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
638 GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
639 GstVaapiDecoderStatus status;
644 status = gst_vaapi_decoder_parse(decode->decoder, frame,
645 adapter, at_eos, &got_unit_size, &got_frame);
648 case GST_VAAPI_DECODER_STATUS_SUCCESS:
649 if (got_unit_size > 0)
650 gst_video_decoder_add_to_frame(vdec, got_unit_size);
652 ret = gst_video_decoder_have_frame(vdec);
656 case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
657 ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
659 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
660 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
661 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
662 GST_WARNING("parse error %d", status);
663 ret = GST_FLOW_NOT_SUPPORTED;
666 GST_ERROR("parse error %d", status);
674 gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
676 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
677 GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
678 GstVideoDecoderClass * const vdec_class = GST_VIDEO_DECODER_CLASS(klass);
679 GstPadTemplate *pad_template;
681 GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
682 GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
684 object_class->finalize = gst_vaapidecode_finalize;
686 vdec_class->open = GST_DEBUG_FUNCPTR(gst_vaapidecode_open);
687 vdec_class->close = GST_DEBUG_FUNCPTR(gst_vaapidecode_close);
688 vdec_class->set_format = GST_DEBUG_FUNCPTR(gst_vaapidecode_set_format);
689 vdec_class->reset = GST_DEBUG_FUNCPTR(gst_vaapidecode_reset);
690 vdec_class->parse = GST_DEBUG_FUNCPTR(gst_vaapidecode_parse);
691 vdec_class->handle_frame = GST_DEBUG_FUNCPTR(gst_vaapidecode_handle_frame);
692 vdec_class->finish = GST_DEBUG_FUNCPTR(gst_vaapidecode_finish);
694 #if GST_CHECK_VERSION(1,0,0)
695 vdec_class->decide_allocation =
696 GST_DEBUG_FUNCPTR(gst_vaapidecode_decide_allocation);
699 gst_element_class_set_static_metadata(element_class,
701 "Codec/Decoder/Video",
703 "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
706 pad_template = gst_static_pad_template_get(&gst_vaapidecode_sink_factory);
707 gst_element_class_add_pad_template(element_class, pad_template);
710 pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
711 gst_element_class_add_pad_template(element_class, pad_template);
715 gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
717 GstCaps *decode_caps;
718 guint i, n_decode_caps;
720 if (decode->allowed_caps)
723 if (!gst_vaapidecode_ensure_display(decode))
724 goto error_no_display;
726 decode_caps = gst_vaapi_display_get_decode_caps(decode->display);
728 goto error_no_decode_caps;
729 n_decode_caps = gst_caps_get_size(decode_caps);
731 decode->allowed_caps = gst_caps_new_empty();
732 if (!decode->allowed_caps)
733 goto error_no_memory;
735 for (i = 0; i < n_decode_caps; i++) {
736 GstStructure *structure;
737 structure = gst_caps_get_structure(decode_caps, i);
740 structure = gst_structure_copy(structure);
743 gst_structure_remove_field(structure, "profile");
746 "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
747 "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
750 decode->allowed_caps =
751 gst_caps_merge_structure(decode->allowed_caps, structure);
754 gst_caps_unref(decode_caps);
760 GST_ERROR("failed to retrieve VA display");
763 error_no_decode_caps:
765 GST_ERROR("failed to retrieve VA decode caps");
770 GST_ERROR("failed to allocate allowed-caps set");
771 gst_caps_unref(decode_caps);
777 gst_vaapidecode_get_caps(GstPad *pad)
779 GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
781 if (!gst_vaapidecode_ensure_allowed_caps(decode))
782 return gst_caps_new_empty();
784 return gst_caps_ref(decode->allowed_caps);
788 gst_vaapidecode_query(GST_PAD_QUERY_FUNCTION_ARGS)
790 GstVaapiDecode * const decode =
791 GST_VAAPIDECODE(gst_pad_get_parent_element(pad));
794 GST_DEBUG("sharing display %p", decode->display);
796 if (gst_vaapi_reply_to_query(query, decode->display))
798 else if (GST_PAD_IS_SINK(pad)) {
799 switch (GST_QUERY_TYPE(query)) {
800 #if GST_CHECK_VERSION(1,0,0)
801 case GST_QUERY_CAPS: {
802 GstCaps * const caps = gst_vaapidecode_get_caps(pad);
803 gst_query_set_caps_result(query, caps);
804 gst_caps_unref(caps);
810 res = GST_PAD_QUERY_FUNCTION_CALL(decode->sinkpad_query,
811 decode->sinkpad, parent, query);
816 res = GST_PAD_QUERY_FUNCTION_CALL(decode->srcpad_query,
817 decode->srcpad, parent, query);
819 g_object_unref(decode);
824 gst_vaapidecode_init(GstVaapiDecode *decode)
826 GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
828 decode->display = NULL;
829 decode->decoder = NULL;
830 decode->decoder_caps = NULL;
831 decode->allowed_caps = NULL;
832 decode->render_time_base = 0;
833 decode->last_buffer_time = 0;
835 g_mutex_init(&decode->decoder_mutex);
836 g_cond_init(&decode->decoder_ready);
838 gst_video_decoder_set_packetized(vdec, FALSE);
840 /* Pad through which data comes in to the element */
841 decode->sinkpad = GST_VIDEO_DECODER_SINK_PAD(vdec);
842 decode->sinkpad_query = GST_PAD_QUERYFUNC(decode->sinkpad);
843 gst_pad_set_query_function(decode->sinkpad, gst_vaapidecode_query);
844 #if !GST_CHECK_VERSION(1,0,0)
845 gst_pad_set_getcaps_function(decode->sinkpad, gst_vaapidecode_get_caps);
848 /* Pad through which data goes out of the element */
849 decode->srcpad = GST_VIDEO_DECODER_SRC_PAD(vdec);
850 decode->srcpad_query = GST_PAD_QUERYFUNC(decode->srcpad);
851 gst_pad_set_query_function(decode->srcpad, gst_vaapidecode_query);