niimaq: try to improve accuracy of timestamping

By reducing instructions in callback, and adjusting for base time. This last
part needs testing however.
This commit is contained in:
Joshua M. Doe 2012-06-29 07:35:26 -04:00
parent 4fa97a4290
commit ad240b0ae3
2 changed files with 48 additions and 43 deletions

View File

@ -123,30 +123,39 @@ gst_niimaqsrc_frame_start_callback (SESSION_ID sid, IMG_ERR err,
{ {
GstNiImaqSrc *niimaqsrc = GST_NIIMAQSRC (userdata); GstNiImaqSrc *niimaqsrc = GST_NIIMAQSRC (userdata);
GstClock *clock; GstClock *clock;
GstNiImaqSrcFrameTime *frametime = g_new (GstNiImaqSrcFrameTime, 1); GstNiImaqSrcFrameTime *frametime;
uInt32 val; guint32 bufnum;
GstClockTime abstime;
if (!niimaqsrc->session_started)
return 1;
if (G_UNLIKELY (niimaqsrc->start_time == NULL)) if (G_UNLIKELY (niimaqsrc->start_time == NULL))
niimaqsrc->start_time = gst_date_time_new_now_utc (); niimaqsrc->start_time = gst_date_time_new_now_utc ();
/* get clock time and set to frametime struct */ /* get clock time */
clock = gst_element_get_clock (GST_ELEMENT (niimaqsrc)); clock = gst_element_get_clock (GST_ELEMENT (niimaqsrc));
if (G_LIKELY (clock)) { g_assert (clock != NULL);
frametime->time = gst_clock_get_time (clock); abstime = gst_clock_get_time (clock);
gst_object_unref (clock);
} else {
frametime->time = GST_CLOCK_TIME_NONE;
}
/* get current frame number */ /* get current frame number */
imgGetAttribute (sid, IMG_ATTR_FRAME_COUNT, &val); imgGetAttribute (sid, IMG_ATTR_FRAME_COUNT, &bufnum);
frametime->number = val;
/* first frame, use as element base time */
if (niimaqsrc->base_time == GST_CLOCK_TIME_NONE)
niimaqsrc->base_time = abstime;
frametime = g_new (GstNiImaqSrcFrameTime, 1);
frametime->number = bufnum;
frametime->time = abstime;
/* append frame number and clock time to list */ /* append frame number and clock time to list */
g_mutex_lock (niimaqsrc->frametime_mutex); g_mutex_lock (niimaqsrc->frametime_mutex);
niimaqsrc->timelist = g_slist_append (niimaqsrc->timelist, frametime); niimaqsrc->timelist = g_slist_append (niimaqsrc->timelist, frametime);
g_mutex_unlock (niimaqsrc->frametime_mutex); g_mutex_unlock (niimaqsrc->frametime_mutex);
gst_object_unref (clock);
/* return 1 to rearm the callback */ /* return 1 to rearm the callback */
return 1; return 1;
} }
@ -654,6 +663,7 @@ gst_niimaqsrc_reset (GstNiImaqSrc * niimaqsrc)
niimaqsrc->timelist = NULL; niimaqsrc->timelist = NULL;
niimaqsrc->start_time = NULL; niimaqsrc->start_time = NULL;
niimaqsrc->start_time_sent = FALSE; niimaqsrc->start_time_sent = FALSE;
niimaqsrc->base_time = GST_CLOCK_TIME_NONE;
} }
static gboolean static gboolean
@ -692,36 +702,36 @@ static GstClockTime
gst_niimaqsrc_get_timestamp_from_buffer_number (GstNiImaqSrc * niimaqsrc, gst_niimaqsrc_get_timestamp_from_buffer_number (GstNiImaqSrc * niimaqsrc,
guint32 buffer_number) guint32 buffer_number)
{ {
GstClockTime timestamp = GST_CLOCK_TIME_NONE; GstClockTime abstime = GST_CLOCK_TIME_NONE;
GstNiImaqSrcFrameTime *frametime; GstNiImaqSrcFrameTime *frametime;
/* search linked list for frame time */ /* search linked list for frame time */
g_mutex_lock (niimaqsrc->frametime_mutex); g_mutex_lock (niimaqsrc->frametime_mutex);
if (G_LIKELY (niimaqsrc->timelist)
&& g_slist_length (niimaqsrc->timelist) > 0) { g_assert (niimaqsrc->timelist != NULL);
/* remove all old frametimes from the list */
/* remove all old frametimes from the list */
frametime = (GstNiImaqSrcFrameTime *) niimaqsrc->timelist->data;
while (frametime->number < buffer_number) {
niimaqsrc->timelist =
g_slist_delete_link (niimaqsrc->timelist, niimaqsrc->timelist);
frametime = (GstNiImaqSrcFrameTime *) niimaqsrc->timelist->data; frametime = (GstNiImaqSrcFrameTime *) niimaqsrc->timelist->data;
while (frametime->number < buffer_number) { }
niimaqsrc->timelist =
g_slist_delete_link (niimaqsrc->timelist, niimaqsrc->timelist);
frametime = (GstNiImaqSrcFrameTime *) niimaqsrc->timelist->data;
}
if (frametime->number == buffer_number) { if (frametime->number == buffer_number) {
timestamp = frametime->time; abstime = frametime->time;
/* remove frame time as we no longer need it */ /* remove frame time as we no longer need it */
niimaqsrc->timelist = niimaqsrc->timelist =
g_slist_delete_link (niimaqsrc->timelist, niimaqsrc->timelist); g_slist_delete_link (niimaqsrc->timelist, niimaqsrc->timelist);
} else { } else {
GST_WARNING_OBJECT (niimaqsrc, GST_WARNING_OBJECT (niimaqsrc,
"Did NOT find buffer date-timestamp in list generated by callback"); "Did NOT find buffer date-timestamp in list generated by callback");
}
} }
g_mutex_unlock (niimaqsrc->frametime_mutex); g_mutex_unlock (niimaqsrc->frametime_mutex);
return timestamp; return GST_CLOCK_DIFF (niimaqsrc->base_time, abstime);
} }
static GstFlowReturn static GstFlowReturn
@ -780,14 +790,7 @@ gst_niimaqsrc_create (GstPushSrc * psrc, GstBuffer ** buffer)
/* set timestamp */ /* set timestamp */
timestamp = timestamp =
gst_niimaqsrc_get_timestamp_from_buffer_number (niimaqsrc, copied_number); gst_niimaqsrc_get_timestamp_from_buffer_number (niimaqsrc, copied_number);
if (timestamp == GST_CLOCK_TIME_NONE) { g_assert (timestamp != GST_CLOCK_TIME_NONE);
GST_WARNING_OBJECT (niimaqsrc, "No timestamp found; callback failed?");
/* FIXME: the clock isn't valid before the first FVAL callback? */
} else {
timestamp =
GST_CLOCK_DIFF (gst_element_get_base_time (GST_ELEMENT (niimaqsrc)),
timestamp);
}
/* make guess of duration from timestamp and cumulative buffer number */ /* make guess of duration from timestamp and cumulative buffer number */
if (GST_CLOCK_TIME_IS_VALID (timestamp)) { if (GST_CLOCK_TIME_IS_VALID (timestamp)) {

View File

@ -49,26 +49,28 @@ typedef struct _GstNiImaqSrcClass GstNiImaqSrcClass;
struct _GstNiImaqSrc { struct _GstNiImaqSrc {
GstPushSrc element; GstPushSrc element;
/* properties */
gchar *interface_name;
gint bufsize;
/* image info */
GstVideoFormat format; GstVideoFormat format;
int width; int width;
int height; int height;
gint framesize; gint framesize;
int rowpixels; int rowpixels;
/* private */
GstClockTime running_time; /* total running time */
gint64 n_frames; /* total frames sent */ gint64 n_frames; /* total frames sent */
uInt32 cumbufnum; uInt32 cumbufnum;
gint64 n_dropped_frames; gint64 n_dropped_frames;
gboolean segment;
gint bufsize;
guint32** buflist; guint32** buflist;
gchar *interface_name;
INTERFACE_ID iid; INTERFACE_ID iid;
SESSION_ID sid; SESSION_ID sid;
gboolean session_started; gboolean session_started;
GstClockTime base_time;
GSList *timelist; GSList *timelist;
GMutex *frametime_mutex; GMutex *frametime_mutex;