diff options
-rw-r--r-- | include/xine/metronom.h | 10 | ||||
-rw-r--r-- | src/xine-engine/metronom.c | 80 |
2 files changed, 66 insertions, 24 deletions
diff --git a/include/xine/metronom.h b/include/xine/metronom.h index 4f4bb04eb..06beb3a5f 100644 --- a/include/xine/metronom.h +++ b/include/xine/metronom.h @@ -217,6 +217,16 @@ struct metronom_s { #define METRONOM_SPU_OFFSET 5 #define METRONOM_VPTS_OFFSET 6 #define METRONOM_PREBUFFER 7 +#define METRONOM_VPTS 8 +/* METRONOM_LOCK can be used to lock metronom when multiple options needs to be fetched atomically (ex. VPTS_OFFSET and AV_OFFSET). + * example: + * metronom->set_option(metronom, METRONOM_LOCK, 1); + * vpts_offset = metronom->get_option(metronom, METRONOM_VPTS_OFFSET|METRONOM_NO_LOCK); + * av_offset = metronom->get_option(metronom, METRONOM_AV_OFFSET|METRONOM_NO_LOCK); + * metronom->set_option(metronom, METRONOM_LOCK, 0); + */ +#define METRONOM_LOCK 9 +#define METRONOM_NO_LOCK 0x8000 metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_MALLOC XINE_PROTECTED; diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 3ca60267d..81d99f09b 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -269,10 +269,10 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) { pthread_mutex_lock (&this->lock); if (this->master) { - pthread_mutex_lock(&this->master->lock); + this->master->set_option(this->master, METRONOM_LOCK, 1); - this->vpts_offset = this->master->vpts_offset; - this->spu_offset = this->master->spu_offset; + this->vpts_offset = this->master->get_option(this->master, METRONOM_VPTS_OFFSET | METRONOM_NO_LOCK); + this->spu_offset = this->master->get_option(this->master, METRONOM_SPU_OFFSET | METRONOM_NO_LOCK); } vpts = pts + this->vpts_offset + this->spu_offset; @@ -284,7 +284,7 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) { this->spu_vpts = vpts; if (this->master) { - pthread_mutex_unlock(&this->master->lock); + this->master->set_option(this->master, METRONOM_LOCK, 0); } pthread_mutex_unlock (&this->lock); @@ -415,14 +415,13 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { pthread_mutex_lock (&this->lock); if (this->master) { - pthread_mutex_lock(&this->master->lock); + this->master->set_option(this->master, METRONOM_LOCK, 1); if (!this->discontinuity_handled_count) { /* we are not initialized yet */ - if (this->master->video_vpts > this->master->audio_vpts) - this->video_vpts = this->audio_vpts = this->master->video_vpts; - else - this->video_vpts = this->audio_vpts = this->master->audio_vpts; + + this->video_vpts = this->audio_vpts = this->master->get_option(this->master, METRONOM_VPTS | METRONOM_NO_LOCK); + /* when being attached to the first master, do not drift into * his vpts values but adopt at once */ this->force_audio_jump = 1; @@ -430,8 +429,8 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { this->discontinuity_handled_count++; } - this->vpts_offset = this->master->vpts_offset; - this->av_offset = this->master->av_offset; + this->vpts_offset = this->master->get_option(this->master, METRONOM_VPTS_OFFSET | METRONOM_NO_LOCK); + this->av_offset = this->master->get_option(this->master, METRONOM_AV_OFFSET | METRONOM_NO_LOCK); } lprintf("got_video_frame pts = %" PRId64 ", duration = %d\n", pts, img->duration); @@ -519,7 +518,7 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { this->video_vpts += this->img_duration; if (this->master) { - pthread_mutex_unlock(&this->master->lock); + this->master->set_option(this->master, METRONOM_LOCK, 0); } pthread_mutex_unlock (&this->lock); @@ -575,14 +574,13 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, pthread_mutex_lock (&this->lock); if (this->master) { - pthread_mutex_lock(&this->master->lock); + this->master->set_option(this->master, METRONOM_LOCK, 1); if (!this->discontinuity_handled_count) { /* we are not initialized yet */ - if (this->master->video_vpts > this->master->audio_vpts) - this->video_vpts = this->audio_vpts = this->master->video_vpts; - else - this->video_vpts = this->audio_vpts = this->master->audio_vpts; + + this->video_vpts = this->audio_vpts = this->master->get_option(this->master, METRONOM_VPTS | METRONOM_NO_LOCK); + this->audio_vpts_rmndr = 0; /* when being attached to the first master, do not drift into * his vpts values but adopt at once */ @@ -591,7 +589,7 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, this->discontinuity_handled_count++; } - this->vpts_offset = this->master->vpts_offset; + this->vpts_offset = this->master->get_option(this->master, METRONOM_VPTS_OFFSET | METRONOM_NO_LOCK); } if (pts && pts != this->last_audio_pts) { @@ -656,7 +654,7 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, lprintf("audio vpts for %10"PRId64" : %10"PRId64"\n", pts, vpts); if (this->master) { - pthread_mutex_unlock(&this->master->lock); + this->master->set_option(this->master, METRONOM_LOCK, 0); } pthread_mutex_unlock (&this->lock); @@ -666,6 +664,19 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, static void metronom_set_option (metronom_t *this, int option, int64_t value) { + if (option == METRONOM_LOCK) { + if (value) { + pthread_mutex_lock (&this->lock); + if (this->master) + this->master->set_option(this->master, option, value); + } else { + if (this->master) + this->master->set_option(this->master, option, value); + pthread_mutex_unlock (&this->lock); + } + return; + } + pthread_mutex_lock (&this->lock); if (this->master) { @@ -725,15 +736,24 @@ static void metronom_clock_set_option (metronom_clock_t *this, static int64_t metronom_get_option (metronom_t *this, int option) { int64_t result; + int mutex_locked; - pthread_mutex_lock (&this->lock); + if (option & METRONOM_NO_LOCK) { + mutex_locked = 0; + } else { + pthread_mutex_lock (&this->lock); + mutex_locked = 1; + } if (this->master) { result = this->master->get_option(this->master, option); - pthread_mutex_unlock (&this->lock); + if (mutex_locked) + pthread_mutex_unlock (&this->lock); return result; } + option &= ~METRONOM_NO_LOCK; + switch (option) { case METRONOM_AV_OFFSET: result = this->av_offset; @@ -750,13 +770,21 @@ static int64_t metronom_get_option (metronom_t *this, int option) { case METRONOM_PREBUFFER: result = this->prebuffer; break; + case METRONOM_VPTS: + if (this->video_vpts > this->audio_vpts) + result = this->video_vpts; + else + result = this->audio_vpts; + break; default: result = 0; xprintf(this->xine, XINE_VERBOSITY_NONE, "unknown option in get_option: %d\n", option); break; } - pthread_mutex_unlock (&this->lock); + if (mutex_locked) { + pthread_mutex_unlock (&this->lock); + } return result; } @@ -776,11 +804,15 @@ static void metronom_set_master(metronom_t *this, metronom_t *master) { pthread_mutex_lock(&this->lock); /* someone might currently be copying values from the old master, * so we need his lock too */ - if (old_master) pthread_mutex_lock(&old_master->lock); + if (old_master) + old_master->set_option(old_master, METRONOM_LOCK, 1); + this->master = master; /* new master -> we have to reinit */ this->discontinuity_handled_count = 0; - if (old_master) pthread_mutex_unlock(&old_master->lock); + + if (old_master) + old_master->set_option(old_master, METRONOM_LOCK, 0); pthread_mutex_unlock(&this->lock); } |