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.
This commit is contained in:
Wim Taymans 2007-02-28 15:05:03 +00:00
parent 3c94c06c5a
commit f1f26384e9
3 changed files with 74 additions and 12 deletions

View file

@ -1,3 +1,11 @@
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),

View file

@ -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.

View file

@ -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)));