summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xine/vdr.h4
-rw-r--r--src/vdr/input_vdr.c381
2 files changed, 340 insertions, 45 deletions
diff --git a/include/xine/vdr.h b/include/xine/vdr.h
index 1f253cdbe..77a7a41f8 100644
--- a/include/xine/vdr.h
+++ b/include/xine/vdr.h
@@ -22,7 +22,7 @@
#define __VDR_H
-#define XINE_VDR_VERSION 900
+#define XINE_VDR_VERSION 901
enum funcs
@@ -441,6 +441,7 @@ result_grab_image_t;
typedef struct __attribute__((packed)) data_get_pts_s
{
data_header_t header;
+ int32_t ms_timeout;
}
data_get_pts_t;
@@ -451,6 +452,7 @@ typedef struct __attribute__((packed)) result_get_pts_s
result_header_t header;
int64_t pts;
+ int8_t queued;
}
result_get_pts_t;
diff --git a/src/vdr/input_vdr.c b/src/vdr/input_vdr.c
index e28858c52..76be59564 100644
--- a/src/vdr/input_vdr.c
+++ b/src/vdr/input_vdr.c
@@ -82,6 +82,16 @@ typedef struct vdr_osd_s
vdr_osd_t;
+typedef struct vdr_vpts_offset_s vdr_vpts_offset_t;
+
+struct vdr_vpts_offset_s
+{
+ vdr_vpts_offset_t *next;
+ int64_t vpts;
+ int64_t offset;
+};
+
+
struct vdr_input_plugin_s
{
input_plugin_t input_plugin;
@@ -126,6 +136,14 @@ struct vdr_input_plugin_s
pthread_cond_t rpc_thread_shutdown_cond;
int startup_phase;
+ pthread_t metronom_thread;
+ pthread_mutex_t metronom_thread_lock;
+ int64_t metronom_thread_request;
+ int metronom_thread_reply;
+ pthread_cond_t metronom_thread_request_cond;
+ pthread_cond_t metronom_thread_reply_cond;
+ pthread_mutex_t metronom_thread_call_lock;
+
xine_event_queue_t *event_queue;
xine_event_queue_t *event_queue_external;
@@ -140,6 +158,12 @@ struct vdr_input_plugin_s
vdr_metronom_t metronom;
int last_disc_type;
+
+ vdr_vpts_offset_t *vpts_offset_queue;
+ vdr_vpts_offset_t *vpts_offset_queue_tail;
+ pthread_mutex_t vpts_offset_queue_lock;
+ pthread_cond_t vpts_offset_queue_changed_cond;
+ int vpts_offset_queue_changes;
};
@@ -308,7 +332,7 @@ static void adjust_zoom(vdr_input_plugin_t *this)
&& this->image16_9_zoom_x && this->image16_9_zoom_y)
{
int ratio = (int)(10000 * this->frame_size.r + 0.5);
-fprintf(stderr, "ratio: %d\n", ratio);
+ /* fprintf(stderr, "ratio: %d\n", ratio); */
if (13332 <= ratio && ratio <= 13334)
{
xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, this->image4_3_zoom_x);
@@ -324,6 +348,29 @@ fprintf(stderr, "ratio: %d\n", ratio);
pthread_mutex_unlock(&this->adjust_zoom_lock);
}
+
+static void vdr_vpts_offset_queue_process(vdr_input_plugin_t *this, int64_t vpts)
+{
+ while (this->vpts_offset_queue
+ && this->vpts_offset_queue->vpts <= vpts)
+ {
+ vdr_vpts_offset_t *curr = this->vpts_offset_queue;
+ this->vpts_offset_queue = curr->next;
+
+ free(curr);
+ }
+
+ if (!this->vpts_offset_queue)
+ this->vpts_offset_queue_tail = 0;
+}
+
+
+static void vdr_vpts_offset_queue_purge(vdr_input_plugin_t *this)
+{
+ vdr_vpts_offset_queue_process(this, 1ll << 62);
+}
+
+
static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this)
{
data_union_t data_union;
@@ -489,7 +536,7 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this)
{
READ_DATA_OR_FAIL(osd_draw_bitmap, LOG_OSD(lprintf("got OSDDRAWBITMAP\n")));
/*
- fprintf(stderr, "vdr: osddrawbitmap %d\n", data->window);
+ fprintf(stderr, "vdr: osddrawbitmap %d, %d, %d, %d, %d, %d\n", data->window, data->x, data->y, data->width, data->height, data->argb);
*/
if (this->osd_buffer_size < this->cur_size)
{
@@ -650,7 +697,7 @@ static off_t vdr_execute_rpc_command(vdr_input_plugin_t *this)
int orig_speed = xine_get_param(this->stream, XINE_PARAM_FINE_SPEED);
if (orig_speed <= 0)
xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL);
-fprintf(stderr, "+++ CLEAR(%d%c): sync point: %02x\n", data->n, data->s ? 'b' : 'a', data->i);
+/* fprintf(stderr, "+++ CLEAR(%d%c): sync point: %02x\n", data->n, data->s ? 'b' : 'a', data->i); */
if (!data->s)
{
pthread_mutex_lock(&this->find_sync_point_lock);
@@ -662,16 +709,16 @@ fprintf(stderr, "+++ CLEAR(%d%c): sync point: %02x\n", data->n, data->s ? 'b' :
xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, 0);
*/
_x_demux_flush_engine(this->stream);
-fprintf(stderr, "=== CLEAR(%d.1)\n", data->n);
+/* fprintf(stderr, "=== CLEAR(%d.1)\n", data->n); */
_x_demux_control_start(this->stream);
-fprintf(stderr, "=== CLEAR(%d.2)\n", data->n);
+/* fprintf(stderr, "=== CLEAR(%d.2)\n", data->n); */
_x_demux_seek(this->stream, 0, 0, 0);
-fprintf(stderr, "=== CLEAR(%d.3)\n", data->n);
+/* fprintf(stderr, "=== CLEAR(%d.3)\n", data->n); */
_x_stream_info_reset(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE);
-fprintf(stderr, "=== CLEAR(%d.4)\n", data->n);
+/* fprintf(stderr, "=== CLEAR(%d.4)\n", data->n); */
_x_meta_info_reset(this->stream, XINE_META_INFO_AUDIOCODEC);
-fprintf(stderr, "=== CLEAR(%d.5)\n", data->n);
+/* fprintf(stderr, "=== CLEAR(%d.5)\n", data->n); */
_x_trigger_relaxed_frame_drop_mode(this->stream);
/* _x_reset_relaxed_frame_drop_mode(this->stream); */
@@ -679,7 +726,7 @@ fprintf(stderr, "=== CLEAR(%d.5)\n", data->n);
if (!this->dont_change_xine_volume)
xine_set_param(this->stream, XINE_PARAM_AUDIO_VOLUME, this->last_volume);
*/
-fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
+/* fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a'); */
if (orig_speed <= 0)
xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, orig_speed);
}
@@ -765,7 +812,7 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
event.type = XINE_EVENT_VDR_TRICKSPEEDMODE;
event.data = 0;
- event.data_length = this->trick_speed_mode;
+ event.data_length = 0; /* this->trick_speed_mode; */
/* fprintf(stderr, "************************: %p, %d\n", event.data, event.data_length); */
xine_event_send(this->stream, &event);
}
@@ -849,7 +896,7 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
}
_t2 = _now();
- fprintf(stderr, "vdr: flush: n: %d, %.1lf\n", _n, _t2 - _t1);
+ /* fprintf(stderr, "vdr: flush: n: %d, %.1lf\n", _n, _t2 - _t1); */
xprintf(this->stream->xine
, XINE_VERBOSITY_LOG
@@ -884,8 +931,9 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
case func_set_volume:
{
+double t3, t2, t1, t0;
READ_DATA_OR_FAIL(set_volume, lprintf("got SETVOLUME\n"));
-
+t0 = _now();
{
int change_volume = (this->volume_mode != XINE_VDR_VOLUME_IGNORE);
int do_mute = (this->last_volume != 0 && 0 == data->volume);
@@ -918,12 +966,14 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
return -1;
};
}
+t1 = _now();
if (change_volume)
{
report_change = 1;
xine_set_param(this->stream, param_volume, this->last_volume);
}
+t2 = _now();
if (report_change && this->volume_mode != XINE_VDR_VOLUME_CHANGE_SW)
{
@@ -935,6 +985,7 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
= xine_get_param(this->stream, param_volume);
data.mute
= xine_get_param(this->stream, param_mute);
+t3 = _now();
event.type = XINE_EVENT_AUDIO_LEVEL;
event.data = &data;
@@ -943,6 +994,7 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
xine_event_send(this->stream, &event);
}
}
+/* fprintf(stderr, "volume: %6.3lf ms, %6.3lf ms, %6.3lf ms\n", t1 - t0, t2 - t1, t3 - t2); */
}
break;
@@ -1074,13 +1126,80 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
case func_get_pts:
{
READ_DATA_OR_FAIL(get_pts, lprintf("got GETPTS\n"));
-
+
{
result_get_pts_t result_get_pts;
result_get_pts.header.func = data->header.func;
result_get_pts.header.len = sizeof (result_get_pts);
+
+ pthread_mutex_lock(&this->vpts_offset_queue_lock);
+
+ while (this->vpts_offset_queue_changes)
+ pthread_cond_wait(&this->vpts_offset_queue_changed_cond, &this->vpts_offset_queue_lock);
+
+ if (this->last_disc_type == DISC_STREAMSTART
+ && data->ms_timeout > 0)
+ {
+ struct timespec abstime;
+ {
+ struct timeval now;
+ gettimeofday(&now, 0);
+
+ abstime.tv_sec = now.tv_sec + data->ms_timeout / 1000;
+ abstime.tv_nsec = now.tv_usec * 1000 + (data->ms_timeout % 1000) * 1e6;
- result_get_pts.pts = (this->last_disc_type == DISC_STREAMSTART) ? -2 : (xine_get_current_vpts(this->stream) - this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET));
+ if (abstime.tv_nsec > 1e9)
+ {
+ abstime.tv_nsec -= 1e9;
+ abstime.tv_sec++;
+ }
+ }
+
+ while (this->last_disc_type == DISC_STREAMSTART
+ || this->vpts_offset_queue_changes)
+ {
+ if (0 != pthread_cond_timedwait(&this->vpts_offset_queue_changed_cond, &this->vpts_offset_queue_lock, &abstime))
+ break;
+ }
+ }
+
+ if (this->last_disc_type == DISC_STREAMSTART
+ || this->vpts_offset_queue_changes)
+ {
+ result_get_pts.pts = -1;
+ result_get_pts.queued = 0;
+ }
+ else
+ {
+ int64_t offset, vpts = xine_get_current_vpts(this->stream);
+
+ vdr_vpts_offset_queue_process(this, vpts);
+
+/* if(this->vpts_offset_queue) */
+if(0)
+ {
+fprintf(stderr, "C ---------------------------------------------\n");
+ vdr_vpts_offset_t *p = this->vpts_offset_queue;
+ while (p)
+ {
+ fprintf(stderr, "C now: %12"PRId64", vpts: %12"PRId64", offset: %12"PRId64"\n", xine_get_current_vpts(this->stream), p->vpts, p->offset);
+ p = p->next;
+ }
+fprintf(stderr, "C =============================================\n");
+ }
+
+ if (this->vpts_offset_queue)
+ offset = this->vpts_offset_queue->offset;
+ else
+ offset = this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET);
+
+ result_get_pts.pts = (vpts - offset) & ((1ll << 33) - 1);
+ result_get_pts.queued = !!this->vpts_offset_queue;
+/* fprintf(stderr, "vpts: %12ld, stc: %12ld, offset: %12ld\n", vpts, result_get_pts.pts, offset); */
+ }
+
+ pthread_mutex_unlock(&this->vpts_offset_queue_lock);
+
if (sizeof (result_get_pts) != vdr_write(this->fh_result, &result_get_pts, sizeof (result_get_pts)))
return -1;
}
@@ -1142,13 +1261,13 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
result_video_size.width = this->frame_size.w;
result_video_size.height = this->frame_size.h;
}
-//fprintf(stderr, "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n");
+/* fprintf(stderr, "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n"); */
result_video_size.zoom_x = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_X);
result_video_size.zoom_y = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_Y);
-//fprintf(stderr, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n");
+/* fprintf(stderr, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n"); */
if (sizeof (result_video_size) != vdr_write(this->fh_result, &result_video_size, sizeof (result_video_size)))
return -1;
-//fprintf(stderr, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n");
+/* fprintf(stderr, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\n"); */
}
}
break;
@@ -1194,7 +1313,7 @@ fprintf(stderr, "--- CLEAR(%d%c)\n", data->n, data->s ? 'b' : 'a');
}
_t2 = _now();
- fprintf(stderr, "vdr: reset_audio: n: %d, %.1lf\n", _n, _t2 - _t1);
+ /* fprintf(stderr, "vdr: reset_audio: n: %d, %.1lf\n", _n, _t2 - _t1); */
xine_set_param(this->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
@@ -1459,7 +1578,7 @@ static off_t vdr_plugin_read(input_plugin_t *this_gen,
if (buf[3] == 0xbe
&& buf[4] == 0xff)
{
-//fprintf(stderr, "------- seen sync point: %02x, waiting for: %02x\n", buf[5], this->find_sync_point);
+/* fprintf(stderr, "------- seen sync point: %02x, waiting for: %02x\n", buf[5], this->find_sync_point); */
if (buf[5] == this->find_sync_point)
{
this->find_sync_point = 0;
@@ -1644,6 +1763,35 @@ static void vdr_plugin_dispose(input_plugin_t *this_gen)
pthread_cond_destroy(&this->rpc_thread_shutdown_cond);
pthread_mutex_destroy(&this->rpc_thread_shutdown_lock);
+ if (this->metronom_thread)
+ {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: joining metronom thread ...\n"), LOG_MODULE);
+
+ pthread_mutex_lock(&this->metronom_thread_call_lock);
+
+ pthread_mutex_lock(&this->metronom_thread_lock);
+ this->metronom_thread_request = -1;
+ this->metronom_thread_reply = 0;
+ pthread_cond_broadcast(&this->metronom_thread_request_cond);
+/*
+ pthread_mutex_unlock(&this->metronom_thread_lock);
+
+ pthread_mutex_lock(&this->metronom_thread_lock);
+ if (!this->metronom_thread_reply)
+*/
+ pthread_cond_wait(&this->metronom_thread_reply_cond, &this->metronom_thread_lock);
+ pthread_mutex_unlock(&this->metronom_thread_lock);
+
+ pthread_mutex_unlock(&this->metronom_thread_call_lock);
+
+ pthread_join(this->metronom_thread, 0);
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("%s: metronom thread joined.\n"), LOG_MODULE);
+ }
+
+ pthread_mutex_destroy(&this->metronom_thread_lock);
+ pthread_cond_destroy(&this->metronom_thread_request_cond);
+ pthread_cond_destroy(&this->metronom_thread_reply_cond);
+
pthread_mutex_destroy(&this->find_sync_point_lock);
pthread_mutex_destroy(&this->adjust_zoom_lock);
@@ -1678,6 +1826,10 @@ static void vdr_plugin_dispose(input_plugin_t *this_gen)
this->stream->metronom = this->metronom.stream_metronom;
this->metronom.stream_metronom = 0;
+ vdr_vpts_offset_queue_purge(this);
+ pthread_cond_destroy(&this->vpts_offset_queue_changed_cond);
+ pthread_mutex_destroy(&this->vpts_offset_queue_lock);
+
free(this);
}
@@ -1928,6 +2080,33 @@ static int vdr_plugin_open_socket_mrl(input_plugin_t *this_gen)
return 1;
}
+static void *vdr_metronom_thread_loop(void *arg)
+{
+ vdr_input_plugin_t *this = (vdr_input_plugin_t *)arg;
+ int run = 1;
+
+ pthread_mutex_lock(&this->metronom_thread_lock);
+
+ while (run)
+ {
+ if (this->metronom_thread_request == 0)
+ pthread_cond_wait(&this->metronom_thread_request_cond, &this->metronom_thread_lock);
+
+ if (this->metronom_thread_request == -1)
+ run = 0;
+ else
+ this->metronom.metronom.handle_audio_discontinuity(&this->metronom.metronom, DISC_ABSOLUTE, this->metronom_thread_request);
+
+ this->metronom_thread_request = 0;
+ this->metronom_thread_reply = 1;
+ pthread_cond_broadcast(&this->metronom_thread_reply_cond);
+ }
+
+ pthread_mutex_unlock(&this->metronom_thread_lock);
+
+ return 0;
+}
+
static int vdr_plugin_open(input_plugin_t *this_gen)
{
vdr_input_plugin_t *this = (vdr_input_plugin_t *)this_gen;
@@ -1956,13 +2135,23 @@ static int vdr_plugin_open(input_plugin_t *this_gen)
return 0;
}
+ if ((err = pthread_create(&this->metronom_thread, NULL,
+ vdr_metronom_thread_loop, (void *)this)) != 0)
+ {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ _("%s: can't create new thread (%s)\n"), LOG_MODULE,
+ strerror(err));
+
+ return 0;
+ }
+
this->rpc_thread_shutdown = 0;
/* let this thread handle rpc commands in startup phase */
this->startup_phase = 1;
if (0 == vdr_rpc_thread_loop(this))
return 0;
-
+/* fprintf(stderr, "####################################################\n"); */
if ((err = pthread_create(&this->rpc_thread, NULL,
vdr_rpc_thread_loop, (void *)this)) != 0)
{
@@ -2023,7 +2212,7 @@ static void event_handler(void *user_data, const xine_event_t *event)
event.type = XINE_EVENT_VDR_TRICKSPEEDMODE;
event.data = 0;
- event.data_length = this->trick_speed_mode;
+ event.data_length = 0; /* this->trick_speed_mode; */
xine_event_send(this->stream, &event);
}
@@ -2114,34 +2303,74 @@ static void event_handler(void *user_data, const xine_event_t *event)
}
-static void vdr_metronom_set_audio_rate(metronom_t *self, int64_t pts_per_smpls)
+static int64_t vdr_vpts_offset_queue_change_begin(vdr_input_plugin_t *this, int type)
{
- vdr_metronom_t *this = (vdr_metronom_t *)self;
- this->stream_metronom->set_audio_rate(this->stream_metronom, pts_per_smpls);
-}
+ pthread_mutex_lock(&this->vpts_offset_queue_lock);
+ this->vpts_offset_queue_changes++;
+ pthread_mutex_unlock(&this->vpts_offset_queue_lock);
-static void vdr_metronom_got_video_frame(metronom_t *self, vo_frame_t *frame)
-{
- vdr_metronom_t *this = (vdr_metronom_t *)self;
- this->stream_metronom->got_video_frame(this->stream_metronom, frame);
+ return this->metronom.metronom.get_option(&this->metronom.metronom, METRONOM_VPTS_OFFSET);
}
-static int64_t vdr_metronom_got_audio_samples(metronom_t *self, int64_t pts, int nsamples)
+static void vdr_vpts_offset_queue_change_end(vdr_input_plugin_t *this, int type, int64_t disc_off, int64_t vpts_offset)
{
- vdr_metronom_t *this = (vdr_metronom_t *)self;
- return this->stream_metronom->got_audio_samples(this->stream_metronom, pts, nsamples);
-}
+ pthread_mutex_lock(&this->vpts_offset_queue_lock);
-static int64_t vdr_metronom_got_spu_packet(metronom_t *self, int64_t pts)
-{
- vdr_metronom_t *this = (vdr_metronom_t *)self;
- return this->stream_metronom->got_spu_packet(this->stream_metronom, pts);
-}
+if(0)
+ {
+fprintf(stderr, "A ---------------------------------------------\n");
+ vdr_vpts_offset_t *p = this->vpts_offset_queue;
+ while (p)
+ {
+ fprintf(stderr, "A now: %12"PRId64", vpts: %12"PRId64", offset: %12"PRId64"\n", xine_get_current_vpts(this->stream), p->vpts, p->offset);
+ p = p->next;
+ }
+fprintf(stderr, "A =============================================\n");
+ }
+
+ if (type == DISC_ABSOLUTE)
+ {
+ int64_t vpts = this->stream->metronom->get_option(this->stream->metronom, METRONOM_VPTS_OFFSET) + disc_off;
+
+ if (!this->vpts_offset_queue
+ || this->vpts_offset_queue_tail->vpts < vpts)
+ {
+ vdr_vpts_offset_t *curr = (vdr_vpts_offset_t *)calloc(1, sizeof (vdr_vpts_offset_t));
+ curr->vpts = vpts;
+ curr->offset = vpts_offset;
+
+ if (!this->vpts_offset_queue)
+ this->vpts_offset_queue = this->vpts_offset_queue_tail = curr;
+ else
+ {
+ this->vpts_offset_queue_tail->next = curr;
+ this->vpts_offset_queue_tail = curr;
+ }
+ }
+ }
+ else
+ vdr_vpts_offset_queue_purge(this);
+
+if(0)
+ {
+fprintf(stderr, "B ---------------------------------------------\n");
+ vdr_vpts_offset_t *p = this->vpts_offset_queue;
+ while (p)
+ {
+ fprintf(stderr, "B now: %12"PRId64", vpts: %12"PRId64", offset: %12"PRId64"\n", xine_get_current_vpts(this->stream), p->vpts, p->offset);
+ p = p->next;
+ }
+fprintf(stderr, "B =============================================\n");
+ }
+
+ this->vpts_offset_queue_changes--;
+ pthread_cond_broadcast(&this->vpts_offset_queue_changed_cond);
-static void vdr_handle_discontinuity(vdr_input_plugin_t *this, int type)
-{
this->last_disc_type = type;
+ pthread_mutex_unlock(&this->vpts_offset_queue_lock);
+
+ if (!this->trick_speed_mode)
{
xine_event_t event;
@@ -2156,15 +2385,71 @@ static void vdr_handle_discontinuity(vdr_input_plugin_t *this, int type)
static void vdr_metronom_handle_audio_discontinuity(metronom_t *self, int type, int64_t disc_off)
{
vdr_metronom_t *this = (vdr_metronom_t *)self;
+ int64_t vpts_offset = vdr_vpts_offset_queue_change_begin(this->input, type);
+/* fprintf(stderr, "had A: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */
this->stream_metronom->handle_audio_discontinuity(this->stream_metronom, type, disc_off);
- vdr_handle_discontinuity(this->input, type);
+/* fprintf(stderr, "had B: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */
+ vdr_vpts_offset_queue_change_end(this->input, type, disc_off, vpts_offset);
}
static void vdr_metronom_handle_video_discontinuity(metronom_t *self, int type, int64_t disc_off)
{
vdr_metronom_t *this = (vdr_metronom_t *)self;
+ int64_t vpts_offset = vdr_vpts_offset_queue_change_begin(this->input, type);
+/* fprintf(stderr, "hvd A: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */
this->stream_metronom->handle_video_discontinuity(this->stream_metronom, type, disc_off);
- vdr_handle_discontinuity(this->input, type);
+/* fprintf(stderr, "hvd B: %d, %"PRId64", %"PRId64", %"PRId64"\n", type, disc_off, xine_get_current_vpts(this->input->stream), this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */
+ vdr_vpts_offset_queue_change_end(this->input, type, disc_off, vpts_offset);
+}
+
+static void vdr_metronom_got_video_frame(metronom_t *self, vo_frame_t *frame)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+
+ if (this->input->trick_speed_mode && frame->pts)
+ {
+ pthread_mutex_lock(&this->input->metronom_thread_call_lock);
+
+ pthread_mutex_lock(&this->input->metronom_thread_lock);
+ this->input->metronom_thread_request = frame->pts;
+ this->input->metronom_thread_reply = 0;
+ pthread_cond_broadcast(&this->input->metronom_thread_request_cond);
+ pthread_mutex_unlock(&this->input->metronom_thread_lock);
+
+ vdr_metronom_handle_video_discontinuity(self, DISC_ABSOLUTE, frame->pts);
+
+ pthread_mutex_lock(&this->input->metronom_thread_lock);
+ if (!this->input->metronom_thread_reply)
+ pthread_cond_wait(&this->input->metronom_thread_reply_cond, &this->input->metronom_thread_lock);
+ pthread_mutex_unlock(&this->input->metronom_thread_lock);
+
+ pthread_mutex_unlock(&this->input->metronom_thread_call_lock);
+ }
+
+ this->stream_metronom->got_video_frame(this->stream_metronom, frame);
+
+ if (this->input->trick_speed_mode && frame->pts)
+ {
+/* fprintf(stderr, "vpts: %12ld, pts: %12ld, offset: %12ld\n", frame->vpts, frame->pts, this->stream_metronom->get_option(this->stream_metronom, METRONOM_VPTS_OFFSET)); */
+ }
+}
+
+static int64_t vdr_metronom_got_audio_samples(metronom_t *self, int64_t pts, int nsamples)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ return this->stream_metronom->got_audio_samples(this->stream_metronom, pts, nsamples);
+}
+
+static int64_t vdr_metronom_got_spu_packet(metronom_t *self, int64_t pts)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ return this->stream_metronom->got_spu_packet(this->stream_metronom, pts);
+}
+
+static void vdr_metronom_set_audio_rate(metronom_t *self, int64_t pts_per_smpls)
+{
+ vdr_metronom_t *this = (vdr_metronom_t *)self;
+ this->stream_metronom->set_audio_rate(this->stream_metronom, pts_per_smpls);
}
static void vdr_metronom_set_option(metronom_t *self, int option, int64_t value)
@@ -2269,8 +2554,13 @@ static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_strea
this->event_queue_external = 0;
pthread_mutex_init(&this->rpc_thread_shutdown_lock, 0);
- pthread_cond_init(&this->rpc_thread_shutdown_cond, 0);
-
+ pthread_cond_init(&this->rpc_thread_shutdown_cond, 0);
+
+ pthread_mutex_init(&this->metronom_thread_lock, 0);
+ pthread_cond_init(&this->metronom_thread_request_cond, 0);
+ pthread_cond_init(&this->metronom_thread_reply_cond, 0);
+ pthread_mutex_init(&this->metronom_thread_call_lock, 0);
+
pthread_mutex_init(&this->find_sync_point_lock, 0);
pthread_mutex_init(&this->adjust_zoom_lock, 0);
this->image4_3_zoom_x = 0;
@@ -2297,6 +2587,9 @@ static input_plugin_t *vdr_class_get_instance(input_class_t *cls_gen, xine_strea
this->metronom.stream_metronom = stream->metronom;
stream->metronom = &this->metronom.metronom;
+ pthread_mutex_init(&this->vpts_offset_queue_lock, 0);
+ pthread_cond_init(&this->vpts_offset_queue_changed_cond, 0);
+
return &this->input_plugin;
}