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);
GstClock *clock;
GstNiImaqSrcFrameTime *frametime = g_new (GstNiImaqSrcFrameTime, 1);
uInt32 val;
GstNiImaqSrcFrameTime *frametime;
guint32 bufnum;
GstClockTime abstime;
if (!niimaqsrc->session_started)
return 1;
if (G_UNLIKELY (niimaqsrc->start_time == NULL))
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));
if (G_LIKELY (clock)) {
frametime->time = gst_clock_get_time (clock);
gst_object_unref (clock);
} else {
frametime->time = GST_CLOCK_TIME_NONE;
}
g_assert (clock != NULL);
abstime = gst_clock_get_time (clock);
/* get current frame number */
imgGetAttribute (sid, IMG_ATTR_FRAME_COUNT, &val);
frametime->number = val;
imgGetAttribute (sid, IMG_ATTR_FRAME_COUNT, &bufnum);
/* 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 */
g_mutex_lock (niimaqsrc->frametime_mutex);
niimaqsrc->timelist = g_slist_append (niimaqsrc->timelist, frametime);
g_mutex_unlock (niimaqsrc->frametime_mutex);
gst_object_unref (clock);
/* return 1 to rearm the callback */
return 1;
}
@ -654,6 +663,7 @@ gst_niimaqsrc_reset (GstNiImaqSrc * niimaqsrc)
niimaqsrc->timelist = NULL;
niimaqsrc->start_time = NULL;
niimaqsrc->start_time_sent = FALSE;
niimaqsrc->base_time = GST_CLOCK_TIME_NONE;
}
static gboolean
@ -692,36 +702,36 @@ static GstClockTime
gst_niimaqsrc_get_timestamp_from_buffer_number (GstNiImaqSrc * niimaqsrc,
guint32 buffer_number)
{
GstClockTime timestamp = GST_CLOCK_TIME_NONE;
GstClockTime abstime = GST_CLOCK_TIME_NONE;
GstNiImaqSrcFrameTime *frametime;
/* search linked list for frame time */
g_mutex_lock (niimaqsrc->frametime_mutex);
if (G_LIKELY (niimaqsrc->timelist)
&& g_slist_length (niimaqsrc->timelist) > 0) {
/* remove all old frametimes from the list */
g_assert (niimaqsrc->timelist != NULL);
/* 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;
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) {
timestamp = frametime->time;
if (frametime->number == buffer_number) {
abstime = frametime->time;
/* remove frame time as we no longer need it */
niimaqsrc->timelist =
g_slist_delete_link (niimaqsrc->timelist, niimaqsrc->timelist);
} else {
GST_WARNING_OBJECT (niimaqsrc,
"Did NOT find buffer date-timestamp in list generated by callback");
}
/* remove frame time as we no longer need it */
niimaqsrc->timelist =
g_slist_delete_link (niimaqsrc->timelist, niimaqsrc->timelist);
} else {
GST_WARNING_OBJECT (niimaqsrc,
"Did NOT find buffer date-timestamp in list generated by callback");
}
g_mutex_unlock (niimaqsrc->frametime_mutex);
return timestamp;
return GST_CLOCK_DIFF (niimaqsrc->base_time, abstime);
}
static GstFlowReturn
@ -780,14 +790,7 @@ gst_niimaqsrc_create (GstPushSrc * psrc, GstBuffer ** buffer)
/* set timestamp */
timestamp =
gst_niimaqsrc_get_timestamp_from_buffer_number (niimaqsrc, copied_number);
if (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);
}
g_assert (timestamp != GST_CLOCK_TIME_NONE);
/* make guess of duration from timestamp and cumulative buffer number */
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {

View File

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