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:
parent
3c94c06c5a
commit
f1f26384e9
@ -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>
|
2007-02-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst-libs/gst/audio/gstaudioclock.c: (gst_audio_clock_init),
|
* 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 gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps);
|
||||||
static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src);
|
static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src);
|
||||||
static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out);
|
static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out);
|
||||||
|
static gboolean gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query);
|
||||||
static void gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps);
|
static void gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps);
|
||||||
|
|
||||||
static void gst_v4lsrc_set_property (GObject * object,
|
static void gst_v4lsrc_set_property (GObject * object,
|
||||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
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->set_caps = gst_v4lsrc_set_caps;
|
||||||
basesrc_class->start = gst_v4lsrc_start;
|
basesrc_class->start = gst_v4lsrc_start;
|
||||||
basesrc_class->stop = gst_v4lsrc_stop;
|
basesrc_class->stop = gst_v4lsrc_stop;
|
||||||
|
basesrc_class->fixate = gst_v4lsrc_fixate;
|
||||||
|
basesrc_class->query = gst_v4lsrc_query;
|
||||||
|
|
||||||
pushsrc_class->create = gst_v4lsrc_create;
|
pushsrc_class->create = gst_v4lsrc_create;
|
||||||
}
|
}
|
||||||
@ -140,9 +142,6 @@ gst_v4lsrc_init (GstV4lSrc * v4lsrc, GstV4lSrcClass * klass)
|
|||||||
|
|
||||||
v4lsrc->fps_list = NULL;
|
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);
|
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 */
|
/* this function is a bit of a last resort */
|
||||||
static void
|
static void
|
||||||
gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps)
|
gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
int i;
|
int i;
|
||||||
int targetwidth, targetheight;
|
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_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
|
||||||
struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
|
struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
|
||||||
|
|
||||||
@ -615,6 +614,53 @@ gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
|
|||||||
return TRUE;
|
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
|
/* 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
|
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.
|
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;
|
GstBuffer *buf;
|
||||||
gint fps_n, fps_d;
|
gint fps_n, fps_d;
|
||||||
|
GstClockTime duration, timestamp, latency;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num);
|
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_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num);
|
||||||
GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
|
GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
|
||||||
GST_BUFFER_OFFSET (buf) = v4lsrc->offset++;
|
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,
|
duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
|
||||||
fps_n, fps_d);
|
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 */
|
/* the negotiate() method already set caps on the source pad */
|
||||||
gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));
|
gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user