diff options
Diffstat (limited to 'src/xine-engine/metronom.c')
-rw-r--r-- | src/xine-engine/metronom.c | 132 |
1 files changed, 72 insertions, 60 deletions
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 5f7a60631..81d99f09b 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -40,9 +40,9 @@ #define METRONOM_INTERNAL #define METRONOM_CLOCK_INTERNAL -#include "xine_internal.h" -#include "metronom.h" -#include "xineutils.h" +#include <xine/xine_internal.h> +#include <xine/metronom.h> +#include <xine/xineutils.h> #define MAX_AUDIO_DELTA 1600 #define AUDIO_SAMPLE_NUM 32768 @@ -269,21 +269,10 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) { pthread_mutex_lock (&this->lock); if (this->master) { - metronom_t *master = this->master; + this->master->set_option(this->master, METRONOM_LOCK, 1); - pthread_mutex_lock(&this->master->lock); - pthread_mutex_unlock(&this->lock); - - this->vpts_offset = this->master->vpts_offset; - this->spu_offset = this->master->spu_offset; - - /* no recursion, please */ - this->master = NULL; - vpts = master->got_spu_packet(this, pts); - this->master = master; - - pthread_mutex_unlock(&this->master->lock); - return vpts; + 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; @@ -294,6 +283,10 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) { this->spu_vpts = vpts; + if (this->master) { + this->master->set_option(this->master, METRONOM_LOCK, 0); + } + pthread_mutex_unlock (&this->lock); return vpts; } @@ -422,17 +415,13 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { pthread_mutex_lock (&this->lock); if (this->master) { - metronom_t *master = this->master; - - pthread_mutex_lock(&this->master->lock); - pthread_mutex_unlock(&this->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; @@ -440,16 +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; - - /* no recursion, please */ - this->master = NULL; - master->got_video_frame(this, img); - this->master = master; - - pthread_mutex_unlock(&this->master->lock); - return; + 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); @@ -536,6 +517,10 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { */ this->video_vpts += this->img_duration; + if (this->master) { + this->master->set_option(this->master, METRONOM_LOCK, 0); + } + pthread_mutex_unlock (&this->lock); } @@ -589,17 +574,13 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, pthread_mutex_lock (&this->lock); if (this->master) { - metronom_t *master = this->master; - - pthread_mutex_lock(&this->master->lock); - pthread_mutex_unlock(&this->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 */ @@ -608,15 +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; - - /* no recursion, please */ - this->master = NULL; - vpts = master->got_audio_samples(this, pts, nsamples); - this->master = master; - - pthread_mutex_unlock(&this->master->lock); - return vpts; + this->vpts_offset = this->master->get_option(this->master, METRONOM_VPTS_OFFSET | METRONOM_NO_LOCK); } if (pts && pts != this->last_audio_pts) { @@ -680,6 +653,10 @@ 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) { + this->master->set_option(this->master, METRONOM_LOCK, 0); + } + pthread_mutex_unlock (&this->lock); return vpts; @@ -687,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) { @@ -746,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; @@ -771,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; } @@ -797,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); } @@ -866,7 +877,8 @@ static void metronom_unregister_scr (metronom_clock_t *this, scr_plugin_t *scr) this->scr_master = get_master_scr(this); } -static int metronom_sync_loop (metronom_clock_t *this) { +static void *metronom_sync_loop (void *const this_gen) { + metronom_clock_t *const this = (metronom_clock_t *const)this_gen; struct timeval tv; struct timespec ts; @@ -889,7 +901,7 @@ static int metronom_sync_loop (metronom_clock_t *this) { pthread_mutex_unlock (&this->lock); } - return 0; + return NULL; } static void metronom_exit (metronom_t *this) { @@ -1005,7 +1017,7 @@ metronom_clock_t *_x_metronom_clock_init(xine_t *xine) this->thread_running = 1; if ((err = pthread_create(&this->sync_thread, NULL, - (void*(*)(void*)) metronom_sync_loop, this)) != 0) + metronom_sync_loop, this)) != 0) xprintf(this->xine, XINE_VERBOSITY_NONE, "cannot create sync thread (%s)\n", strerror(err)); |