diff --git a/gst/dvdspu/gstdvdspu.c b/gst/dvdspu/gstdvdspu.c index 50edc920a1..cf0a63b935 100644 --- a/gst/dvdspu/gstdvdspu.c +++ b/gst/dvdspu/gstdvdspu.c @@ -58,23 +58,17 @@ enum #define VIDEO_FORMATS GST_VIDEO_OVERLAY_COMPOSITION_BLEND_FORMATS -#define DVDSPU_CAPS GST_VIDEO_CAPS_MAKE (VIDEO_FORMATS) -#define DVDSPU_ALL_CAPS DVDSPU_CAPS ";" \ - GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("ANY", GST_VIDEO_FORMATS_ALL) - -static GstStaticCaps sw_template_caps = GST_STATIC_CAPS (DVDSPU_CAPS); - static GstStaticPadTemplate video_sink_factory = GST_STATIC_PAD_TEMPLATE ("video", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (DVDSPU_ALL_CAPS) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (VIDEO_FORMATS)) ); static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (DVDSPU_ALL_CAPS) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (VIDEO_FORMATS)) ); static GstStaticPadTemplate subpic_sink_factory = @@ -96,10 +90,8 @@ static gboolean gst_dvd_spu_src_event (GstPad * pad, GstObject * parent, GstEvent * event); static gboolean gst_dvd_spu_src_query (GstPad * pad, GstObject * parent, GstQuery * query); -static GstCaps *gst_dvd_spu_src_get_caps (GstDVDSpu * dvdspu, GstPad * pad, - GstCaps * filter); -static GstCaps *gst_dvd_spu_video_get_caps (GstDVDSpu * dvdspu, GstPad * pad, +static GstCaps *gst_dvd_spu_video_proxy_getcaps (GstPad * pad, GstCaps * filter); static gboolean gst_dvd_spu_video_set_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * caps); @@ -118,7 +110,7 @@ static gboolean gst_dvd_spu_subpic_event (GstPad * pad, GstObject * parent, GstEvent * event); static gboolean gst_dvd_spu_subpic_set_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * caps); -static gboolean gst_dvd_spu_negotiate (GstDVDSpu * dvdspu, GstCaps * caps); +static gboolean gst_dvd_spu_negotiate (GstDVDSpu * dvdspu); static void gst_dvd_spu_clear (GstDVDSpu * dvdspu); static void gst_dvd_spu_flush_spu_info (GstDVDSpu * dvdspu, @@ -310,7 +302,6 @@ gst_dvd_spu_src_event (GstPad * pad, GstObject * parent, GstEvent * event) static gboolean gst_dvd_spu_src_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstDVDSpu *dvdspu = GST_DVD_SPU (parent); gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { @@ -319,7 +310,7 @@ gst_dvd_spu_src_query (GstPad * pad, GstObject * parent, GstQuery * query) GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); - caps = gst_dvd_spu_src_get_caps (dvdspu, pad, filter); + caps = gst_dvd_spu_video_proxy_getcaps (pad, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); res = TRUE; @@ -333,239 +324,54 @@ gst_dvd_spu_src_query (GstPad * pad, GstObject * parent, GstQuery * query) return res; } -static gboolean -gst_dvd_spu_can_handle_caps (GstCaps * caps) -{ - GstCaps *sw_caps; - gboolean ret; - - sw_caps = gst_static_caps_get (&sw_template_caps); - ret = gst_caps_is_subset (caps, sw_caps); - gst_caps_unref (sw_caps); - - return ret; -} - static gboolean gst_dvd_spu_video_set_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * caps) { + gboolean res = FALSE; GstVideoInfo info; - gboolean ret = FALSE; + SpuState *state; if (!gst_video_info_from_caps (&info, caps)) - goto invalid_caps; + goto done; - dvdspu->spu_state.info = info; - - ret = gst_dvd_spu_negotiate (dvdspu, caps); - - DVD_SPU_LOCK (dvdspu); - if (!dvdspu->attach_compo_to_buffer && !gst_dvd_spu_can_handle_caps (caps)) { - GST_DEBUG_OBJECT (dvdspu, "unsupported caps %" GST_PTR_FORMAT, caps); - ret = FALSE; + res = gst_pad_set_caps (dvdspu->srcpad, caps); + if (res) { + DVD_SPU_LOCK (dvdspu); + state = &dvdspu->spu_state; + state->info = info; + gst_dvd_spu_negotiate (dvdspu); + DVD_SPU_UNLOCK (dvdspu); } - DVD_SPU_UNLOCK (dvdspu); - - return ret; - - /* ERRORS */ -invalid_caps: - { - GST_DEBUG_OBJECT (dvdspu, "could not parse caps"); - return FALSE; - } -} - - -/** - * gst_dvd_spu_add_feature_and_intersect: - * - * Creates a new #GstCaps containing the (given caps + - * given caps feature) + (given caps intersected by the - * given filter). - * - * Returns: the new #GstCaps - */ -static GstCaps * -gst_dvd_spu_add_feature_and_intersect (GstCaps * caps, - const gchar * feature, GstCaps * filter) -{ - int i, caps_size; - GstCaps *new_caps; - - new_caps = gst_caps_copy (caps); - - caps_size = gst_caps_get_size (new_caps); - for (i = 0; i < caps_size; i++) { - GstCapsFeatures *features = gst_caps_get_features (new_caps, i); - if (!gst_caps_features_is_any (features)) { - gst_caps_features_add (features, feature); - } - } - - gst_caps_append (new_caps, gst_caps_intersect_full (caps, - filter, GST_CAPS_INTERSECT_FIRST)); - - return new_caps; -} - -/** - * gst_dvd_spu_intersect_by_feature: - * - * Creates a new #GstCaps based on the following filtering rule. - * - * For each individual caps contained in given caps, if the - * caps uses the given caps feature, keep a version of the caps - * with the feature and an another one without. Otherwise, intersect - * the caps with the given filter. - * - * Returns: the new #GstCaps - */ -static GstCaps * -gst_dvd_spu_intersect_by_feature (GstCaps * caps, - const gchar * feature, GstCaps * filter) -{ - int i, caps_size; - GstCaps *new_caps; - - new_caps = gst_caps_new_empty (); - - caps_size = gst_caps_get_size (caps); - for (i = 0; i < caps_size; i++) { - GstStructure *caps_structure = gst_caps_get_structure (caps, i); - GstCapsFeatures *caps_features = - gst_caps_features_copy (gst_caps_get_features (caps, i)); - GstCaps *filtered_caps; - GstCaps *simple_caps = - gst_caps_new_full (gst_structure_copy (caps_structure), NULL); - gst_caps_set_features (simple_caps, 0, caps_features); - - if (gst_caps_features_contains (caps_features, feature)) { - gst_caps_append (new_caps, gst_caps_copy (simple_caps)); - - gst_caps_features_remove (caps_features, feature); - filtered_caps = gst_caps_ref (simple_caps); - } else { - filtered_caps = gst_caps_intersect_full (simple_caps, filter, - GST_CAPS_INTERSECT_FIRST); - } - - gst_caps_unref (simple_caps); - gst_caps_append (new_caps, filtered_caps); - } - - return new_caps; +done: + return res; } static GstCaps * -gst_dvd_spu_video_get_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * filter) +gst_dvd_spu_video_proxy_getcaps (GstPad * pad, GstCaps * filter) { - GstPad *srcpad = dvdspu->srcpad; - GstCaps *peer_caps = NULL, *caps = NULL, *dvdspu_filter = NULL; + GstDVDSpu *dvdspu = GST_DVD_SPU (gst_pad_get_parent (pad)); + GstCaps *caps; + GstPad *otherpad; - if (filter) { - /* filter caps + composition feature + filter caps - * filtered by the software caps. */ - GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps); - dvdspu_filter = gst_dvd_spu_add_feature_and_intersect (filter, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); + /* Proxy the getcaps between videosink and the srcpad, ignoring the + * subpicture sink pad */ + otherpad = (pad == dvdspu->srcpad) ? dvdspu->videosinkpad : dvdspu->srcpad; - GST_DEBUG_OBJECT (dvdspu, "dvdspu filter %" GST_PTR_FORMAT, dvdspu_filter); - } - - peer_caps = gst_pad_peer_query_caps (srcpad, dvdspu_filter); - - if (dvdspu_filter) - gst_caps_unref (dvdspu_filter); - - if (peer_caps) { - GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peer_caps); - - if (gst_caps_is_any (peer_caps)) { - /* if peer returns ANY caps, return filtered src pad template caps */ - caps = gst_caps_copy (gst_pad_get_pad_template_caps (srcpad)); - } else { - /* duplicate caps which contains the composition into one version with - * the meta and one without. Filter the other caps by the software caps */ - GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps); - caps = gst_dvd_spu_intersect_by_feature (peer_caps, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); - } - - gst_caps_unref (peer_caps); + caps = gst_pad_peer_query_caps (otherpad, filter); + if (caps) { + GstCaps *temp, *templ; + templ = gst_pad_get_pad_template_caps (otherpad); + temp = gst_caps_intersect (caps, templ); + gst_caps_unref (templ); + gst_caps_unref (caps); + caps = temp; } else { - /* no peer, our padtemplate is enough then */ caps = gst_pad_get_pad_template_caps (pad); } - if (filter) { - GstCaps *intersection = gst_caps_intersect_full (filter, caps, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (caps); - caps = intersection; - } - - GST_DEBUG_OBJECT (dvdspu, "returning %" GST_PTR_FORMAT, caps); - - return caps; -} - -static GstCaps * -gst_dvd_spu_src_get_caps (GstDVDSpu * dvdspu, GstPad * pad, GstCaps * filter) -{ - GstPad *sinkpad = dvdspu->videosinkpad; - GstCaps *peer_caps = NULL, *caps = NULL, *dvdspu_filter = NULL; - - if (filter) { - /* duplicate filter caps which contains the composition into one version - * with the meta and one without. Filter the other caps by the software - * caps */ - GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps); - dvdspu_filter = gst_dvd_spu_intersect_by_feature (filter, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); - } - - peer_caps = gst_pad_peer_query_caps (sinkpad, dvdspu_filter); - - if (dvdspu_filter) - gst_caps_unref (dvdspu_filter); - - if (peer_caps) { - GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peer_caps); - - if (gst_caps_is_any (peer_caps)) { - /* if peer returns ANY caps, return filtered sink pad template caps */ - caps = gst_caps_copy (gst_pad_get_pad_template_caps (sinkpad)); - } else { - /* return upstream caps + composition feature + upstream caps - * filtered by the software caps. */ - GstCaps *sw_caps = gst_static_caps_get (&sw_template_caps); - caps = gst_dvd_spu_add_feature_and_intersect (peer_caps, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, sw_caps); - gst_caps_unref (sw_caps); - } - - gst_caps_unref (peer_caps); - - } else { - /* no peer, our padtemplate is enough then */ - caps = gst_pad_get_pad_template_caps (pad); - } - - if (filter) { - GstCaps *intersection = gst_caps_intersect_full (filter, caps, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (caps); - caps = intersection; - } - - GST_DEBUG_OBJECT (dvdspu, "returning %" GST_PTR_FORMAT, caps); - + gst_object_unref (dvdspu); return caps; } @@ -694,16 +500,12 @@ gst_dvd_spu_video_event (GstPad * pad, GstObject * parent, GstEvent * event) break; } case GST_EVENT_FLUSH_START: - DVD_SPU_LOCK (dvdspu); - dvdspu->video_flushing = TRUE; - DVD_SPU_UNLOCK (dvdspu); res = gst_pad_event_default (pad, parent, event); goto done; case GST_EVENT_FLUSH_STOP: res = gst_pad_event_default (pad, parent, event); DVD_SPU_LOCK (dvdspu); - dvdspu->video_flushing = FALSE; gst_segment_init (&dvdspu->video_seg, GST_FORMAT_UNDEFINED); gst_buffer_replace (&dvdspu->ref_frame, NULL); gst_buffer_replace (&dvdspu->pending_frame, NULL); @@ -727,7 +529,6 @@ error: static gboolean gst_dvd_spu_video_query (GstPad * pad, GstObject * parent, GstQuery * query) { - GstDVDSpu *dvdspu = GST_DVD_SPU (parent); gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { @@ -736,7 +537,7 @@ gst_dvd_spu_video_query (GstPad * pad, GstObject * parent, GstQuery * query) GstCaps *filter, *caps; gst_query_parse_caps (query, &filter); - caps = gst_dvd_spu_video_get_caps (dvdspu, pad, filter); + caps = gst_dvd_spu_video_proxy_getcaps (pad, filter); gst_query_set_caps_result (query, caps); gst_caps_unref (caps); res = TRUE; @@ -759,7 +560,7 @@ gst_dvd_spu_video_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) g_return_val_if_fail (dvdspu != NULL, GST_FLOW_ERROR); if (gst_pad_check_reconfigure (dvdspu->srcpad)) - gst_dvd_spu_negotiate (dvdspu, NULL); + gst_dvd_spu_negotiate (dvdspu); GST_LOG_OBJECT (dvdspu, "video buffer %p with TS %" GST_TIME_FORMAT, buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); @@ -1261,134 +1062,40 @@ submit_new_spu_packet (GstDVDSpu * dvdspu, GstBuffer * buf) } static gboolean -gst_dvd_spu_negotiate (GstDVDSpu * dvdspu, GstCaps * caps) +gst_dvd_spu_negotiate (GstDVDSpu * dvdspu) { - gboolean upstream_has_meta = FALSE; - gboolean caps_has_meta = FALSE; - gboolean alloc_has_meta = FALSE; - gboolean attach = FALSE; - gboolean ret = TRUE; - GstCapsFeatures *f; - GstCaps *overlay_caps; GstQuery *query; + GstCaps *caps; + gboolean attach = FALSE; + + gst_dvd_spu_reset_composition (dvdspu); GST_DEBUG_OBJECT (dvdspu, "performing negotiation"); - /* Clear the cached composition */ - gst_dvd_spu_reset_composition (dvdspu); - - /* Clear any pending reconfigure to avoid negotiating twice */ - gst_pad_check_reconfigure (dvdspu->srcpad); - - if (!caps) - caps = gst_pad_get_current_caps (dvdspu->videosinkpad); - else - gst_caps_ref (caps); - + caps = gst_pad_get_current_caps (dvdspu->srcpad); if (!caps || gst_caps_is_empty (caps)) goto no_format; - /* Check if upstream caps have meta */ - if ((f = gst_caps_get_features (caps, 0))) { - upstream_has_meta = gst_caps_features_contains (f, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - } + query = gst_query_new_allocation (caps, FALSE); - if (upstream_has_meta) { - overlay_caps = gst_caps_ref (caps); - } else { - GstCaps *peercaps; + if (!gst_pad_peer_query (dvdspu->srcpad, query)) + GST_DEBUG_OBJECT (dvdspu, "ALLOCATION query failed"); - /* BaseTransform requires caps for the allocation query to work */ - overlay_caps = gst_caps_copy (caps); - f = gst_caps_get_features (overlay_caps, 0); - gst_caps_features_add (f, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); - - /* Then check if downstream accept dvdspu composition in caps */ - /* FIXME: We should probably check if downstream *prefers* the - * dvdspu meta, and only enforce usage of it if we can't handle - * the format ourselves and thus would have to drop the overlays. - * Otherwise we should prefer what downstream wants here. - */ - peercaps = gst_pad_peer_query_caps (dvdspu->srcpad, NULL); - caps_has_meta = gst_caps_can_intersect (peercaps, overlay_caps); - gst_caps_unref (peercaps); - - GST_DEBUG ("caps have dvdspu meta %d", caps_has_meta); - } - - if (upstream_has_meta || caps_has_meta) { - /* Send caps immediatly, it's needed by GstBaseTransform to get a reply - * from allocation query */ - ret = gst_pad_set_caps (dvdspu->srcpad, overlay_caps); - - /* First check if the allocation meta has compositon */ - query = gst_query_new_allocation (overlay_caps, FALSE); - - if (!gst_pad_peer_query (dvdspu->srcpad, query)) { - /* no problem, we use the query defaults */ - GST_DEBUG_OBJECT (dvdspu, "ALLOCATION query failed"); - - /* In case we were flushing, mark reconfigure and fail this method, - * will make it retry */ - if (dvdspu->video_flushing) - ret = FALSE; - } - - alloc_has_meta = gst_query_find_allocation_meta (query, - GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL); - - GST_DEBUG ("sink alloc has dvdspu meta %d", alloc_has_meta); - - gst_query_unref (query); - } - - /* For backward compatbility, we will prefer bliting if downstream - * allocation does not support the meta. In other case we will prefer - * attaching, and will fail the negotiation in the unlikely case we are - * force to blit, but format isn't supported. */ - - if (upstream_has_meta) { + if (gst_query_find_allocation_meta (query, + GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL)) attach = TRUE; - } else if (caps_has_meta) { - if (alloc_has_meta) { - attach = TRUE; - } else { - /* Don't attach unless we cannot handle the format */ - attach = !gst_dvd_spu_can_handle_caps (caps); - } - } else { - ret = gst_dvd_spu_can_handle_caps (caps); - } - /* If we attach, then pick the dvdspu caps */ - if (attach) { - GST_DEBUG_OBJECT (dvdspu, "Using caps %" GST_PTR_FORMAT, overlay_caps); - /* Caps where already sent */ - } else if (ret) { - GST_DEBUG_OBJECT (dvdspu, "Using caps %" GST_PTR_FORMAT, caps); - ret = gst_pad_set_caps (dvdspu->srcpad, caps); - } + gst_query_unref (query); + gst_caps_unref (caps); dvdspu->attach_compo_to_buffer = attach; - if (!ret) { - GST_DEBUG_OBJECT (dvdspu, "negotiation failed, schedule reconfigure"); - gst_pad_mark_reconfigure (dvdspu->srcpad); - } - - gst_caps_unref (overlay_caps); - gst_caps_unref (caps); - - return ret; + return TRUE; no_format: - { - if (caps) - gst_caps_unref (caps); - return FALSE; - } + if (caps) + gst_caps_unref (caps); + return FALSE; } static GstFlowReturn diff --git a/gst/dvdspu/gstdvdspu.h b/gst/dvdspu/gstdvdspu.h index 61d3e9c42e..6fa700cb3b 100644 --- a/gst/dvdspu/gstdvdspu.h +++ b/gst/dvdspu/gstdvdspu.h @@ -94,7 +94,6 @@ struct _GstDVDSpu { /* Mutex to protect state we access from different chain funcs */ GMutex spu_lock; - gboolean video_flushing; GstSegment video_seg; GstSegment subp_seg;