diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2014-10-22 18:03:13 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2014-10-22 19:09:01 +0200 |
commit | b7ed4e935559972d1c27869ee93e068ae2b8ee61 (patch) | |
tree | a8fe5552cd6996bd4a63c3b98ac6d1e1e02b63f2 /gst/inter | |
parent | 1dd83ca6ee76834a18fc6152493ace44a0fd8bed (diff) | |
download | gstreamer-plugins-bad-b7ed4e935559972d1c27869ee93e068ae2b8ee61.tar.gz |
intervideo: Properly pass through caps from the sink to the source
Otherwise a magic capsfilter after the source is required with
exactly the same caps as the input.
This would've failed before with invalid buffer sizes:
gst-launch-1.0 videotestsrc ! intervideosink intervideosrc ! "video/x-raw,width=640,height=480" ! xvimagesink
Diffstat (limited to 'gst/inter')
-rw-r--r-- | gst/inter/gstintersurface.h | 7 | ||||
-rw-r--r-- | gst/inter/gstintervideosink.c | 34 | ||||
-rw-r--r-- | gst/inter/gstintervideosink.h | 3 | ||||
-rw-r--r-- | gst/inter/gstintervideosrc.c | 74 | ||||
-rw-r--r-- | gst/inter/gstintervideosrc.h | 1 |
5 files changed, 102 insertions, 17 deletions
diff --git a/gst/inter/gstintersurface.h b/gst/inter/gstintersurface.h index 160f27e27..1ac621d48 100644 --- a/gst/inter/gstintersurface.h +++ b/gst/inter/gstintersurface.h @@ -33,12 +33,7 @@ struct _GstInterSurface char *name; /* video */ - GstVideoFormat format; - int fps_n; - int fps_d; - int width; - int height; - int n_frames; + GstVideoInfo video_info; int video_buffer_count; /* audio */ diff --git a/gst/inter/gstintervideosink.c b/gst/inter/gstintervideosink.c index ca63bce80..4f5fc2bbe 100644 --- a/gst/inter/gstintervideosink.c +++ b/gst/inter/gstintervideosink.c @@ -45,6 +45,8 @@ #include <gst/video/video.h> #include "gstintervideosink.h" +#include <string.h> + GST_DEBUG_CATEGORY_STATIC (gst_inter_video_sink_debug_category); #define GST_CAT_DEFAULT gst_inter_video_sink_debug_category @@ -61,6 +63,8 @@ static void gst_inter_video_sink_get_times (GstBaseSink * sink, GstBuffer * buffer, GstClockTime * start, GstClockTime * end); static gboolean gst_inter_video_sink_start (GstBaseSink * sink); static gboolean gst_inter_video_sink_stop (GstBaseSink * sink); +static gboolean gst_inter_video_sink_set_caps (GstBaseSink * sink, + GstCaps * caps); static GstFlowReturn gst_inter_video_sink_render (GstBaseSink * sink, GstBuffer * buffer); @@ -111,6 +115,7 @@ gst_inter_video_sink_class_init (GstInterVideoSinkClass * klass) base_sink_class->start = GST_DEBUG_FUNCPTR (gst_inter_video_sink_start); base_sink_class->stop = GST_DEBUG_FUNCPTR (gst_inter_video_sink_stop); base_sink_class->render = GST_DEBUG_FUNCPTR (gst_inter_video_sink_render); + base_sink_class->set_caps = GST_DEBUG_FUNCPTR (gst_inter_video_sink_set_caps); g_object_class_install_property (gobject_class, PROP_CHANNEL, g_param_spec_string ("channel", "Channel", @@ -180,10 +185,10 @@ gst_inter_video_sink_get_times (GstBaseSink * sink, GstBuffer * buffer, if (GST_BUFFER_DURATION_IS_VALID (buffer)) { *end = *start + GST_BUFFER_DURATION (buffer); } else { - if (intervideosink->fps_n > 0) { + if (intervideosink->info.fps_n > 0) { *end = *start + - gst_util_uint64_scale_int (GST_SECOND, intervideosink->fps_d, - intervideosink->fps_n); + gst_util_uint64_scale_int (GST_SECOND, intervideosink->info.fps_d, + intervideosink->info.fps_n); } } } @@ -197,6 +202,9 @@ gst_inter_video_sink_start (GstBaseSink * sink) GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (sink); intervideosink->surface = gst_inter_surface_get (intervideosink->channel); + g_mutex_lock (&intervideosink->surface->mutex); + memset (&intervideosink->surface->video_info, 0, sizeof (GstVideoInfo)); + g_mutex_unlock (&intervideosink->surface->mutex); return TRUE; } @@ -211,6 +219,7 @@ gst_inter_video_sink_stop (GstBaseSink * sink) gst_buffer_unref (intervideosink->surface->video_buffer); } intervideosink->surface->video_buffer = NULL; + memset (&intervideosink->surface->video_info, 0, sizeof (GstVideoInfo)); g_mutex_unlock (&intervideosink->surface->mutex); gst_inter_surface_unref (intervideosink->surface); @@ -219,6 +228,25 @@ gst_inter_video_sink_stop (GstBaseSink * sink) return TRUE; } +static gboolean +gst_inter_video_sink_set_caps (GstBaseSink * sink, GstCaps * caps) +{ + GstInterVideoSink *intervideosink = GST_INTER_VIDEO_SINK (sink); + GstVideoInfo info; + + if (!gst_video_info_from_caps (&info, caps)) { + GST_ERROR_OBJECT (sink, "Failed to parse caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + + g_mutex_lock (&intervideosink->surface->mutex); + intervideosink->surface->video_info = info; + intervideosink->info = info; + g_mutex_unlock (&intervideosink->surface->mutex); + + return TRUE; +} + static GstFlowReturn gst_inter_video_sink_render (GstBaseSink * sink, GstBuffer * buffer) { diff --git a/gst/inter/gstintervideosink.h b/gst/inter/gstintervideosink.h index f7196c521..e476daabd 100644 --- a/gst/inter/gstintervideosink.h +++ b/gst/inter/gstintervideosink.h @@ -41,8 +41,7 @@ struct _GstInterVideoSink GstInterSurface *surface; char *channel; - int fps_n; - int fps_d; + GstVideoInfo info; }; struct _GstInterVideoSinkClass diff --git a/gst/inter/gstintervideosrc.c b/gst/inter/gstintervideosrc.c index b7348018d..de459f565 100644 --- a/gst/inter/gstintervideosrc.c +++ b/gst/inter/gstintervideosrc.c @@ -56,7 +56,10 @@ static void gst_inter_video_src_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec); static void gst_inter_video_src_finalize (GObject * object); +static GstCaps *gst_inter_video_src_get_caps (GstBaseSrc * src, + GstCaps * filter); static gboolean gst_inter_video_src_set_caps (GstBaseSrc * src, GstCaps * caps); +static GstCaps *gst_inter_video_src_fixate (GstBaseSrc * src, GstCaps * caps); static gboolean gst_inter_video_src_start (GstBaseSrc * src); static gboolean gst_inter_video_src_stop (GstBaseSrc * src); static void @@ -65,7 +68,6 @@ gst_inter_video_src_get_times (GstBaseSrc * src, GstBuffer * buffer, static GstFlowReturn gst_inter_video_src_create (GstBaseSrc * src, guint64 offset, guint size, GstBuffer ** buf); -static GstCaps *gst_inter_video_src_fixate (GstBaseSrc * src, GstCaps * caps); enum { @@ -84,7 +86,7 @@ GST_STATIC_PAD_TEMPLATE ("src", /* class initialization */ - +#define parent_class gst_inter_video_src_parent_class G_DEFINE_TYPE (GstInterVideoSrc, gst_inter_video_src, GST_TYPE_BASE_SRC); static void @@ -109,12 +111,13 @@ gst_inter_video_src_class_init (GstInterVideoSrcClass * klass) gobject_class->set_property = gst_inter_video_src_set_property; gobject_class->get_property = gst_inter_video_src_get_property; gobject_class->finalize = gst_inter_video_src_finalize; + base_src_class->get_caps = GST_DEBUG_FUNCPTR (gst_inter_video_src_get_caps); base_src_class->set_caps = GST_DEBUG_FUNCPTR (gst_inter_video_src_set_caps); + base_src_class->fixate = GST_DEBUG_FUNCPTR (gst_inter_video_src_fixate); base_src_class->start = GST_DEBUG_FUNCPTR (gst_inter_video_src_start); base_src_class->stop = GST_DEBUG_FUNCPTR (gst_inter_video_src_stop); base_src_class->get_times = GST_DEBUG_FUNCPTR (gst_inter_video_src_get_times); base_src_class->create = GST_DEBUG_FUNCPTR (gst_inter_video_src_create); - base_src_class->fixate = GST_DEBUG_FUNCPTR (gst_inter_video_src_fixate); g_object_class_install_property (gobject_class, PROP_CHANNEL, g_param_spec_string ("channel", "Channel", @@ -176,7 +179,37 @@ gst_inter_video_src_finalize (GObject * object) G_OBJECT_CLASS (gst_inter_video_src_parent_class)->finalize (object); } +static GstCaps * +gst_inter_video_src_get_caps (GstBaseSrc * src, GstCaps * filter) +{ + GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (src); + GstCaps *caps; + + GST_DEBUG_OBJECT (intervideosrc, "get_caps"); + if (!intervideosrc->surface) + return GST_BASE_SRC_CLASS (parent_class)->get_caps (src, filter); + + g_mutex_lock (&intervideosrc->surface->mutex); + if (intervideosrc->surface->video_info.finfo) { + caps = gst_video_info_to_caps (&intervideosrc->surface->video_info); + if (filter) { + GstCaps *tmp; + + tmp = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (caps); + caps = tmp; + } + } else { + caps = NULL; + } + g_mutex_unlock (&intervideosrc->surface->mutex); + + if (caps) + return caps; + else + return GST_BASE_SRC_CLASS (parent_class)->get_caps (src, filter); +} static gboolean gst_inter_video_src_set_caps (GstBaseSrc * src, GstCaps * caps) @@ -185,8 +218,10 @@ gst_inter_video_src_set_caps (GstBaseSrc * src, GstCaps * caps) GST_DEBUG_OBJECT (intervideosrc, "set_caps"); - if (!gst_video_info_from_caps (&intervideosrc->info, caps)) + if (!gst_video_info_from_caps (&intervideosrc->info, caps)) { + GST_ERROR_OBJECT (src, "Failed to parse caps %" GST_PTR_FORMAT, caps); return FALSE; + } return gst_pad_set_caps (src->srcpad, caps); } @@ -200,6 +235,8 @@ gst_inter_video_src_start (GstBaseSrc * src) GST_DEBUG_OBJECT (intervideosrc, "start"); intervideosrc->surface = gst_inter_surface_get (intervideosrc->channel); + intervideosrc->timestamp_offset = 0; + intervideosrc->n_frames = 0; return TRUE; } @@ -248,13 +285,26 @@ gst_inter_video_src_create (GstBaseSrc * src, guint64 offset, guint size, GstBuffer ** buf) { GstInterVideoSrc *intervideosrc = GST_INTER_VIDEO_SRC (src); + GstCaps *caps; GstBuffer *buffer; GST_DEBUG_OBJECT (intervideosrc, "create"); + caps = NULL; buffer = NULL; g_mutex_lock (&intervideosrc->surface->mutex); + if (intervideosrc->surface->video_info.finfo) { + if (!gst_video_info_is_equal (&intervideosrc->surface->video_info, + &intervideosrc->info)) { + caps = gst_video_info_to_caps (&intervideosrc->surface->video_info); + intervideosrc->timestamp_offset += + gst_util_uint64_scale_int (GST_SECOND * intervideosrc->n_frames, + GST_VIDEO_INFO_FPS_D (&intervideosrc->info), + GST_VIDEO_INFO_FPS_N (&intervideosrc->info)); + intervideosrc->n_frames = 0; + } + } if (intervideosrc->surface->video_buffer) { buffer = gst_buffer_ref (intervideosrc->surface->video_buffer); intervideosrc->surface->video_buffer_count++; @@ -265,6 +315,17 @@ gst_inter_video_src_create (GstBaseSrc * src, guint64 offset, guint size, } g_mutex_unlock (&intervideosrc->surface->mutex); + if (caps) { + gboolean ret = gst_base_src_set_caps (src, caps); + gst_caps_unref (caps); + if (!ret) { + GST_ERROR_OBJECT (src, "Failed to set caps %" GST_PTR_FORMAT, caps); + if (buffer) + gst_buffer_unref (buffer); + return GST_FLOW_NOT_NEGOTIATED; + } + } + if (buffer == NULL) { GstMapInfo map; @@ -284,14 +345,14 @@ gst_inter_video_src_create (GstBaseSrc * src, guint64 offset, guint size, buffer = gst_buffer_make_writable (buffer); - GST_BUFFER_PTS (buffer) = + GST_BUFFER_PTS (buffer) = intervideosrc->timestamp_offset + gst_util_uint64_scale_int (GST_SECOND * intervideosrc->n_frames, GST_VIDEO_INFO_FPS_D (&intervideosrc->info), GST_VIDEO_INFO_FPS_N (&intervideosrc->info)); GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE; GST_DEBUG_OBJECT (intervideosrc, "create ts %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buffer))); - GST_BUFFER_DURATION (buffer) = + GST_BUFFER_DURATION (buffer) = intervideosrc->timestamp_offset + gst_util_uint64_scale_int (GST_SECOND * (intervideosrc->n_frames + 1), GST_VIDEO_INFO_FPS_D (&intervideosrc->info), GST_VIDEO_INFO_FPS_N (&intervideosrc->info)) - GST_BUFFER_PTS (buffer); @@ -319,6 +380,7 @@ gst_inter_video_src_fixate (GstBaseSrc * src, GstCaps * caps) structure = gst_caps_get_structure (caps, 0); + gst_structure_fixate_field_string (structure, "format", "I420"); gst_structure_fixate_field_nearest_int (structure, "width", 320); gst_structure_fixate_field_nearest_int (structure, "height", 240); gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1); diff --git a/gst/inter/gstintervideosrc.h b/gst/inter/gstintervideosrc.h index a68af7603..3842f96d5 100644 --- a/gst/inter/gstintervideosrc.h +++ b/gst/inter/gstintervideosrc.h @@ -45,6 +45,7 @@ struct _GstInterVideoSrc GstVideoInfo info; int n_frames; + GstClockTime timestamp_offset; }; struct _GstInterVideoSrcClass |