Commit f1f26384 authored by Wim Taymans's avatar Wim Taymans

sys/v4l/: Fix duration and timestamping, taking latency into account.

Original commit message from CVS:
* sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init),
(gst_v4lsrc_fixate), (gst_v4lsrc_query):
* sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_buffer_new):
Fix duration and timestamping, taking latency into account.
Implement latency query.
parent 3c94c06c
2007-02-28 Wim Taymans <wim@fluendo.com>
* sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init),
(gst_v4lsrc_fixate), (gst_v4lsrc_query):
* sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_buffer_new):
Fix duration and timestamping, taking latency into account.
Implement latency query.
2007-02-28 Wim Taymans <wim@fluendo.com>
* gst-libs/gst/audio/gstaudioclock.c: (gst_audio_clock_init),
......@@ -60,8 +60,8 @@ static gboolean gst_v4lsrc_stop (GstBaseSrc * src);
static gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps);
static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src);
static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out);
static void gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps);
static gboolean gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query);
static void gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps);
static void gst_v4lsrc_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
......@@ -119,6 +119,8 @@ gst_v4lsrc_class_init (GstV4lSrcClass * klass)
basesrc_class->set_caps = gst_v4lsrc_set_caps;
basesrc_class->start = gst_v4lsrc_start;
basesrc_class->stop = gst_v4lsrc_stop;
basesrc_class->fixate = gst_v4lsrc_fixate;
basesrc_class->query = gst_v4lsrc_query;
pushsrc_class->create = gst_v4lsrc_create;
}
......@@ -140,9 +142,6 @@ gst_v4lsrc_init (GstV4lSrc * v4lsrc, GstV4lSrcClass * klass)
v4lsrc->fps_list = NULL;
gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (v4lsrc),
gst_v4lsrc_fixate);
gst_base_src_set_live (GST_BASE_SRC (v4lsrc), TRUE);
}
......@@ -201,12 +200,12 @@ gst_v4lsrc_get_property (GObject * object,
/* this function is a bit of a last resort */
static void
gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps)
gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps)
{
GstStructure *structure;
int i;
int targetwidth, targetheight;
GstV4lSrc *v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
GstV4lSrc *v4lsrc = GST_V4LSRC (bsrc);
struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
......@@ -615,6 +614,53 @@ gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
return TRUE;
}
static gboolean
gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query)
{
GstV4lSrc *v4lsrc;
gboolean res = FALSE;
v4lsrc = GST_V4LSRC (bsrc);
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_LATENCY:
{
GstClockTime min_latency, max_latency;
gint fps_n, fps_d;
/* device must be open */
if (!GST_V4L_IS_OPEN (v4lsrc))
goto done;
/* we must have a framerate */
if (!(res = gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)))
goto done;
/* min latency is the time to capture one frame */
min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
/* max latency is total duration of the frame buffer */
max_latency = v4lsrc->mbuf.frames * min_latency;
GST_DEBUG_OBJECT (bsrc,
"report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
/* we are always live, the min latency is 1 frame and the max latency is
* the complete buffer of frames. */
gst_query_set_latency (query, TRUE, min_latency, max_latency);
res = TRUE;
break;
}
default:
res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
break;
}
done:
return res;
}
/* start and stop are not symmetric -- start will open the device, but not start
capture. it's setcaps that will start capture, which is called via basesrc's
negotiate method. stop will both stop capture and close the device.
......
......@@ -697,6 +697,7 @@ gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
{
GstBuffer *buf;
gint fps_n, fps_d;
GstClockTime duration, timestamp, latency;
GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num);
......@@ -711,12 +712,19 @@ gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num);
GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
GST_BUFFER_OFFSET (buf) = v4lsrc->offset++;
GST_BUFFER_TIMESTAMP (buf) = gst_clock_get_time (GST_ELEMENT (v4lsrc)->clock);
GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4lsrc)->base_time;
/* FIXME: this is a most ghetto timestamp/duration */
GST_BUFFER_DURATION (buf) = gst_util_uint64_scale_int (GST_SECOND,
fps_n, fps_d);
duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
latency = duration;
timestamp = gst_clock_get_time (GST_ELEMENT_CAST (v4lsrc)->clock);
timestamp -= gst_element_get_base_time (GST_ELEMENT_CAST (v4lsrc));
if (timestamp > latency)
timestamp -= latency;
else
timestamp = 0;
GST_BUFFER_TIMESTAMP (buf) = timestamp;
GST_BUFFER_DURATION (buf) = duration;
/* the negotiate() method already set caps on the source pad */
gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment