mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-15 20:30: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
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|||||||
Reference in New Issue
Block a user