2 * gstvaapidecode.c - VA-API video decoder
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: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/vaapi/gstvaapivideobuffer.h>
34 #include <gst/video/videocontext.h>
36 #include "gstvaapidecode.h"
37 #include "gstvaapipluginutil.h"
38 #include "gstvaapipluginbuffer.h"
40 #include <gst/vaapi/gstvaapidecoder_h264.h>
41 #include <gst/vaapi/gstvaapidecoder_jpeg.h>
42 #include <gst/vaapi/gstvaapidecoder_mpeg2.h>
43 #include <gst/vaapi/gstvaapidecoder_mpeg4.h>
44 #include <gst/vaapi/gstvaapidecoder_vc1.h>
46 #define GST_PLUGIN_NAME "vaapidecode"
47 #define GST_PLUGIN_DESC "A VA-API based video decoder"
49 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
50 #define GST_CAT_DEFAULT gst_debug_vaapidecode
52 /* ElementFactory information */
53 static const GstElementDetails gst_vaapidecode_details =
56 "Codec/Decoder/Video",
58 "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
60 /* Default templates */
61 #define GST_CAPS_CODEC(CODEC) CODEC "; "
63 static const char gst_vaapidecode_sink_caps_str[] =
64 GST_CAPS_CODEC("video/mpeg, mpegversion=2, systemstream=(boolean)false")
66 GST_CAPS_CODEC("video/mpeg, mpegversion=4")
67 GST_CAPS_CODEC("video/x-divx")
68 GST_CAPS_CODEC("video/x-xvid")
69 GST_CAPS_CODEC("video/x-h263")
71 GST_CAPS_CODEC("video/x-h264")
72 GST_CAPS_CODEC("video/x-wmv")
74 GST_CAPS_CODEC("image/jpeg")
78 static const char gst_vaapidecode_src_caps_str[] =
79 GST_VAAPI_SURFACE_CAPS;
81 static GstStaticPadTemplate gst_vaapidecode_sink_factory =
82 GST_STATIC_PAD_TEMPLATE(
86 GST_STATIC_CAPS(gst_vaapidecode_sink_caps_str));
88 static GstStaticPadTemplate gst_vaapidecode_src_factory =
89 GST_STATIC_PAD_TEMPLATE(
93 GST_STATIC_CAPS(gst_vaapidecode_src_caps_str));
96 gst_vaapidecode_implements_iface_init(GstImplementsInterfaceClass *iface);
99 gst_video_context_interface_init(GstVideoContextInterface *iface);
101 #define GstVideoContextClass GstVideoContextInterface
102 G_DEFINE_TYPE_WITH_CODE(
106 G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
107 gst_vaapidecode_implements_iface_init);
108 G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
109 gst_video_context_interface_init))
112 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps);
115 gst_vaapi_decoder_notify_caps(GObject *obj, GParamSpec *pspec, void *user_data)
117 GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data);
120 g_assert(decode->decoder == GST_VAAPI_DECODER(obj));
122 caps = gst_vaapi_decoder_get_caps(decode->decoder);
123 gst_vaapidecode_update_src_caps(decode, caps);
126 static inline gboolean
127 gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
129 if (decode->sinkpad_caps)
130 gst_caps_unref(decode->sinkpad_caps);
131 decode->sinkpad_caps = gst_caps_ref(caps);
136 gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps)
139 GstStructure *structure;
140 const GValue *v_width, *v_height, *v_framerate, *v_par, *v_interlaced;
143 if (!decode->srcpad_caps) {
144 decode->srcpad_caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
145 if (!decode->srcpad_caps)
149 structure = gst_caps_get_structure(caps, 0);
150 v_width = gst_structure_get_value(structure, "width");
151 v_height = gst_structure_get_value(structure, "height");
152 v_framerate = gst_structure_get_value(structure, "framerate");
153 v_par = gst_structure_get_value(structure, "pixel-aspect-ratio");
154 v_interlaced = gst_structure_get_value(structure, "interlaced");
156 structure = gst_caps_get_structure(decode->srcpad_caps, 0);
157 if (v_width && v_height) {
158 gst_structure_set_value(structure, "width", v_width);
159 gst_structure_set_value(structure, "height", v_height);
162 gst_structure_set_value(structure, "framerate", v_framerate);
164 gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
166 gst_structure_set_value(structure, "interlaced", v_interlaced);
168 gst_structure_set(structure, "type", G_TYPE_STRING, "vaapi", NULL);
169 gst_structure_set(structure, "opengl", G_TYPE_BOOLEAN, USE_GLX, NULL);
171 other_caps = gst_caps_copy(decode->srcpad_caps);
172 success = gst_pad_set_caps(decode->srcpad, other_caps);
173 gst_caps_unref(other_caps);
178 gst_vaapidecode_release(GstVaapiDecode *decode, GObject *dead_object)
180 g_mutex_lock(&decode->decoder_mutex);
181 g_cond_signal(&decode->decoder_ready);
182 g_mutex_unlock(&decode->decoder_mutex);
186 gst_vaapidecode_is_valid_time(GstVaapiDecode *decode, gint64 time)
188 if (decode->segment.format != GST_FORMAT_TIME)
190 if (decode->segment.stop != -1 && time != -1 && time > decode->segment.stop)
192 if (decode->segment.start != -1 && time != -1 && time < decode->segment.start)
199 gst_vaapidecode_step(GstVaapiDecode *decode)
201 GstVaapiSurfaceProxy *proxy;
202 GstVaapiDecoderStatus status;
205 GstClockTime timestamp;
206 gboolean try_again = FALSE;
209 proxy = gst_vaapi_decoder_get_surface(decode->decoder, &status, try_again);
212 if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
213 g_mutex_lock(&decode->decoder_mutex);
214 if (decode->escape_decoding){
215 goto handle_escape_decoding;
218 &decode->decoder_ready,
219 &decode->decoder_mutex
221 if (decode->escape_decoding){
222 goto handle_escape_decoding;
224 g_mutex_unlock(&decode->decoder_mutex);
228 if (status != GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA)
230 /* More data is needed */
236 (GWeakNotify)gst_vaapidecode_release,
240 buffer = gst_vaapi_video_buffer_new(decode->display);
242 goto error_create_buffer;
244 timestamp = GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
245 if (GST_CLOCK_TIME_IS_VALID(timestamp) &&
246 !gst_vaapidecode_is_valid_time(decode, (gint64)timestamp)) {
247 g_object_unref(proxy);
251 if (!decode->render_time_base)
252 decode->render_time_base = g_get_monotonic_time();
253 decode->last_buffer_time = timestamp;
255 GST_BUFFER_TIMESTAMP(buffer) = timestamp;
256 GST_BUFFER_DURATION(buffer) = GST_VAAPI_SURFACE_PROXY_DURATION(proxy);
257 gst_buffer_set_caps(buffer, GST_PAD_CAPS(decode->srcpad));
259 if (GST_VAAPI_SURFACE_PROXY_TFF(proxy))
260 GST_BUFFER_FLAG_SET(buffer, GST_VIDEO_BUFFER_TFF);
262 gst_vaapi_video_buffer_set_surface_proxy(
263 GST_VAAPI_VIDEO_BUFFER(buffer),
267 ret = gst_pad_push(decode->srcpad, buffer);
268 if (ret != GST_FLOW_OK)
269 goto error_commit_buffer;
271 g_object_unref(proxy);
276 handle_escape_decoding:
278 g_mutex_unlock(&decode->decoder_mutex);
279 GST_INFO("Escape decoding wait: flush event comes for seek etc.");
280 return GST_FLOW_UNEXPECTED;
284 GST_DEBUG("decode error %d", status);
286 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
287 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
288 case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
289 ret = GST_FLOW_NOT_SUPPORTED;
292 ret = GST_FLOW_UNEXPECTED;
299 const GstVaapiID surface_id =
300 gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy));
302 GST_DEBUG("video sink failed to create video buffer for proxy'ed "
303 "surface %" GST_VAAPI_ID_FORMAT,
304 GST_VAAPI_ID_ARGS(surface_id));
305 g_object_unref(proxy);
306 return GST_FLOW_UNEXPECTED;
310 GST_DEBUG("video sink rejected the video buffer (error %d)", ret);
311 g_object_unref(proxy);
312 return GST_FLOW_UNEXPECTED;
316 static inline gboolean
317 gst_vaapidecode_ensure_display(GstVaapiDecode *decode)
319 return gst_vaapi_ensure_display(decode, GST_VAAPI_DISPLAY_TYPE_ANY,
324 gst_vaapi_codec_from_caps(GstCaps *caps)
326 return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps));
330 gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
332 GstVaapiDisplay *dpy;
334 if (!gst_vaapidecode_ensure_display(decode))
336 dpy = decode->display;
338 switch (gst_vaapi_codec_from_caps(caps)) {
339 case GST_VAAPI_CODEC_MPEG2:
340 decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps);
342 #if USE_MPEG4_DECODER
343 case GST_VAAPI_CODEC_MPEG4:
344 case GST_VAAPI_CODEC_H263:
345 decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps);
348 case GST_VAAPI_CODEC_H264:
349 decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps);
351 case GST_VAAPI_CODEC_WMV3:
352 case GST_VAAPI_CODEC_VC1:
353 decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps);
356 case GST_VAAPI_CODEC_JPEG:
357 decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps);
361 decode->decoder = NULL;
364 if (!decode->decoder)
368 G_OBJECT(decode->decoder),
370 G_CALLBACK(gst_vaapi_decoder_notify_caps),
374 decode->decoder_caps = gst_caps_ref(caps);
379 gst_vaapidecode_destroy(GstVaapiDecode *decode)
381 if (decode->decoder) {
382 (void)gst_vaapi_decoder_put_buffer(decode->decoder, NULL);
383 g_object_unref(decode->decoder);
384 decode->decoder = NULL;
387 if (decode->decoder_caps) {
388 gst_caps_unref(decode->decoder_caps);
389 decode->decoder_caps = NULL;
392 gst_vaapidecode_release(decode, NULL);
396 gst_vaapidecode_reset(GstVaapiDecode *decode, GstCaps *caps)
400 /* Only reset decoder if codec type changed */
401 if (decode->decoder && decode->decoder_caps) {
402 if (gst_caps_is_always_compatible(caps, decode->decoder_caps))
404 codec = gst_vaapi_codec_from_caps(caps);
405 if (codec == gst_vaapi_decoder_get_codec(decode->decoder))
409 gst_vaapidecode_destroy(decode);
410 return gst_vaapidecode_create(decode, caps);
414 gst_vaapidecode_configure_segment(
415 GstVaapiDecode *decode,
420 gdouble rate, applied_rate;
422 gint64 start, stop, time;
424 gst_event_parse_new_segment_full(event, &update, &rate, &applied_rate,
425 &format, &start, &stop, &time);
426 if (format == GST_FORMAT_TIME) {
427 gst_segment_set_newsegment_full(&decode->segment, update, rate, applied_rate,
428 format, start, stop, time);
429 GST_DEBUG("configured new segment, update %d, rate %lf, applied rate %lf, "
430 "format GST_FORMAT_TIME, "
431 "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT ", "
432 "time %" GST_TIME_FORMAT,
433 update, rate, applied_rate,
434 GST_TIME_ARGS(start), GST_TIME_ARGS(stop),
435 GST_TIME_ARGS(time));
440 gst_vaapidecode_flush(GstVaapiDecode *decode)
442 g_return_val_if_fail(decode->decoder, FALSE);
444 if (!gst_vaapi_decoder_put_buffer(decode->decoder, NULL))
446 if (gst_vaapidecode_step(decode) != GST_FLOW_OK)
451 /* GstImplementsInterface interface */
454 gst_vaapidecode_implements_interface_supported(
455 GstImplementsInterface *iface,
459 return (type == GST_TYPE_VIDEO_CONTEXT);
463 gst_vaapidecode_implements_iface_init(GstImplementsInterfaceClass *iface)
465 iface->supported = gst_vaapidecode_implements_interface_supported;
468 /* GstVideoContext interface */
471 gst_vaapidecode_set_video_context(GstVideoContext *context, const gchar *type,
474 GstVaapiDecode *decode = GST_VAAPIDECODE (context);
475 gst_vaapi_set_display (type, value, &decode->display);
479 gst_video_context_interface_init(GstVideoContextInterface *iface)
481 iface->set_context = gst_vaapidecode_set_video_context;
485 gst_vaapidecode_finalize(GObject *object)
487 GstVaapiDecode * const decode = GST_VAAPIDECODE(object);
489 gst_vaapidecode_destroy(decode);
491 if (decode->sinkpad_caps) {
492 gst_caps_unref(decode->sinkpad_caps);
493 decode->sinkpad_caps = NULL;
496 if (decode->srcpad_caps) {
497 gst_caps_unref(decode->srcpad_caps);
498 decode->srcpad_caps = NULL;
501 g_clear_object(&decode->display);
503 if (decode->allowed_caps) {
504 gst_caps_unref(decode->allowed_caps);
505 decode->allowed_caps = NULL;
508 if (decode->delayed_new_seg) {
509 gst_event_unref(decode->delayed_new_seg);
510 decode->delayed_new_seg = NULL;
513 g_cond_clear(&decode->decoder_ready);
514 g_mutex_clear(&decode->decoder_mutex);
516 G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
522 } _GstStateChangeMap;
523 _GstStateChangeMap gst_state_change_string_map[] = {
524 {GST_STATE_CHANGE_NULL_TO_READY, "GST_STATE_CHANGE_NULL_TO_READY"},
525 {GST_STATE_CHANGE_READY_TO_PAUSED, "GST_STATE_CHANGE_READY_TO_PAUSED",},
526 {GST_STATE_CHANGE_PAUSED_TO_PLAYING,"GST_STATE_CHANGE_PAUSED_TO_PLAYING"},
527 {GST_STATE_CHANGE_PLAYING_TO_PAUSED,"GST_STATE_CHANGE_PLAYING_TO_PAUSED"},
528 {GST_STATE_CHANGE_PAUSED_TO_READY, "GST_STATE_CHANGE_PAUSED_TO_READY"},
529 {GST_STATE_CHANGE_READY_TO_NULL, "GST_STATE_CHANGE_READY_TO_NULL"},
530 {-1, "UNDEFINED_STATE_CHANGE"}
533 static GstStateChangeReturn
534 gst_vaapidecode_change_state(GstElement *element, GstStateChange transition)
536 GstVaapiDecode * const decode = GST_VAAPIDECODE(element);
537 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
540 for (i=0; i<sizeof(gst_state_change_string_map)/sizeof(_GstStateChangeMap);i++) {
541 if (gst_state_change_string_map[i].trans == transition)
542 GST_INFO(gst_state_change_string_map[i].trans_name);
545 switch (transition) {
546 case GST_STATE_CHANGE_NULL_TO_READY:
547 decode->is_ready = TRUE;
549 case GST_STATE_CHANGE_READY_TO_PAUSED:
551 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
557 ret = GST_ELEMENT_CLASS(gst_vaapidecode_parent_class)->change_state(element, transition);
558 if (ret != GST_STATE_CHANGE_SUCCESS)
561 switch (transition) {
562 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
564 case GST_STATE_CHANGE_PAUSED_TO_READY:
566 case GST_STATE_CHANGE_READY_TO_NULL:
567 gst_vaapidecode_destroy(decode);
568 g_clear_object(&decode->display);
569 decode->is_ready = FALSE;
574 return GST_STATE_CHANGE_SUCCESS;
578 gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
580 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
581 GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
582 GstPadTemplate *pad_template;
584 GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
585 GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
587 object_class->finalize = gst_vaapidecode_finalize;
589 element_class->change_state = gst_vaapidecode_change_state;
591 gst_element_class_set_details_simple(
593 gst_vaapidecode_details.longname,
594 gst_vaapidecode_details.klass,
595 gst_vaapidecode_details.description,
596 gst_vaapidecode_details.author
600 pad_template = gst_static_pad_template_get(&gst_vaapidecode_sink_factory);
601 gst_element_class_add_pad_template(element_class, pad_template);
602 gst_object_unref(pad_template);
605 pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory);
606 gst_element_class_add_pad_template(element_class, pad_template);
607 gst_object_unref(pad_template);
611 gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode)
613 GstCaps *decode_caps;
614 guint i, n_decode_caps;
616 if (decode->allowed_caps)
619 if (!gst_vaapidecode_ensure_display(decode))
620 goto error_no_display;
622 decode_caps = gst_vaapi_display_get_decode_caps(decode->display);
624 goto error_no_decode_caps;
625 n_decode_caps = gst_caps_get_size(decode_caps);
627 decode->allowed_caps = gst_caps_new_empty();
628 if (!decode->allowed_caps)
629 goto error_no_memory;
631 for (i = 0; i < n_decode_caps; i++) {
632 GstStructure *structure;
633 structure = gst_caps_get_structure(decode_caps, i);
636 structure = gst_structure_copy(structure);
639 gst_structure_remove_field(structure, "profile");
642 "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
643 "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
646 gst_caps_merge_structure(decode->allowed_caps, structure);
649 gst_caps_unref(decode_caps);
655 GST_DEBUG("failed to retrieve VA display");
658 error_no_decode_caps:
660 GST_DEBUG("failed to retrieve VA decode caps");
665 GST_DEBUG("failed to allocate allowed-caps set");
666 gst_caps_unref(decode_caps);
672 gst_vaapidecode_get_caps(GstPad *pad)
674 GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
676 if (!decode->is_ready)
677 return gst_static_pad_template_get_caps(&gst_vaapidecode_sink_factory);
679 if (!gst_vaapidecode_ensure_allowed_caps(decode))
680 return gst_caps_new_empty();
682 return gst_caps_ref(decode->allowed_caps);
686 gst_vaapidecode_set_caps(GstPad *pad, GstCaps *caps)
688 GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
690 g_return_val_if_fail(pad == decode->sinkpad, FALSE);
692 if (!gst_vaapidecode_update_sink_caps(decode, caps))
694 if (!gst_vaapidecode_update_src_caps(decode, caps))
696 if (!gst_vaapidecode_reset(decode, decode->sinkpad_caps))
699 /* Propagate NEWSEGMENT event downstream, now that pads are linked */
700 if (decode->delayed_new_seg) {
701 if (gst_pad_push_event(decode->srcpad, decode->delayed_new_seg))
702 gst_event_unref(decode->delayed_new_seg);
703 decode->delayed_new_seg = NULL;
709 gst_vaapidecode_chain(GstPad *pad, GstBuffer *buf)
711 GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
713 if (!gst_vaapi_decoder_put_buffer(decode->decoder, buf))
714 goto error_push_buffer;
716 gst_buffer_unref(buf);
717 return gst_vaapidecode_step(decode);
722 GST_DEBUG("failed to push input buffer to decoder");
723 gst_buffer_unref(buf);
724 return GST_FLOW_UNEXPECTED;
729 gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event)
731 GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
733 GST_INFO("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
735 /* Propagate event downstream */
736 switch (GST_EVENT_TYPE(event)) {
737 case GST_EVENT_FLUSH_START:
738 g_mutex_lock(&decode->decoder_mutex);
739 decode->escape_decoding = TRUE;
740 g_cond_signal(&decode->decoder_ready);
741 g_mutex_unlock(&decode->decoder_mutex);
743 case GST_EVENT_FLUSH_STOP:
744 g_mutex_lock(&decode->decoder_mutex);
745 decode->escape_decoding = FALSE;
746 g_mutex_unlock(&decode->decoder_mutex);
747 gst_segment_init(&decode->segment, GST_FORMAT_UNDEFINED);
749 gst_vaapi_decoder_clear_buffer(decode->decoder);
751 case GST_EVENT_NEWSEGMENT:
752 if (decode->delayed_new_seg) {
753 gst_event_unref(decode->delayed_new_seg);
754 decode->delayed_new_seg = NULL;
756 if (!GST_PAD_PEER(decode->srcpad)) {
757 decode->delayed_new_seg = gst_event_ref(event);
760 gst_vaapidecode_configure_segment(decode, event);
763 if (!gst_vaapidecode_flush(decode)) {
764 GST_WARNING("failed to flush buffers");
770 return gst_pad_push_event(decode->srcpad, event);
774 gst_vaapidecode_src_event(GstPad *pad, GstEvent *event)
776 GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
778 GST_DEBUG("handle src event '%s'", GST_EVENT_TYPE_NAME(event));
780 /* Propagate event upstream */
781 return gst_pad_push_event(decode->sinkpad, event);
785 gst_vaapidecode_query (GstPad *pad, GstQuery *query) {
786 GstVaapiDecode *decode = GST_VAAPIDECODE (gst_pad_get_parent_element (pad));
789 GST_DEBUG ("sharing display %p", decode->display);
791 if (gst_vaapi_reply_to_query (query, decode->display))
794 res = gst_pad_query_default (pad, query);
796 g_object_unref (decode);
801 gst_vaapidecode_init(GstVaapiDecode *decode)
803 GstVaapiDecodeClass *klass = GST_VAAPIDECODE_GET_CLASS(decode);
804 GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
806 decode->display = NULL;
807 decode->decoder = NULL;
808 decode->decoder_caps = NULL;
809 decode->allowed_caps = NULL;
810 decode->delayed_new_seg = NULL;
811 decode->render_time_base = 0;
812 decode->last_buffer_time = 0;
813 decode->is_ready = FALSE;
814 decode->escape_decoding = FALSE;
816 g_mutex_init(&decode->decoder_mutex);
817 g_cond_init(&decode->decoder_ready);
818 gst_segment_init(&decode->segment, GST_FORMAT_UNDEFINED);
820 /* Pad through which data comes in to the element */
821 decode->sinkpad = gst_pad_new_from_template(
822 gst_element_class_get_pad_template(element_class, "sink"),
825 decode->sinkpad_caps = NULL;
827 gst_pad_set_getcaps_function(decode->sinkpad, gst_vaapidecode_get_caps);
828 gst_pad_set_setcaps_function(decode->sinkpad, gst_vaapidecode_set_caps);
829 gst_pad_set_chain_function(decode->sinkpad, gst_vaapidecode_chain);
830 gst_pad_set_event_function(decode->sinkpad, gst_vaapidecode_sink_event);
831 gst_pad_set_query_function(decode->sinkpad, gst_vaapidecode_query);
832 gst_element_add_pad(GST_ELEMENT(decode), decode->sinkpad);
834 /* Pad through which data goes out of the element */
835 decode->srcpad = gst_pad_new_from_template(
836 gst_element_class_get_pad_template(element_class, "src"),
839 decode->srcpad_caps = NULL;
841 gst_pad_use_fixed_caps(decode->srcpad);
842 gst_pad_set_event_function(decode->srcpad, gst_vaapidecode_src_event);
843 gst_pad_set_query_function(decode->srcpad, gst_vaapidecode_query);
844 gst_element_add_pad(GST_ELEMENT(decode), decode->srcpad);