fix problem of needing to skip audio every 3-5 frames even when frames are finished in time.

replaced gettimeofday for clock_gettime in bio2jack driver
This commit is contained in:
niels
2013-01-04 22:57:40 +01:00
parent fa0673be72
commit a19fb4de85
3 changed files with 78 additions and 57 deletions

View File

@@ -70,9 +70,9 @@
a 'TIMER("stop\n")' at the end of any function and this does the rest a 'TIMER("stop\n")' at the end of any function and this does the rest
(naturally you can place any printf-compliant text you like in the argument (naturally you can place any printf-compliant text you like in the argument
along with the associated values). */ along with the associated values). */
static struct timeval timer_now; static struct timespec timer_now;
#define TIMER(format,args...) gettimeofday(&timer_now,0); \ #define TIMER(format,args...) gettimeofday(&timer_now,0); \
veejay_msg(4, "%ld.%06ld: %s::%s(%d) "format, timer_now.tv_sec, timer_now.tv_usec, __FILE__, __FUNCTION__, __LINE__, ##args) veejay_msg(4, "%ld.%06ld: %s::%s(%d) "format, timer_now.tv_sec, timer_now.tv_nsec, __FILE__, __FUNCTION__, __LINE__, ##args)
#else #else
#define TIMER(...) #define TIMER(...)
#endif #endif
@@ -150,7 +150,7 @@ typedef struct jack_driver_s
unsigned long rw_buffer1_size; /* number of bytes in the buffer allocated for processing data in JACK_(Read|Write) */ unsigned long rw_buffer1_size; /* number of bytes in the buffer allocated for processing data in JACK_(Read|Write) */
char *rw_buffer1; char *rw_buffer1;
struct timeval previousTime; /* time of last JACK_Callback() write to jack, allows for MS accurate bytes played */ struct timespec previousTime; /* time of last JACK_Callback() write to jack, allows for MS accurate bytes played */
unsigned long num_ticks; unsigned long num_ticks;
unsigned long chunk_size; unsigned long chunk_size;
@@ -192,7 +192,7 @@ typedef struct jack_driver_s
/* variables used for trying to restart the connection to jack */ /* variables used for trying to restart the connection to jack */
bool jackd_died; /* true if jackd has died and we should try to restart it */ bool jackd_died; /* true if jackd has died and we should try to restart it */
struct timeval last_reconnect_attempt; struct timespec last_reconnect_attempt;
} jack_driver_t; } jack_driver_t;
@@ -247,19 +247,27 @@ static void JACK_CleanupDriver(jack_driver_t * drv);
/* Return the difference between two timeval structures in terms of milliseconds */ /* Return the difference between two timeval structures in terms of milliseconds */
long long
TimeValDifference(struct timeval *start, struct timeval *end) TimeValDifference1(struct timespec *start, struct timespec *end)
{ {
double long ms; /* milliseconds value */ double long ms; /* milliseconds value */
ms = end->tv_sec - start->tv_sec; /* compute seconds difference */ ms = end->tv_sec - start->tv_sec; /* compute seconds difference */
ms *= (double) 1000; /* convert to milliseconds */ ms *= (double) 1000; /* convert to milliseconds */
ms += (double) (end->tv_usec - start->tv_usec) / (double) 1000; /* add on microseconds difference */ // ms += (double) (end->tv_usec - start->tv_usec) / (double) 1000; /* add on microseconds difference */
return (long) ms; return (long) ms;
} }
long
TimeValDifference( struct timespec *start, struct timespec *end)
{
return (( end->tv_sec * 1000000000) + end->tv_nsec ) -
(( start->tv_sec * 1000000000) + start->tv_nsec );
}
/* get a device and lock the devices mutex */ /* get a device and lock the devices mutex */
/* */ /* */
/* also attempt to reconnect to jack since this function is called from */ /* also attempt to reconnect to jack since this function is called from */
@@ -293,8 +301,8 @@ getDriver(int deviceID)
/* should we try to restart the jack server? */ /* should we try to restart the jack server? */
if(drv->jackd_died && drv->client == 0) if(drv->jackd_died && drv->client == 0)
{ {
struct timeval now; struct timespec now;
gettimeofday(&now, 0); clock_gettime( CLOCK_REALTIME, &now);
/* wait 250ms before trying again */ /* wait 250ms before trying again */
if(TimeValDifference(&drv->last_reconnect_attempt, &now) >= 250) if(TimeValDifference(&drv->last_reconnect_attempt, &now) >= 250)
@@ -516,8 +524,8 @@ JACK_callback(nframes_t nframes, void *arg)
drv->chunk_size = nframes; drv->chunk_size = nframes;
TIMER("start\n"); TIMER("start\n");
gettimeofday(&drv->previousTime, 0); /* record the current time */ // gettimeofday(&drv->previousTime, 0); /* record the current time */
clock_gettime( CLOCK_REALTIME, &drv->previousTime );
CALLBACK_TRACE("nframes %ld, sizeof(sample_t) == %d\n", (long) nframes, CALLBACK_TRACE("nframes %ld, sizeof(sample_t) == %d\n", (long) nframes,
sizeof(sample_t)); sizeof(sample_t));
@@ -550,9 +558,6 @@ JACK_callback(nframes_t nframes, void *arg)
long read = 0; long read = 0;
CALLBACK_TRACE("playing... jackFramesAvailable = %ld inputFramesAvailable = %ld\n",
jackFramesAvailable, inputFramesAvailable);
#if JACK_CLOSE_HACK #if JACK_CLOSE_HACK
if(drv->in_use == FALSE) if(drv->in_use == FALSE)
{ {
@@ -570,8 +575,6 @@ JACK_callback(nframes_t nframes, void *arg)
(&drv->callback_buffer2, &drv->callback_buffer2_size, (&drv->callback_buffer2, &drv->callback_buffer2_size,
jackBytesAvailable)) jackBytesAvailable))
{ {
return -1; return -1;
} }
@@ -2287,7 +2290,7 @@ JACK_GetPositionFromDriver(jack_driver_t * drv, enum pos_enum position,
int type) int type)
{ {
long return_val = 0; long return_val = 0;
struct timeval now; struct timespec now;
long elapsedMS; long elapsedMS;
double sec2msFactor = 1000; double sec2msFactor = 1000;
@@ -2312,7 +2315,8 @@ JACK_GetPositionFromDriver(jack_driver_t * drv, enum pos_enum position,
{ {
type_str = "PLAYED"; type_str = "PLAYED";
return_val = drv->played_client_bytes; return_val = drv->played_client_bytes;
gettimeofday(&now, 0); // gettimeofday(&now, 0);
clock_gettime( CLOCK_REALTIME, &now );
elapsedMS = TimeValDifference(&drv->previousTime, &now); /* find the elapsed milliseconds since last JACK_Callback() */ elapsedMS = TimeValDifference(&drv->previousTime, &now); /* find the elapsed milliseconds since last JACK_Callback() */
@@ -2526,8 +2530,9 @@ JACK_CleanupDriver(jack_driver_t * drv)
drv->output_sample_rate_ratio = 1.0; drv->output_sample_rate_ratio = 1.0;
drv->input_sample_rate_ratio = 1.0; drv->input_sample_rate_ratio = 1.0;
drv->jackd_died = FALSE; drv->jackd_died = FALSE;
gettimeofday(&drv->previousTime, 0); /* record the current time */ clock_gettime(CLOCK_REALTIME, &drv->previousTime); /* record the current time */
gettimeofday(&drv->last_reconnect_attempt, 0); // gettimeofday(&drv->last_reconnect_attempt, 0);
memcpy( &drv->last_reconnect_attempt, &drv->previousTime, sizeof(struct timespec));
} }
/* Initialize the jack porting library to a clean state */ /* Initialize the jack porting library to a clean state */
@@ -2677,11 +2682,11 @@ JACK_SetClientName(char *name)
} }
} }
long JACK_OutputStatus(int deviceID,long int *sec, long int *usec) long JACK_OutputStatus(int deviceID,long *sec, long *usec)
{ {
jack_driver_t *this = &outDev[deviceID]; jack_driver_t *this = &outDev[deviceID];
*sec = (long int) this->previousTime.tv_sec; *sec = this->previousTime.tv_sec;
*usec = (long int) this->previousTime.tv_usec; *usec = this->previousTime.tv_nsec;
return (this->num_ticks * this->chunk_size); return (this->num_ticks * this->chunk_size);
} }

