basetextoverlay: rework caps negotiation

Make textoverlay negotiate caps more correctly.

1) Check what caps we received in the video-sink
2) If it already has the overlay meta -> use it directly
3) If it doesn't, textoverlay try adding the overlay meta and using it,
   if downstream doesn't support it, just use what is received in the
   video-sink
4) Check if the allocation query also supports the meta to enable
   really using it

Before it wasn't really doing renegotiation of any kind, just
re-checking if it should use the overlay meta or not

Also had to update the caps in the test as memory:SystemMemory seems
to be required when you use a caps feature otherwise intersection/subset
checks will fail.

https://bugzilla.gnome.org/show_bug.cgi?id=733916
This commit is contained in:
Thiago Santos 2014-08-08 12:46:47 -03:00
parent c20e044ef0
commit a080c0ebbf
2 changed files with 80 additions and 37 deletions

View file

@ -708,46 +708,92 @@ gst_base_text_overlay_setcaps_txt (GstBaseTextOverlay * overlay, GstCaps * caps)
return TRUE; return TRUE;
} }
/* FIXME: upstream nego (e.g. when the video window is resized) */
/* only negotiate/query video overlay composition support for now */ /* only negotiate/query video overlay composition support for now */
static gboolean static gboolean
gst_base_text_overlay_negotiate (GstBaseTextOverlay * overlay) gst_base_text_overlay_negotiate (GstBaseTextOverlay * overlay, GstCaps * caps)
{ {
GstCaps *target;
GstQuery *query; GstQuery *query;
gboolean attach = FALSE; gboolean attach = FALSE;
gboolean caps_has_meta = TRUE;
gboolean ret;
GstCapsFeatures *f;
GST_DEBUG_OBJECT (overlay, "performing negotiation"); GST_DEBUG_OBJECT (overlay, "performing negotiation");
target = gst_pad_get_current_caps (overlay->srcpad); if (!caps)
caps = gst_pad_get_current_caps (overlay->video_sinkpad);
else
gst_caps_ref (caps);
if (!target || gst_caps_is_empty (target)) if (!caps || gst_caps_is_empty (caps))
goto no_format; goto no_format;
/* find supported meta */ /* Try to use the overlay meta if possible */
query = gst_query_new_allocation (target, TRUE); f = gst_caps_get_features (caps, 0);
/* if the caps doesn't have the overlay meta, we query if downstream
* accepts it before trying the version without the meta
* If upstream already is using the meta then we can only use it */
if (!f
|| !gst_caps_features_contains (f,
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) {
GstCaps *overlay_caps;
/* In this case we added the meta, but we can work without it
* so preserve the original caps so we can use it as a fallback */
overlay_caps = gst_caps_copy (caps);
f = gst_caps_get_features (overlay_caps, 0);
if (f == NULL) {
f = gst_caps_features_new
(GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL);
} else {
gst_caps_features_add (f,
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
}
ret = gst_pad_peer_query_accept_caps (overlay->srcpad, overlay_caps);
GST_DEBUG_OBJECT (overlay, "Downstream accepts the overlay meta: %d", ret);
if (ret) {
gst_caps_unref (caps);
caps = overlay_caps;
} else {
/* fallback to the original */
gst_caps_unref (overlay_caps);
caps_has_meta = FALSE;
}
if (!gst_pad_peer_query (overlay->srcpad, query)) {
/* no problem, we use the query defaults */
GST_DEBUG_OBJECT (overlay, "ALLOCATION query failed");
} }
GST_DEBUG_OBJECT (overlay, "Using caps %" GST_PTR_FORMAT, caps);
ret = gst_pad_set_caps (overlay->srcpad, caps);
if (gst_query_find_allocation_meta (query, if (ret) {
GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL)) /* find supported meta */
attach = TRUE; query = gst_query_new_allocation (caps, TRUE);
overlay->attach_compo_to_buffer = attach; if (!gst_pad_peer_query (overlay->srcpad, query)) {
/* no problem, we use the query defaults */
GST_DEBUG_OBJECT (overlay, "ALLOCATION query failed");
}
gst_query_unref (query); if (caps_has_meta && gst_query_find_allocation_meta (query,
gst_caps_unref (target); GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL))
attach = TRUE;
return TRUE; overlay->attach_compo_to_buffer = attach;
gst_query_unref (query);
} else {
overlay->attach_compo_to_buffer = FALSE;
}
gst_caps_unref (caps);
return ret;
no_format: no_format:
{ {
if (target) if (caps)
gst_caps_unref (target); gst_caps_unref (caps);
return FALSE; return FALSE;
} }
} }
@ -780,24 +826,20 @@ gst_base_text_overlay_setcaps (GstBaseTextOverlay * overlay, GstCaps * caps)
overlay->width = GST_VIDEO_INFO_WIDTH (&info); overlay->width = GST_VIDEO_INFO_WIDTH (&info);
overlay->height = GST_VIDEO_INFO_HEIGHT (&info); overlay->height = GST_VIDEO_INFO_HEIGHT (&info);
ret = gst_pad_set_caps (overlay->srcpad, caps); GST_BASE_TEXT_OVERLAY_LOCK (overlay);
g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
ret = gst_base_text_overlay_negotiate (overlay, caps);
if (ret) { if (!overlay->attach_compo_to_buffer &&
GST_BASE_TEXT_OVERLAY_LOCK (overlay); !gst_base_text_overlay_can_handle_caps (caps)) {
g_mutex_lock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); GST_DEBUG_OBJECT (overlay, "unsupported caps %" GST_PTR_FORMAT, caps);
gst_base_text_overlay_negotiate (overlay); ret = FALSE;
if (!overlay->attach_compo_to_buffer &&
!gst_base_text_overlay_can_handle_caps (caps)) {
GST_DEBUG_OBJECT (overlay, "unsupported caps %" GST_PTR_FORMAT, caps);
ret = FALSE;
}
gst_base_text_overlay_update_wrap_mode (overlay);
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
GST_BASE_TEXT_OVERLAY_UNLOCK (overlay);
} }
gst_base_text_overlay_update_wrap_mode (overlay);
g_mutex_unlock (GST_BASE_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock);
GST_BASE_TEXT_OVERLAY_UNLOCK (overlay);
return ret; return ret;
/* ERRORS */ /* ERRORS */
@ -1852,7 +1894,7 @@ gst_base_text_overlay_push_frame (GstBaseTextOverlay * overlay,
goto done; goto done;
if (gst_pad_check_reconfigure (overlay->srcpad)) if (gst_pad_check_reconfigure (overlay->srcpad))
gst_base_text_overlay_negotiate (overlay); gst_base_text_overlay_negotiate (overlay, NULL);
video_frame = gst_buffer_make_writable (video_frame); video_frame = gst_buffer_make_writable (video_frame);

View file

@ -53,7 +53,8 @@ static GstPad *myvideosrcpad, *mytextsrcpad, *mysinkpad;
"format = (string) I420" "format = (string) I420"
#define VIDEO_CAPS_TEMPLATE_WITH_FEATURE_STRING \ #define VIDEO_CAPS_TEMPLATE_WITH_FEATURE_STRING \
"video/x-raw(" GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION "), " \ "video/x-raw(" GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY ", " \
GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION "), " \
"format = (string) I420;" \ "format = (string) I420;" \
"video/x-raw, " \ "video/x-raw, " \
"format = (string) I420;" "format = (string) I420;"