diff --git a/gst-libs/gst/video/gstvideodecoder.c b/gst-libs/gst/video/gstvideodecoder.c index c3072c1ec7..ecd7c2fc2f 100644 --- a/gst-libs/gst/video/gstvideodecoder.c +++ b/gst-libs/gst/video/gstvideodecoder.c @@ -1578,6 +1578,47 @@ gst_video_decoder_src_query (GstPad * pad, GstObject * parent, GstQuery * query) return ret; } +/** + * gst_video_decoder_proxy_getcaps: + * @decoder: a #GstVideoDecoder + * @caps: (allow-none): initial caps + * @filter: (allow-none): filter caps + * + * Returns caps that express @caps (or sink template caps if @caps == NULL) + * restricted to resolution/format/... combinations supported by downstream + * elements. + * + * Returns: (transfer-full): a #GstCaps owned by caller + * + * @Since: 1.6 + */ +GstCaps * +gst_video_decoder_proxy_getcaps (GstVideoDecoder * decoder, GstCaps * caps, + GstCaps * filter) +{ + return __gst_video_element_proxy_getcaps (GST_ELEMENT_CAST (decoder), + GST_VIDEO_DECODER_SINK_PAD (decoder), + GST_VIDEO_DECODER_SRC_PAD (decoder), caps, filter); +} + +static GstCaps * +gst_video_decoder_sink_getcaps (GstVideoDecoder * decoder, GstCaps * filter) +{ + GstVideoDecoderClass *klass; + GstCaps *caps; + + klass = GST_VIDEO_DECODER_GET_CLASS (decoder); + + if (klass->getcaps) + caps = klass->getcaps (decoder, filter); + else + caps = gst_video_decoder_proxy_getcaps (decoder, NULL, filter); + + GST_LOG_OBJECT (decoder, "Returning caps %" GST_PTR_FORMAT, caps); + + return caps; +} + static gboolean gst_video_decoder_sink_query_default (GstVideoDecoder * decoder, GstQuery * query) @@ -1615,15 +1656,12 @@ gst_video_decoder_sink_query_default (GstVideoDecoder * decoder, break; } case GST_QUERY_CAPS:{ - GstCaps *filter; - GstCaps *result; + GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); - result = __gst_video_element_proxy_getcaps (GST_ELEMENT_CAST (decoder), - GST_VIDEO_DECODER_SINK_PAD (decoder), - GST_VIDEO_DECODER_SRC_PAD (decoder), NULL, filter); - gst_query_set_caps_result (query, result); - gst_caps_unref (result); + caps = gst_video_decoder_sink_getcaps (decoder, filter); + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); res = TRUE; break; } diff --git a/gst-libs/gst/video/gstvideodecoder.h b/gst-libs/gst/video/gstvideodecoder.h index e5e3efee7c..6e79497a5b 100644 --- a/gst-libs/gst/video/gstvideodecoder.h +++ b/gst-libs/gst/video/gstvideodecoder.h @@ -256,6 +256,11 @@ struct _GstVideoDecoder * return TRUE if the query could be performed. Subclasses * should chain up to the parent implementation to invoke the * default handler. Since 1.4 + * @getcaps: Optional. + * Allows for a custom sink getcaps implementation. + * If not implemented, default returns + * gst_video_decoder_proxy_getcaps + * applied to sink template caps. * * Subclasses can override any of the available virtual methods or not, as * needed. At minimum @handle_frame needs to be overridden, and @set_format @@ -312,9 +317,12 @@ struct _GstVideoDecoderClass gboolean (*src_query) (GstVideoDecoder *decoder, GstQuery *query); + GstCaps* (*getcaps) (GstVideoDecoder *decoder, + GstCaps *filter); + /*< private >*/ - void *padding[GST_PADDING_LARGE-3]; + void *padding[GST_PADDING_LARGE-4]; }; GType gst_video_decoder_get_type (void); @@ -398,6 +406,11 @@ void gst_video_decoder_merge_tags (GstVideoDecoder *decoder, const GstTagList *tags, GstTagMergeMode mode); +GstCaps * gst_video_decoder_proxy_getcaps (GstVideoDecoder * decoder, + GstCaps * caps, + GstCaps * filter); + + G_END_DECLS #endif diff --git a/tests/check/libs/videodecoder.c b/tests/check/libs/videodecoder.c index 960cbd17dc..2197c75966 100644 --- a/tests/check/libs/videodecoder.c +++ b/tests/check/libs/videodecoder.c @@ -989,6 +989,42 @@ GST_START_TEST (videodecoder_query_caps_with_range_caps_peer) GST_END_TEST; +#define GETCAPS_CAPS_STR "video/x-test-custom, somefield=(string)getcaps" +static GstCaps * +_custom_video_decoder_getcaps (GstVideoDecoder * dec, GstCaps * filter) +{ + return gst_caps_from_string (GETCAPS_CAPS_STR); +} + +GST_START_TEST (videodecoder_query_caps_with_custom_getcaps) +{ + GstCaps *caps; + GstVideoDecoderClass *klass; + GstCaps *expected_caps; + + setup_videodecodertester (&sinktemplate_restricted, NULL); + + klass = GST_VIDEO_DECODER_CLASS (GST_VIDEO_DECODER_GET_CLASS (dec)); + klass->getcaps = _custom_video_decoder_getcaps; + + gst_pad_set_active (mysrcpad, TRUE); + gst_element_set_state (dec, GST_STATE_PLAYING); + gst_pad_set_active (mysinkpad, TRUE); + + caps = gst_pad_peer_query_caps (mysrcpad, NULL); + fail_unless (caps != NULL); + + expected_caps = gst_caps_from_string (GETCAPS_CAPS_STR); + fail_unless (gst_caps_is_equal (expected_caps, caps)); + gst_caps_unref (expected_caps); + gst_caps_unref (caps); + + cleanup_videodecodertest (); +} + +GST_END_TEST; + + static Suite * gst_videodecoder_suite (void) { @@ -999,6 +1035,7 @@ gst_videodecoder_suite (void) tcase_add_test (tc, videodecoder_query_caps_with_fixed_caps_peer); tcase_add_test (tc, videodecoder_query_caps_with_range_caps_peer); + tcase_add_test (tc, videodecoder_query_caps_with_custom_getcaps); tcase_add_test (tc, videodecoder_playback); tcase_add_test (tc, videodecoder_playback_with_events); diff --git a/win32/common/libgstvideo.def b/win32/common/libgstvideo.def index 00f4d0ed81..625674389f 100644 --- a/win32/common/libgstvideo.def +++ b/win32/common/libgstvideo.def @@ -114,6 +114,7 @@ EXPORTS gst_video_decoder_have_frame gst_video_decoder_merge_tags gst_video_decoder_negotiate + gst_video_decoder_proxy_getcaps gst_video_decoder_release_frame gst_video_decoder_set_estimate_rate gst_video_decoder_set_latency