View File

@@ -138,7 +138,7 @@ enum JACK_PORT_CONNECTION_MODE
/* defaults to CONNECT_ALL */ /* defaults to CONNECT_ALL */
void JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode); void JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode);
long JACK_OutputStatus(int deviceID,long int *sec, long int *usec); long JACK_OutputStatus(int deviceID,long *sec, long *usec);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -1239,6 +1239,7 @@ static void veejay_mjpeg_software_frame_sync(veejay_t * info,
{ {
video_playback_setup *settings = video_playback_setup *settings =
(video_playback_setup *) info->settings; (video_playback_setup *) info->settings;
// int skip = 0;
if (info->uc->use_timer ) { if (info->uc->use_timer ) {
@@ -1251,33 +1252,26 @@ static void veejay_mjpeg_software_frame_sync(veejay_t * info,
struct timespec nsecsleep; struct timespec nsecsleep;
int usec_since_lastframe=0; int usec_since_lastframe=0;
for (;;) { for (;;) {
clock_gettime( CLOCK_REALTIME, &now ); clock_gettime( CLOCK_REALTIME, &now );
//gettimeofday(&now, 0); //gettimeofday(&now, 0);
usec_since_lastframe = (now.tv_nsec / 1000) - (settings->lastframe_completion.tv_nsec / 1000); usec_since_lastframe = (now.tv_nsec - settings->lastframe_completion.tv_nsec)/1000;
if (usec_since_lastframe < 0)
// usec_since_lastframe =
// now.tv_usec - settings->lastframe_completion.tv_usec;
//usec_since_lastframe = vj_get_relative_time();
while (usec_since_lastframe < 0)
usec_since_lastframe += 1000000; usec_since_lastframe += 1000000;
// usec_since_lastframe += 1000000000;
if (now.tv_sec > settings->lastframe_completion.tv_sec + 1) if (now.tv_sec > settings->lastframe_completion.tv_sec + 1)
usec_since_lastframe = 1000000; usec_since_lastframe = 1000000;
if (settings->first_frame || (frame_periods * settings->usec_per_frame - usec_since_lastframe) < (1000000 / HZ)) if (settings->first_frame || (frame_periods * settings->usec_per_frame - usec_since_lastframe) < (1000000 / HZ)) {
break;
break;
/* Assume some other process will get a time-slice before }
* we do... and hence the worst-case delay of 1/HZ after
* sleep timer expiry will apply. Reasonable since X will nsecsleep.tv_nsec = (settings->usec_per_frame - usec_since_lastframe - 1000000 / HZ) * 1000;
* probably do something... // nsecsleep.tv_nsec = (frame_periods * settings->usec_per_frame - usec_since_lastframe - 1000000 / HZ) * 1000;
*/
nsecsleep.tv_nsec = (frame_periods * settings->usec_per_frame - usec_since_lastframe - 1000000 / HZ) * 1000;
nsecsleep.tv_sec = 0; nsecsleep.tv_sec = 0;
nanosleep(&nsecsleep, NULL); nanosleep(&nsecsleep, NULL);
} }
@@ -1286,8 +1280,17 @@ static void veejay_mjpeg_software_frame_sync(veejay_t * info,
settings->first_frame = 0; settings->first_frame = 0;
/* We are done with writing the picture - Now update all surrounding info */ /* We are done with writing the picture - Now update all surrounding info */
struct timespec lasttime;
memcpy( &lasttime, &(settings->lastframe_completion), sizeof(struct timespec));
clock_gettime( CLOCK_REALTIME, &(settings->lastframe_completion) ); clock_gettime( CLOCK_REALTIME, &(settings->lastframe_completion) );
/*
if( skip) {
long d1 = (settings->lastframe_completion.tv_sec * 1000000000) + settings->lastframe_completion.tv_nsec;
long d2 = (lasttime.tv_sec * 1000000000) + lasttime.tv_nsec;
double diff = ( ( double) d1-d2)/1000000000.0;
}*/
// gettimeofday(&(settings->lastframe_completion), 0); // gettimeofday(&(settings->lastframe_completion), 0);
settings->syncinfo[settings->currently_processed_frame].timestamp = settings->lastframe_completion; settings->syncinfo[settings->currently_processed_frame].timestamp = settings->lastframe_completion;
} }
@@ -2635,8 +2638,13 @@ static void veejay_playback_cycle(veejay_t * info)
stats.nsync++; stats.nsync++;
clock_gettime( CLOCK_REALTIME, &time_now); clock_gettime( CLOCK_REALTIME, &time_now);
stats.tdiff = ( time_now.tv_sec - bs.timestamp.tv_sec ) + long d1 = (time_now.tv_sec * 1000000000) + time_now.tv_nsec;
( ( time_now.tv_nsec - bs.timestamp.tv_nsec / 1000 ) * 1.e-6); long n1 = (bs.timestamp.tv_sec * 1000000000) + bs.timestamp.tv_nsec;
double dn = ( (double) (d1 - n1) )/10000000.0; // * 1.e7;
stats.tdiff = dn; // ( time_now.tv_sec - bs.timestamp.tv_sec ) +
// ( ( time_now.tv_nsec - bs.timestamp.tv_nsec / 1000 ) * 1.e-6);
} }
while (stats.tdiff > settings->spvf && (stats.nsync - first_free) < (QUEUE_LEN-1)); while (stats.tdiff > settings->spvf && (stats.nsync - first_free) < (QUEUE_LEN-1));
@@ -2653,25 +2661,33 @@ static void veejay_playback_cycle(veejay_t * info)
long int sec=0; long int sec=0;
long int usec=0; long int usec=0;
long num_audio_bytes_written = vj_jack_get_status( &sec,&usec); long num_audio_bytes_written = vj_jack_get_status( &sec,&usec);
long as = (el->audio_rate / el->video_fps) * el->audio_bps;
long musec = time_now.tv_nsec / 1000;
long msec = time_now.tv_sec;
audio_tmstmp.tv_sec = sec; audio_tmstmp.tv_sec = sec;
audio_tmstmp.tv_nsec = (1000 * usec); audio_tmstmp.tv_nsec = usec; //(1000 * usec);
if( audio_tmstmp.tv_sec ) { if( audio_tmstmp.tv_sec ) {
//@ measure against bytes written to jack //@ measure against bytes written to jack
tdiff1 = settings->spvf * (stats.nsync - nvcorr) - tdiff1 = settings->spvf * (stats.nsync - nvcorr) -
settings->spas * num_audio_bytes_written; settings->spas * num_audio_bytes_written;
//tdiff2 = (bs.timestamp.tv_sec - audio_tmstmp.tv_sec) + (bs.timestamp.tv_usec - audio_tmstmp.tv_usec) * 1.e-6;
tdiff2 = (bs.timestamp.tv_sec - audio_tmstmp.tv_sec ) + ( (bs.timestamp.tv_nsec - audio_tmstmp.tv_nsec )/1000) * 1.e-6; //1000000000
long d1 = (bs.timestamp.tv_sec * 1000000000) + bs.timestamp.tv_nsec;
long n1 = (audio_tmstmp.tv_sec * 1000000000) + audio_tmstmp.tv_nsec;
tdiff2 = ( (double) (d1 - n1) )/ 1000000000.0; // * 1.e7;
//10000000
last_tdiff = tdiff1; last_tdiff = tdiff1;
double tt = tdiff1 - tdiff2;
if( tt > settings->spvf && tt <= (settings->spvf *1.01) ) {
tdiff2 += 0.01;
}
//@ tt > spvf
// tdiff2 = (bs.timestamp.tv_sec - audio_tmstmp.tv_sec ) + ( (bs.timestamp.tv_nsec - audio_tmstmp.tv_nsec )/1000) * 1.e-6;
} }
} }
#endif #endif
@@ -2689,16 +2705,15 @@ static void veejay_playback_cycle(veejay_t * info)
if (info->sync_correction) { if (info->sync_correction) {
if (stats.tdiff > settings->spvf) { if (stats.tdiff > settings->spvf) {
skipa = 1; skipa = 1;
//skipv = 1; // skipv = 1;
if (info->sync_ins_frames && current_speed != 0) { if (info->sync_ins_frames && current_speed != 0) {
skipi = 1; skipi = 1;
} }
nvcorr++; nvcorr++;
stats.num_corrs_a++; stats.num_corrs_a++;
stats.tdiff -= settings->spvf; stats.tdiff -= settings->spvf;
stats.stats_changed = 1; stats.stats_changed = 1;
} }
if (stats.tdiff < -settings->spvf) { if (stats.tdiff < -settings->spvf) {
/* Video is behind audio */ /* Video is behind audio */
skipv = 1; skipv = 1;
@@ -2750,8 +2765,9 @@ static void veejay_playback_cycle(veejay_t * info)
#endif #endif
if( info->real_fps > (1000* settings->spvf ) && info->audio ) { if( info->real_fps > (1000* settings->spvf ) && info->audio ) {
veejay_msg(VEEJAY_MSG_WARNING, "Rendering video frame takes too long! (measured %ld ms).", info->real_fps); veejay_msg(VEEJAY_MSG_WARNING, "Rendering video frame takes too long! (measured %ld ms).", info->real_fps);
} continue;
}
if(!info->audio && skipv ) continue; if(!info->audio && skipv ) continue;
veejay_mjpeg_queue_buf(info,frame, 1 ); veejay_mjpeg_queue_buf(info,frame, 1 );