mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-15 04:10:00 +01:00
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:
@@ -70,9 +70,9 @@
|
||||
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
|
||||
along with the associated values). */
|
||||
static struct timeval timer_now;
|
||||
static struct timespec timer_now;
|
||||
#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
|
||||
#define TIMER(...)
|
||||
#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) */
|
||||
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 chunk_size;
|
||||
@@ -192,7 +192,7 @@ typedef struct jack_driver_s
|
||||
|
||||
/* 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 */
|
||||
struct timeval last_reconnect_attempt;
|
||||
struct timespec last_reconnect_attempt;
|
||||
} 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 */
|
||||
|
||||
long
|
||||
TimeValDifference(struct timeval *start, struct timeval *end)
|
||||
TimeValDifference1(struct timespec *start, struct timespec *end)
|
||||
{
|
||||
double long ms; /* milliseconds value */
|
||||
|
||||
ms = end->tv_sec - start->tv_sec; /* compute seconds difference */
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
/* */
|
||||
/* 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? */
|
||||
if(drv->jackd_died && drv->client == 0)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, 0);
|
||||
struct timespec now;
|
||||
clock_gettime( CLOCK_REALTIME, &now);
|
||||
|
||||
/* wait 250ms before trying again */
|
||||
if(TimeValDifference(&drv->last_reconnect_attempt, &now) >= 250)
|
||||
@@ -516,8 +524,8 @@ JACK_callback(nframes_t nframes, void *arg)
|
||||
drv->chunk_size = nframes;
|
||||
|
||||
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,
|
||||
sizeof(sample_t));
|
||||
|
||||
@@ -550,9 +558,6 @@ JACK_callback(nframes_t nframes, void *arg)
|
||||
|
||||
long read = 0;
|
||||
|
||||
CALLBACK_TRACE("playing... jackFramesAvailable = %ld inputFramesAvailable = %ld\n",
|
||||
jackFramesAvailable, inputFramesAvailable);
|
||||
|
||||
#if JACK_CLOSE_HACK
|
||||
if(drv->in_use == FALSE)
|
||||
{
|
||||
@@ -570,8 +575,6 @@ JACK_callback(nframes_t nframes, void *arg)
|
||||
(&drv->callback_buffer2, &drv->callback_buffer2_size,
|
||||
jackBytesAvailable))
|
||||
{
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2287,7 +2290,7 @@ JACK_GetPositionFromDriver(jack_driver_t * drv, enum pos_enum position,
|
||||
int type)
|
||||
{
|
||||
long return_val = 0;
|
||||
struct timeval now;
|
||||
struct timespec now;
|
||||
long elapsedMS;
|
||||
double sec2msFactor = 1000;
|
||||
|
||||
@@ -2312,7 +2315,8 @@ JACK_GetPositionFromDriver(jack_driver_t * drv, enum pos_enum position,
|
||||
{
|
||||
type_str = "PLAYED";
|
||||
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() */
|
||||
|
||||
@@ -2526,8 +2530,9 @@ JACK_CleanupDriver(jack_driver_t * drv)
|
||||
drv->output_sample_rate_ratio = 1.0;
|
||||
drv->input_sample_rate_ratio = 1.0;
|
||||
drv->jackd_died = FALSE;
|
||||
gettimeofday(&drv->previousTime, 0); /* record the current time */
|
||||
gettimeofday(&drv->last_reconnect_attempt, 0);
|
||||
clock_gettime(CLOCK_REALTIME, &drv->previousTime); /* record the current time */
|
||||
// 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 */
|
||||
@@ -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];
|
||||
*sec = (long int) this->previousTime.tv_sec;
|
||||
*usec = (long int) this->previousTime.tv_usec;
|
||||
*sec = this->previousTime.tv_sec;
|
||||
*usec = this->previousTime.tv_nsec;
|
||||
return (this->num_ticks * this->chunk_size);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ enum JACK_PORT_CONNECTION_MODE
|
||||
/* defaults to CONNECT_ALL */
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1239,6 +1239,7 @@ static void veejay_mjpeg_software_frame_sync(veejay_t * info,
|
||||
{
|
||||
video_playback_setup *settings =
|
||||
(video_playback_setup *) info->settings;
|
||||
// int skip = 0;
|
||||
|
||||
if (info->uc->use_timer ) {
|
||||
|
||||
@@ -1251,33 +1252,26 @@ static void veejay_mjpeg_software_frame_sync(veejay_t * info,
|
||||
struct timespec nsecsleep;
|
||||
|
||||
int usec_since_lastframe=0;
|
||||
|
||||
for (;;) {
|
||||
clock_gettime( CLOCK_REALTIME, &now );
|
||||
//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;
|
||||
|
||||
|
||||
// usec_since_lastframe =
|
||||
// now.tv_usec - settings->lastframe_completion.tv_usec;
|
||||
//usec_since_lastframe = vj_get_relative_time();
|
||||
|
||||
while (usec_since_lastframe < 0)
|
||||
if (usec_since_lastframe < 0)
|
||||
usec_since_lastframe += 1000000;
|
||||
// usec_since_lastframe += 1000000000;
|
||||
if (now.tv_sec > settings->lastframe_completion.tv_sec + 1)
|
||||
usec_since_lastframe = 1000000;
|
||||
|
||||
|
||||
if (settings->first_frame || (frame_periods * settings->usec_per_frame - usec_since_lastframe) < (1000000 / HZ))
|
||||
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
|
||||
* probably do something...
|
||||
*/
|
||||
nsecsleep.tv_nsec = (frame_periods * settings->usec_per_frame - usec_since_lastframe - 1000000 / HZ) * 1000;
|
||||
if (settings->first_frame || (frame_periods * settings->usec_per_frame - usec_since_lastframe) < (1000000 / HZ)) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
nsecsleep.tv_nsec = (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;
|
||||
nanosleep(&nsecsleep, NULL);
|
||||
}
|
||||
@@ -1286,8 +1280,17 @@ static void veejay_mjpeg_software_frame_sync(veejay_t * info,
|
||||
|
||||
settings->first_frame = 0;
|
||||
/* 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) );
|
||||
/*
|
||||
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);
|
||||
settings->syncinfo[settings->currently_processed_frame].timestamp = settings->lastframe_completion;
|
||||
}
|
||||
@@ -2635,8 +2638,13 @@ static void veejay_playback_cycle(veejay_t * info)
|
||||
stats.nsync++;
|
||||
clock_gettime( CLOCK_REALTIME, &time_now);
|
||||
|
||||
stats.tdiff = ( time_now.tv_sec - bs.timestamp.tv_sec ) +
|
||||
( ( time_now.tv_nsec - bs.timestamp.tv_nsec / 1000 ) * 1.e-6);
|
||||
long d1 = (time_now.tv_sec * 1000000000) + time_now.tv_nsec;
|
||||
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));
|
||||
@@ -2653,25 +2661,33 @@ static void veejay_playback_cycle(veejay_t * info)
|
||||
long int sec=0;
|
||||
long int usec=0;
|
||||
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_nsec = (1000 * usec);
|
||||
audio_tmstmp.tv_nsec = usec; //(1000 * usec);
|
||||
if( audio_tmstmp.tv_sec ) {
|
||||
//@ measure against bytes written to jack
|
||||
tdiff1 = settings->spvf * (stats.nsync - nvcorr) -
|
||||
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;
|
||||
|
||||
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
|
||||
@@ -2689,16 +2705,15 @@ static void veejay_playback_cycle(veejay_t * info)
|
||||
if (info->sync_correction) {
|
||||
if (stats.tdiff > settings->spvf) {
|
||||
skipa = 1;
|
||||
//skipv = 1;
|
||||
// skipv = 1;
|
||||
if (info->sync_ins_frames && current_speed != 0) {
|
||||
skipi = 1;
|
||||
}
|
||||
|
||||
nvcorr++;
|
||||
stats.num_corrs_a++;
|
||||
stats.tdiff -= settings->spvf;
|
||||
stats.stats_changed = 1;
|
||||
}
|
||||
stats.stats_changed = 1;
|
||||
}
|
||||
if (stats.tdiff < -settings->spvf) {
|
||||
/* Video is behind audio */
|
||||
skipv = 1;
|
||||
@@ -2750,8 +2765,9 @@ static void veejay_playback_cycle(veejay_t * info)
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!info->audio && skipv ) continue;
|
||||
|
||||
veejay_mjpeg_queue_buf(info,frame, 1 );
|
||||
|
||||
Reference in New Issue
Block a user