summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xine_input_vdr.c606
1 files changed, 279 insertions, 327 deletions
diff --git a/xine_input_vdr.c b/xine_input_vdr.c
index 2258d198..8e6a861f 100644
--- a/xine_input_vdr.c
+++ b/xine_input_vdr.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: xine_input_vdr.c,v 1.13 2006-07-06 02:57:59 phintuka Exp $
+ * $Id: xine_input_vdr.c,v 1.14 2006-07-07 14:09:05 phintuka Exp $
*
*/
@@ -55,12 +55,12 @@
/*#define LOG_TRACE*/
#define ADJUST_SCR_SPEED 1
-#define INITIAL_READ_DELAY (16*(40*1000)) /* us. 16 frames, 40ms / frame */
#define METRONOM_PREBUFFER_VAL (4 * 90000 / 25 )
#define HD_BUF_NUM_BUFS (2048) /* 2k payload * 2048 = 4Mb , ~ 1 second */
#define HD_BUF_ELEM_SIZE (2048+64)
+#define RADIO_MAX_BUFFERS 10
/******************************* LOG ***********************************/
@@ -204,6 +204,9 @@ typedef struct vdr_input_plugin_s {
int B_frames;
int P_frames;
+ int64_t pause_start;
+ int paused_frames;
+
/* Network */
pthread_t control_thread;
pthread_t data_thread;
@@ -222,6 +225,8 @@ typedef struct vdr_input_plugin_s {
fifo_buffer_t *buffer_pool; /* stream's video fifo */
fifo_buffer_t *big_buffer; /* for jumbo PES */
fifo_buffer_t *hd_buffer; /* more buffer for HD streams */
+ fifo_buffer_t *iframe_buffer; /* buffer for cached I-frame */
+ int saving_iframe;
uint64_t discard_index; /* index of next byte to feed to demux;
all data before this offset will
be discarded */
@@ -231,7 +236,6 @@ typedef struct vdr_input_plugin_s {
uint64_t curpos; /* current position (demux side) */
int curframe;
int max_buffers; /* max no. of non-demuxed buffers */
- int read_delay; /* usec to wait at next read call */
/* saved video properties */
int video_properties_saved;
@@ -560,6 +564,24 @@ static inline const char *scr_tunning_str(int value)
}
#endif
+static int64_t monotonic_time_ms (void)
+{
+ static struct timeval tv_0;
+ static int init_done = 0;
+ struct timeval tv;
+ int64_t ms;
+
+ if(!init_done) {
+ init_done = 1;
+ xine_monotonic_clock(&tv_0, NULL);
+ }
+ xine_monotonic_clock(&tv, NULL);
+
+ ms = 1000LL * (tv.tv_sec - tv_0.tv_sec);
+ ms += tv.tv_usec / 1000;
+ return ms;
+}
+
static void scr_tunning_set_paused(vdr_input_plugin_t *this)
{
if(this->scr_tunning != SCR_TUNNING_PAUSED) {
@@ -569,8 +591,14 @@ static void scr_tunning_set_paused(vdr_input_plugin_t *this)
this->speed_before_pause = _x_get_fine_speed(this->stream);
+#if 0
if(_x_get_fine_speed(this->stream) != XINE_SPEED_PAUSE)
_x_set_fine_speed(this->stream, XINE_SPEED_PAUSE);
+#else
+ _x_set_fine_speed(this->stream, 1000000 / 1000); //-> speed to 0.1%
+#endif
+ this->pause_start = monotonic_time_ms();
+ this->paused_frames = 0;
}
}
@@ -585,29 +613,11 @@ static void reset_scr_tunning(vdr_input_plugin_t *this, int new_speed)
if(_x_get_fine_speed(this->stream) != new_speed) {
_x_set_fine_speed(this->stream, XINE_FINE_SPEED_NORMAL);
}
-pvrscr_set_fine_speed((scr_plugin_t*)this->scr, XINE_FINE_SPEED_NORMAL);
+ pvrscr_set_fine_speed((scr_plugin_t*)this->scr, XINE_FINE_SPEED_NORMAL);
}
}
}
-static int64_t monotonic_time_ms (void)
-{
- static struct timeval tv_0;
- static int init_done = 0;
- struct timeval tv;
- int64_t ms;
-
- if(!init_done) {
- init_done = 1;
- xine_monotonic_clock(&tv_0, NULL);
- }
- xine_monotonic_clock(&tv, NULL);
-
- ms = 1000LL * (tv.tv_sec - tv_0.tv_sec);
- ms += tv.tv_usec / 1000;
- return ms;
-}
-
static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this)
{
/* Grab current buffer usage */
@@ -615,9 +625,6 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this)
this->block_buffer->size(this->block_buffer);
int num_free = this->buffer_pool->num_free(this->buffer_pool);
int scr_tunning = this->scr_tunning;
-
- static int64_t pause_start = -1LL; /* TODO: -> this... */
- static int pause_bufs = -1;
if(this->stream->audio_fifo)
num_used += this->stream->audio_fifo->size(this->stream->audio_fifo);
@@ -629,11 +636,10 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this)
if(!((fcnt++)%2500) ||
(this->scr_tunning==SCR_TUNNING_PAUSED && !(fcnt%10)) ||
(this->no_video && !(fcnt%50))) {
- LOGSCR("Buffer %2d%% (%3d/%3d) %s %s",
+ LOGSCR("Buffer %2d%% (%3d/%3d) %s",
100*num_used/(num_used+num_free),
num_used, num_used+num_free,
- scr_tunning_str(this->scr_tunning),
- this->live_mode?"LIVE":"PLAY");
+ scr_tunning_str(this->scr_tunning));
}
}
@@ -650,9 +656,9 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this)
/* If buffer is (almost) empty. pause it for a while */
if( num_used < 1 &&
scr_tunning != SCR_TUNNING_PAUSED &&
- this->live_mode && !this->no_video && !this->still_mode) {
+ !this->no_video && !this->still_mode) {
/*
- TODO:
+ #warning TODO:
- First I-frame can be delivered as soon as it is decoded
-> illusion of faster channel switches
- Clock must still be paused, but stream can be in PLAYING state
@@ -662,8 +668,6 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this)
int num_vbufs = this->stream->video_out->get_property(this->stream->video_out,
VO_PROP_BUFS_IN_FIFO);
if(num_vbufs < 3) {
- pause_start = monotonic_time_ms();
- pause_bufs = 0;
LOGSCR("SCR paused by adjust_speed (vbufs=%d)", num_vbufs);
scr_tunning_set_paused(this);
} else {
@@ -672,54 +676,50 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this)
/* If currently paused, revert to normal if buffer > 50% */
} else if( scr_tunning == SCR_TUNNING_PAUSED) {
-
- if(pause_bufs < 0) {
- pause_start = monotonic_time_ms();
- pause_bufs = 0;
- }
- pause_bufs++;
-
- int num_vbufs = this->stream->video_out->get_property(this->stream->video_out,
- VO_PROP_BUFS_IN_FIFO);
-
- if( num_used/2 > num_free || (this->no_video && num_used>5) || !this->live_mode
/*
- TODO:
+ #warning TODO:
- Using amount of buffers is not good trigger as it depends on channel bitrate
- Wait time is not not good trigger as it depends on tuner lock time
-> maybe keep track of PTSes or wait until decoder has complete IBBBP frame sequence ?
- First I-frame can be delivered as soon as it is decoded
-> illusion of faster channel switches
*/
- || pause_bufs > 200
- || (pause_bufs>100 && pause_start + 400 < monotonic_time_ms())
+ int num_vbufs = this->stream->video_out->get_property(this->stream->video_out,
+ VO_PROP_BUFS_IN_FIFO);
+ this->paused_frames++;
+
+ if( num_used/2 > num_free
+ || (this->no_video && num_used > 5)
+ || this->paused_frames > 200
+ || (this->paused_frames > 100
+ && this->pause_start + 400 < monotonic_time_ms())
|| num_vbufs > 5
|| this->still_mode
) {
LOGSCR("SCR tunning resetted by adjust_speed, "
"vbufs=%d (SCR was paused for %d bufs/%d ms)",
- num_vbufs, pause_bufs, monotonic_time_ms()-pause_start);
+ num_vbufs, this->paused_frames,
+ monotonic_time_ms() - this->pause_start);
- pause_bufs = -1;
- pause_start = -1LL;
+ this->paused_frames = 0;
+ this->pause_start = 0;
reset_scr_tunning(this, this->speed_before_pause);
}
/* when playing realtime, adjust the scr to make xine buffers half full */
- } else if( _x_get_fine_speed(this->stream) == XINE_FINE_SPEED_NORMAL &&
- this->live_mode ) {
+ } else if( _x_get_fine_speed(this->stream) == XINE_FINE_SPEED_NORMAL) {
if(this->no_video) { /* radio stream ? */
- if( num_used > 10 )
+ if( num_used >= (RADIO_MAX_BUFFERS-1))
scr_tunning = +1; /* play faster */
- else if( num_used < 5 )
+ else if( num_used <= (RADIO_MAX_BUFFERS/3))
scr_tunning = -1; /* play slower */
else
scr_tunning = SCR_TUNNING_OFF;
} else {
if( num_used > 4*num_free )
- scr_tunning = +1; /* play .5% faster */
+ scr_tunning = +2; /* play 1% faster */
else if( num_used > 2*num_free )
scr_tunning = +1; /* play .5% faster */
else if( num_free > 4*num_used ) /* <20% */
@@ -793,17 +793,8 @@ static int64_t pts_from_pes(const uint8_t *buf, int size)
static void clear_pts_from_pes(uint8_t *buf, int size)
{
if(size>14 && buf[7] & 0x80) { /* pts avail */
-#if 0
-#warning setting to 0 instead of removing
- buf[ 9] &= ~0x0E;
- buf[10] = 0;
- buf[11] &= ~0xFE;
- buf[12] = 0;
- buf[13] &= ~0xFE;
-#else
buf[7] &= 0x7f; /* clear pts avail */
memcpy(buf+9, buf+14, size-14);
-#endif
}
}
@@ -1019,7 +1010,6 @@ static void queue_nosignal(vdr_input_plugin_t *this)
buf->type = BUF_VIDEO_MPEG;
xine_fast_memcpy(buf->content, &v_mpg_nosignal[pos], buf->size);
pos += buf->size;
- LOGMSG("p");
this->stream->video_fifo->put(this->stream->video_fifo, buf);
}
}
@@ -1224,6 +1214,7 @@ static void strip_network_headers(vdr_input_plugin_t *this, buf_element_t *buf)
buf->content += sizeof(stream_tcp_header_t);
buf->size -= sizeof(stream_tcp_header_t);
}
+ buf->type = BUF_DEMUX_BLOCK;
}
}
@@ -1970,22 +1961,6 @@ static void vdr_flush_engine(vdr_input_plugin_t *this)
reset_scr_tunning(this, this->speed_before_pause);
-#if 0
-/* net mode: may already have important data received as data and control are not synchronized.
- So, do discard in read_block.
- Another possibility is to flush up to discard_index.
-
- * buffer size can't be added to curpos (network headers ; possible missing packets).
- * local mode: size must be added if flushed ...
-*/
- this->curpos += (uint64_t)fifo_buffer_clear(this->block_buffer);
- if(this->curr_buffer) { /* safe, but only now, as we know demuxer can't be in middle of PES frame now */
- this->curpos += (uint64_t)this->curr_buffer->size;
- this->curr_buffer->free_buffer(this->curr_buffer);
- this->curr_buffer = NULL;
- }
-#endif
-
vdr_x_demux_flush_engine (this->stream, this);
#if 0
@@ -2069,41 +2044,42 @@ static int set_video_properties(vdr_input_plugin_t *this,
static int set_live_mode(vdr_input_plugin_t *this, int onoff)
{
pthread_mutex_lock(&this->lock);
+
if(this->live_mode != onoff) {
config_values_t *config = this->stream->xine->config;
this->live_mode = onoff;
- if(!this->live_mode) {
+
+ this->stream->metronom->set_option(this->stream->metronom,
+ METRONOM_PREBUFFER, METRONOM_PREBUFFER_VAL);
+
+ if(!this->live_mode || this->fd_control > 0) {
config->update_num(this->stream->xine->config,
- "audio.synchronization.av_sync_method",0);
- this->max_buffers = (this->buffer_pool->buffer_pool_capacity >> 1) - 10;
- if(this->scr_tunning != SCR_TUNNING_OFF) {
- LOGSCR("reset scr tunning by set_live_mode");
- reset_scr_tunning(this, this->speed_before_pause=XINE_FINE_SPEED_NORMAL);
- }
+ "audio.synchronization.av_sync_method", 1);
} else {
config->update_num(this->stream->xine->config,
- "audio.synchronization.av_sync_method",1);
-#ifdef INITIAL_READ_DELAY
- this->read_delay = INITIAL_READ_DELAY;
-#endif
- this->max_buffers = this->buffer_pool->buffer_pool_capacity - 10;
- this->stream->metronom->set_option(this->stream->metronom,
- METRONOM_PREBUFFER, METRONOM_PREBUFFER_VAL);
- if(this->scr_tunning != SCR_TUNNING_PAUSED) {
- LOGSCR("pause scr tunning by set_live_mode");
- scr_tunning_set_paused(this);
- }
+ "audio.synchronization.av_sync_method", 0);
}
}
-#if 1
- if(this->live_mode) {
- if(this->scr_tunning != SCR_TUNNING_PAUSED) {
- LOGSCR("pause scr tunning by set_live_mode");
- scr_tunning_set_paused(this);
- }
+ /* set buffer usage limits */
+ this->max_buffers = this->buffer_pool->buffer_pool_capacity;
+ if(this->live_mode && this->fd_control < 0)
+ this->max_buffers >>= 1;
+ this->max_buffers -= 10;
+
+ if(this->no_video)
+ this->max_buffers = RADIO_MAX_BUFFERS;
+
+ /* SCR tunning */
+ if(this->live_mode) {
+ LOGSCR("pause scr tunning by set_live_mode");
+ scr_tunning_set_paused(this);
+ } else {
+ LOGSCR("reset scr tunning by set_live_mode");
+ reset_scr_tunning(this, this->speed_before_pause=XINE_FINE_SPEED_NORMAL);
}
-#endif
+
+ this->still_mode = 0;
pthread_mutex_unlock(&this->lock);
@@ -2379,21 +2355,20 @@ static int handle_control_osdcmd(vdr_input_plugin_t *this)
static int vdr_plugin_poll(vdr_input_plugin_t *this, int timeout_ms)
{
- static int timeouts = 0;
struct timespec abstime;
int result = 0;
/* Caller must have locked this->vdr_entry_lock ! */
if(this->slave_stream) {
- LOGDBG("vdr_plugin_poll: called while playing slave stream !");
+ LOGMSG("vdr_plugin_poll: called while playing slave stream !");
return 1;
}
TRACE("vdr_plugin_poll (%d ms), buffer_pool: blocks=%d, bytes=%d",
timeout_ms, this->buffer_pool->size(this->buffer_pool),
this->buffer_pool->data_size(this->buffer_pool));
-
+#if 0
if(this->is_paused) {
VDR_ENTRY_UNLOCK();
@@ -2408,7 +2383,7 @@ static int vdr_plugin_poll(vdr_input_plugin_t *this, int timeout_ms)
VDR_ENTRY_LOCK(0);
}
-
+#endif
pthread_mutex_lock (&this->buffer_pool->buffer_pool_mutex);
result = this->buffer_pool->buffer_pool_num_free -
(this->buffer_pool->buffer_pool_capacity - this->max_buffers);
@@ -2430,23 +2405,10 @@ static int vdr_plugin_poll(vdr_input_plugin_t *this, int timeout_ms)
pthread_mutex_lock (&this->buffer_pool->buffer_pool_mutex);
while(result <= 5) {
- TRACE("vdr_plugin_poll waiting (max %d ms), "
- "%d bufs free (rd pos=%" PRIu64 ")",
- timeout_ms, this->buffer_pool->buffer_pool_num_free, this->curpos);
if(pthread_cond_timedwait (&this->buffer_pool->buffer_pool_cond_not_empty,
&this->buffer_pool->buffer_pool_mutex,
- &abstime) == ETIMEDOUT) {
-
- if(this->live_mode) {
- if(timeouts>2 && timeouts<6) {
- timeout_ms=200;
- create_timeout_time(&abstime, timeout_ms);
- continue;
- }
- }
-
- break;
- }
+ &abstime) == ETIMEDOUT)
+ break;
result = this->buffer_pool->buffer_pool_num_free -
(this->buffer_pool->buffer_pool_capacity - this->max_buffers);
}
@@ -2465,8 +2427,6 @@ static int vdr_plugin_poll(vdr_input_plugin_t *this, int timeout_ms)
result = 0;
pthread_yield();
xine_usec_sleep(3*1000);
- } else {
- timeouts = 0;
}
return result;
@@ -2494,7 +2454,8 @@ static int vdr_plugin_flush(vdr_input_plugin_t *this, int timeout_ms)
this->stream->video_out->get_property(this->stream->video_out,
VO_PROP_BUFS_IN_FIFO));
- if(this->live_mode && this->fd_control < 0) {
+ if(this->live_mode /*&& this->fd_control < 0*/) {
+ /* No flush in live mode */
sched_yield();
return 1;
}
@@ -2539,45 +2500,42 @@ static int vdr_plugin_flush(vdr_input_plugin_t *this, int timeout_ms)
static int vdr_plugin_flush_remote(vdr_input_plugin_t *this, int timeout_ms,
uint64_t offset, int frame)
{
- int r;
+ int r, live_mode;
pthread_mutex_lock(&this->lock);
+
+ live_mode = this->live_mode;
this->live_mode = 0; /* --> 1 again when data arrives ... */
- if(this->scr_tunning) {
- /*LOGMSG("reset scr tunning by flush");*/
- reset_scr_tunning(this, this->speed_before_pause);
- }
- pthread_mutex_unlock(&this->lock);
+ LOGSCR("reset scr tunning by flush_remote");
+ reset_scr_tunning(this, this->speed_before_pause);
+
+ /* wait until all data has been received */
while(this->curpos < offset && timeout_ms > 0) {
TRACE("FLUSH: wait position (%" PRIu64 " ; need %" PRIu64 ")",
this->curpos, offset);
+ pthread_mutex_unlock(&this->lock);
xine_usec_sleep(3*1000);
+ pthread_mutex_lock(&this->lock);
timeout_ms -= 3;
}
- pthread_mutex_lock(&this->lock);
- this->live_mode = 0;
- if(this->scr_tunning) {
- /*LOGMSG("reset scr tunning by flush");*/
- reset_scr_tunning(this, this->speed_before_pause);
- }
+ LOGSCR("reset scr tunning by flush_remote");
+ reset_scr_tunning(this, this->speed_before_pause);
+
pthread_mutex_unlock(&this->lock);
r = vdr_plugin_flush(this, MAX(5, timeout_ms));
printf_control(this, "RESULT %d %d\r\n", this->token, r);
- /*xine_usec_sleep(20*1000);*/
-
- this->live_mode = 1;
+ pthread_mutex_lock(&this->lock);
+ this->live_mode = live_mode;
this->stream->metronom->set_option(this->stream->metronom,
METRONOM_PREBUFFER,
METRONOM_PREBUFFER_VAL);
- pthread_mutex_lock(&this->lock);
- /*#warning no pause*/
- /* scr_tunning_set_paused(this);*/
this->guard_index = offset;
+
pthread_mutex_unlock(&this->lock);
return CONTROL_OK;
@@ -2635,10 +2593,11 @@ static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd)
pthread_mutex_lock(&this->lock);
this->no_video = tmp32;
if(this->no_video) {
- this->max_buffers = 6;
+ this->max_buffers = RADIO_MAX_BUFFERS;
} else {
this->max_buffers = this->buffer_pool->buffer_pool_capacity;
- if(!this->live_mode) this->max_buffers >>= 1;
+ if(!this->live_mode && this->fd_control < 0)
+ this->max_buffers >>= 1;
this->max_buffers -= 10;
}
pthread_mutex_unlock(&this->lock);
@@ -2676,33 +2635,21 @@ static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd)
} else if(!strncasecmp(cmd, "STILL ", 6)) {
pthread_mutex_lock(&this->lock);
- if(this->fd_control >= 0) {
- /*set_live_mode(this, 1);*/
- if(cmd[6] == '0')
- this->still_mode = 0;
- if(cmd[6] == '1') {
- this->still_mode = 1;
- reset_scr_tunning(this, this->speed_before_pause);
- }
- this->stream_start = 1;
- }
+ /*if(this->fd_control >= 0) {*/
+ if(1 == sscanf(cmd, "STILL %d", &tmp32)) {
+ this->still_mode = tmp32;
+ if(this->still_mode)
+ reset_scr_tunning(this, this->speed_before_pause);
+ this->stream_start = 1;
+ } else
+ err = CONTROL_PARAM_ERROR;
+ /*}*/
pthread_mutex_unlock(&this->lock);
-
+
} else if(!strncasecmp(cmd, "LIVE ", 5)) {
- if(this->fd_control >= 0) {
- set_live_mode(this, 1);
- pthread_mutex_lock(&this->lock);
this->still_mode = 0;
- if(cmd[5] == '0') {
- LOGSCR("reset scr tunning by LIVE 0");
- reset_scr_tunning(this, this->speed_before_pause);
- } else {
- /* */
- }
- pthread_mutex_unlock(&this->lock);
- } else
- err = (1 == sscanf(cmd, "LIVE %d", &tmp32)) ?
- set_live_mode(this, tmp32) : -2 ;
+ err = (1 == sscanf(cmd, "LIVE %d", &tmp32)) ?
+ set_live_mode(this, tmp32) : -2 ;
} else if(!strncasecmp(cmd, "VOLUME ", 7)) {
if(1 == sscanf(cmd, "VOLUME %d", &tmp32)) {
@@ -3092,6 +3039,7 @@ static void vdr_event_cb (void *user_data, const xine_event_t *event)
event.data_length = 0;
event.type = XINE_EVENT_UI_PLAYBACK_FINISHED;
xine_event_send (this->stream, &event);
+LOGMSG("No loop play, playback of slave stream finished");
} else {
#if 0
xine_usec_sleep(500*1000);
@@ -3175,25 +3123,27 @@ static int vdr_plugin_read_net_tcp(vdr_input_plugin_t *this)
if(hdr->pos == (uint64_t)(-1ULL) /*0xffffffff*/) {
/* control data */
char *pkt_data = read_buffer->content + sizeof(stream_tcp_header_t);
- pkt_data[64] = 0;
-LOGMSG("CTRL: %s", (char*)pkt_data);
- //if(!strncmp((char*)pkt_data, "????", 11)) {
- //}
- todo = sizeof(stream_tcp_header_t);
- cnt = 0;
-
- } else {
-
- /* frame ready */
- read_buffer->size = cnt;
- read_buffer->type = BUF_MAJOR_MASK;
- this->block_buffer->put(this->block_buffer, read_buffer);
- read_buffer = NULL;
+ if(pkt_data[0]) { /* -> can't be pes frame */
+ pkt_data[64] = 0;
+ LOGMSG("Control message in data stream: %s", (char*)pkt_data);
+ vdr_plugin_parse_control((input_plugin_t*)this, (char*)pkt_data);
+
+ /* read next block */
+ todo = sizeof(stream_tcp_header_t);
+ cnt = 0;
+ continue;
+ }
}
+
+ /* frame ready */
+ read_buffer->size = cnt;
+ read_buffer->type = BUF_MAJOR_MASK;
+ this->block_buffer->put(this->block_buffer, read_buffer);
+ read_buffer = NULL;
}
}
- if(read_buffer) {
+ if(read_buffer) {
read_buffer->free_buffer(read_buffer);
if(cnt && this->fd_data >= 0 && result == XIO_TIMEOUT) {
LOGMSG("TCP: Delay too long, disconnecting");
@@ -3248,7 +3198,9 @@ static int vdr_plugin_read_net_udp(vdr_input_plugin_t *this)
LOGDBG("UDP Fifo buffer full !");
if(this->scr && !udp->scr_jump_done) {
pvrscr_skip_frame (this->scr);
- LOGMSG("SCR jump: +40 ms");
+ LOGMSG("SCR jump: +40 ms (live=%d, tunning=%d) time %ds",
+ this->live_mode, this->scr_tunning,
+ (int)(monotonic_time_ms()/1000));
udp->scr_jump_done = 50;
xine_usec_sleep(5*1000);
}
@@ -3316,23 +3268,27 @@ static int vdr_plugin_read_net_udp(vdr_input_plugin_t *this)
/* Check for control messages */
if(pkt->seq == (uint16_t)(-1) /*0xffff*/) {
if(pkt->pos == (uint64_t)(-1ULL) /*0xffffffff*/) {
- pkt_data[64] = 0;
-LOGMSG("CTRL: %s", (char*)pkt_data);
- if(!strncmp((char*)pkt_data, "UDP MISSING", 11)) {
- /* Re-send failed */
- int seq1 = 0, seq2 = 0;
- uint64_t rpos = 0ULL;
- sscanf((char*)pkt_data, "UDP MISSING %d-%d %" PRIu64,
- &seq1, &seq2, &rpos);
- read_buffer->size = sizeof(stream_udp_header_t);
- read_buffer->type = BUF_MAJOR_MASK;
- pkt->seq = seq1;
- pkt->pos = rpos;
- udp->missed_frames++;
- /* -> drop frame thru as empty ; it will trigger queue to continue */
- }
+ if(pkt_data[0]) { /* -> can't be PES frame */
+ pkt_data[64] = 0;
+ LOGMSG("Control message in data stream: %s", (char*)pkt_data);
+ if(!strncmp((char*)pkt_data, "UDP MISSING", 11)) {
+ /* Re-send failed */
+ int seq1 = 0, seq2 = 0;
+ uint64_t rpos = 0ULL;
+ sscanf((char*)pkt_data, "UDP MISSING %d-%d %" PRIu64,
+ &seq1, &seq2, &rpos);
+ read_buffer->size = sizeof(stream_udp_header_t);
+ read_buffer->type = BUF_MAJOR_MASK;
+ pkt->seq = seq1;
+ pkt->pos = rpos;
+ udp->missed_frames++;
+ /* -> drop frame thru as empty ; it will trigger queue to continue */
+ } else {
+ vdr_plugin_parse_control((input_plugin_t*)this, (char*)pkt_data);
+ }
+ continue;
+ } /* if(pkt_data[0] */
}
- continue;
}
/* Check if header is valid */
@@ -3501,6 +3457,50 @@ static void *vdr_data_thread(void *this_gen)
pthread_exit(NULL);
}
+static int write_slave_stream(vdr_input_plugin_t *this, const char *data, int len)
+{
+#if 0
+ fifo_input_plugin_t *slave;
+ buf_element_t *buf;
+
+ TRACE("write_slave_stream (%d bytes)", len);
+
+ if(!this->pip_stream) {
+ LOGMSG("Detected new video stream");
+ LOGMSG(" no xine stream yet, trying to create ...");
+ vdr_plugin_parse_control(this_gen, "SUBSTREAM 0xE1 50 50 288 196");
+ }
+ if(!this->pip_stream) {
+ LOGMSG(" pip substream: no stream !");
+ return -1;
+ }
+ LOGMSG(" pip substream open, queuing data");
+
+ slave = (fifo_input_plugin_t*)this->pip_stream->input_plugin;
+ if(!slave) {
+ LOGMSG(" pip substream: no input plugin !");
+ return len;
+ }
+
+ buf_element_t *buf = slave->buffer_pool->buffer_pool_try_alloc(slave->buffer_pool);
+ if(!buf) {
+ LOGMSG(" pip substream: fifo full !");
+ return 0;
+ }
+ if(len > buf->max_size) {
+ LOGMSG(" pip substream: buf too small");
+ buf->free_buffer(buf);
+ return len;
+ }
+
+ buf->content = buf->mem;
+ buf->size = len;
+ buf->type = BUF_DEMUX_BLOCK;
+ xine_fast_memcpy(buf->content, data, len);
+ slave->buffer->put(slave->buffer, buf);
+#endif
+ return len;
+}
static int vdr_plugin_write(input_plugin_t *this_gen, const char *data, int len)
{
@@ -3510,43 +3510,9 @@ static int vdr_plugin_write(input_plugin_t *this_gen, const char *data, int len)
if(this->slave_stream)
return len;
-#if 0
/* slave */
- if(((uint8_t*)data)[3] > 0xe0 && ((uint8_t*)data)[3] <= 0xef) {
- if(!this->pip_stream) {
- LOGMSG("Detected new video stream");
- LOGMSG(" no xine stream yet, trying to create ...");
- vdr_plugin_parse_control(this_gen, "SUBSTREAM 0xE1 50 50 288 196");
- LOGMSG(" substream up and running ?");
- }
- if(this->pip_stream) {
- fifo_input_plugin_t *slave = (fifo_input_plugin_t*)this->pip_stream->input_plugin;
- /* LOGMSG(" input already open, queuing data"); */
- if(slave) {
- buf = slave->buffer_pool->buffer_pool_try_alloc(slave->buffer_pool);
- if(buf) {
- if(len < buf->max_size) {
- /* buf->free_buffer = buffer_pool_free; */
- buf->content = buf->mem;
- buf->size = len;
- buf->type = BUF_DEMUX_BLOCK;
- xine_fast_memcpy(buf->content, data, len);
- slave->buffer->put(slave->buffer, buf);
- } else {
-LOGMSG(" pip substream: buf too small");
- buf->free_buffer(buf);
- }
- } else {
-LOGMSG(" pip substream: fifo full !");
- }
- return len;
- }
- } else {
-LOGMSG(" pip substream: no stream !");
- }
- return len;
- }
-#endif
+ if(((uint8_t*)data)[3] > 0xe0 && ((uint8_t*)data)[3] <= 0xef)
+ return write_slave_stream(this, data, len);
TRACE("vdr_plugin_write (%d bytes)", len);
@@ -3613,7 +3579,7 @@ static void track_audio_stream_change(vdr_input_plugin_t *this, buf_element_t *b
if(buf->content[3] >= 0xc0 && buf->content[3] < 0xe0) {
/* audio */
if(this->prev_audio_stream_id != (buf->content[3] << 8)) {
- LOGMSG("Audio changed -> %d (%02X)", buf->content[3] - 0xc0, buf->content[3]);
+ LOGDBG("Audio changed -> %d (%02X)", buf->content[3] - 0xc0, buf->content[3]);
this->prev_audio_stream_id = buf->content[3] << 8;
audio_changed = 1;
}
@@ -3625,20 +3591,20 @@ static void track_audio_stream_change(vdr_input_plugin_t *this, buf_element_t *b
int SubStreamType = SubStreamId & 0xF0;
int SubStreamIndex = SubStreamId & 0x1F;
switch (SubStreamType) {
- case 0x20: // SPU
- case 0x30: // SPU
- LOGMSG("SPU %d", SubStreamId);
+ case 0x20: /* SPU */
+ case 0x30: /* SPU */
+ /*LOGMSG("SPU %d", SubStreamId);*/
break;
- case 0x80: // AC3 & DTS
+ case 0x80: /* AC3 & DTS */
if(this->prev_audio_stream_id != ((0xbd<<8) | SubStreamId)) {
- LOGMSG("Audio changed -> AC3 %d (BD:%02X)", SubStreamIndex, SubStreamId);
+ LOGDBG("Audio changed -> AC3 %d (BD:%02X)", SubStreamIndex, SubStreamId);
this->prev_audio_stream_id = ((0xbd<<8) | SubStreamId);
audio_changed = 1;
}
break;
- case 0xA0: // LPCM
+ case 0xA0: /* LPCM */
if(this->prev_audio_stream_id != ((0xbd<<8) | SubStreamId)) {
- LOGMSG("Audio changed -> LPCM %d (BD:%02X)", SubStreamIndex, SubStreamId);
+ LOGDBG("Audio changed -> LPCM %d (BD:%02X)", SubStreamIndex, SubStreamId);
this->prev_audio_stream_id = ((0xbd<<8) | SubStreamId);
audio_changed = 1;
}
@@ -3655,7 +3621,7 @@ static void track_audio_stream_change(vdr_input_plugin_t *this, buf_element_t *b
if(audio_changed && !first_audio) {
buf_element_t *buf_elem =
this->stream->audio_fifo->buffer_pool_try_alloc (this->stream->audio_fifo);
-#if 1
+#if 0
LOGMSG("VDR-Given stream: %04x", this->audio_stream_id);
if(this->reset_audio_cnt < 1)
LOGMSG("audio changed, reset cnt still < 1");
@@ -3670,11 +3636,6 @@ static void track_audio_stream_change(vdr_input_plugin_t *this, buf_element_t *b
}
}
-static int get_video_frame_type(vdr_input_plugin_t *this, buf_element_t *buf)
-{
- return -1;
-}
-
static off_t vdr_plugin_read (input_plugin_t *this_gen,
char *buf, off_t len)
{
@@ -3738,12 +3699,17 @@ static buf_element_t *vdr_plugin_read_block (input_plugin_t *this_gen,
return NULL; /* disconnected ? */
}
+#ifdef CACHE_FIRST_IFRAME
+ if(NULL != (buf = get_cached_iframe(this)))
+ return buf;
+#endif
+
#ifdef ADJUST_SCR_SPEED
if(pthread_mutex_lock(&this->lock)) {
LOGERR("read_block: pthread_mutex_lock failed");
return NULL;
}
- if( !this->live_mode ) {
+ if( !this->live_mode && this->fd_control < 0) {
if(this->scr_tunning)
reset_scr_tunning(this, this->speed_before_pause);
} else {
@@ -3753,89 +3719,67 @@ static buf_element_t *vdr_plugin_read_block (input_plugin_t *this_gen,
#endif
do {
- int loops=0;
- pthread_mutex_lock(&this->block_buffer->mutex);
- if(this->block_buffer->fifo_size <= 0) {
- struct timespec abstime;
- create_timeout_time(&abstime, 250); /* no infinite waits if player is stopped and fifo full ... */
- while(this->block_buffer->fifo_size <= 0) {
- if(loops>0)
- TRACE("vdr_plugin_read_block - wait ... %d",loops);
- if(pthread_cond_timedwait (&this->block_buffer->not_empty,
- &this->block_buffer->mutex, &abstime)
- == ETIMEDOUT) {
- loops++;
- create_timeout_time(&abstime, 250);
-
- }
- if(loops>1)
- TRACE("vdr_plugin_read_block - wait end %d",loops);
-
- if((loops>1 && this->block_buffer->fifo_size <= 0) ||
- this->stream->demux_action_pending) {
- pthread_mutex_unlock(&this->block_buffer->mutex);
- if(NULL != (buf = make_padding_frame(this)))
- return buf;
- /* no free buffers ... */
- pthread_mutex_lock(&this->block_buffer->mutex);
- }
- } /* while(this->block_buffer->fifo_size <= 0) */
- } /* if(this->block_buffer->fifo_size <= 0) */
- pthread_mutex_unlock(&this->block_buffer->mutex);
-
- if(!(buf = fifo_buffer_try_get(this->block_buffer)))
+ buf = fifo_buffer_try_get(this->block_buffer);
+ if(!buf) {
+ struct timespec abstime;
+ create_timeout_time(&abstime, 500);
+ pthread_mutex_lock(&this->block_buffer->mutex);
+ if(this->block_buffer->fifo_size <= 0)
+ pthread_cond_timedwait (&this->block_buffer->not_empty,
+ &this->block_buffer->mutex, &abstime);
+ pthread_mutex_unlock(&this->block_buffer->mutex);
+ if(this->block_buffer->fifo_size <= 0)
+ if(NULL != (buf = make_padding_frame(this)))
+ return buf;
continue;
- loops=0;
+ }
+
+ /* control buffers go always to demuxer */
+ if ((buf->type & BUF_MAJOR_MASK) == BUF_CONTROL_BASE)
+ return buf;
pthread_mutex_lock(&this->lock);
+ /* Update stream position and remove network headers */
strip_network_headers(this, buf);
- /* control buffers go always to demuxer */
- if ((buf->type & BUF_MAJOR_MASK) == BUF_CONTROL_BASE) {
- pthread_mutex_unlock(&this->lock);
- return buf;
- }
-
+ /* Update stream position */
this->curpos += buf->size;
+
+ /* Handle discard */
if(this->discard_index > this->curpos && this->guard_index < this->curpos) {
pthread_mutex_unlock(&this->lock);
- TRACE("DISCARD: curpos=%" PRIu64 ", discard_index=%" PRIu64,
- this->curpos, this->discard_index);
buf->free_buffer(buf);
buf = NULL;
- } else {
-#if 0
- if(this->guard_index >= this->curpos)
- LOGMSG("guard index: %" PRIu64 ", discard index: %" PRIu64 ", "
- "pos: %" PRIu64" , diff: %" PRIu64,
- this->discard_index, this->guard_index,
- this->curpos, this->discard_index-this->guard_index);
-#endif
+ continue;
+ }
- /* Send current PTS ? */
- if(this->stream_start)
- this->send_pts = 1;
+ /* Send current PTS ? */
+ if(this->stream_start) {
+ this->send_pts = 1;
this->stream_start = 0;
+ }
- if(this->send_pts) {
- int64_t pts = pts_from_pes(buf->content, buf->size);
- if(pts > 0) {
- vdr_x_demux_control_newpts(this->stream, pts, 0);
- this->send_pts = 0;
- }
- }
+ pthread_mutex_unlock(&this->lock);
- pthread_mutex_unlock(&this->lock);
- }
} while(!buf);
-#if 1
- track_audio_stream_change(this, buf);
+#ifdef CACHE_FIRST_IFRAME
+ cache_iframe(this, buf);
#endif
+ track_audio_stream_change(this, buf);
+
+ /* Send current PTS ? */
+ if(this->send_pts) {
+ int64_t pts = pts_from_pes(buf->content, buf->size);
+ if(pts > 0) {
+ vdr_x_demux_control_newpts(this->stream, pts, 0);
+ this->send_pts = 0;
+ }
+ }
+
TRACE("vdr_plugin_read_block: return data, pos end = %" PRIu64, this->curpos);
- buf->type = BUF_DEMUX_BLOCK;
return buf;
}
@@ -3989,6 +3933,8 @@ static void vdr_plugin_dispose (input_plugin_t *this_gen)
if(this->stream && this->stream->video_fifo)
this->stream->video_fifo->clear(this->stream->video_fifo);
+ if(this->iframe_buffer)
+ this->iframe_buffer->clear(this->iframe_buffer);
if(this->block_buffer)
this->block_buffer->clear(this->block_buffer);
if(this->big_buffer)
@@ -3996,6 +3942,8 @@ static void vdr_plugin_dispose (input_plugin_t *this_gen)
if(this->hd_buffer)
this->hd_buffer->clear(this->hd_buffer);
+ if(this->iframe_buffer)
+ this->iframe_buffer->dispose(this->iframe_buffer);
if(this->big_buffer)
this->big_buffer->dispose(this->big_buffer);
if(this->block_buffer)
@@ -4057,7 +4005,6 @@ static int vdr_plugin_open_local (input_plugin_t *this_gen)
static void set_recv_buffer_size(int fd, int max_buf)
{
-#if 1
/* try to have larger receiving buffer */
/*while(max_buf) {*/
@@ -4078,7 +4025,6 @@ static void set_recv_buffer_size(int fd, int max_buf)
max_buf = 256;
/* not going to send anything, so shrink send buffer ... */
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(int));
-#endif
}
static int alloc_udp_data_socket(int firstport, int trycount, int *port)
@@ -4217,6 +4163,8 @@ static int connect_rtp_data_stream(vdr_input_plugin_t *this)
return -1;
}
+ LOGMSG("Connecting (data) to rtp://%u.%u.%u.%u:%u ...",
+ ip0, ip1, ip2, ip3, port);
multicastAddress.sin_family = AF_INET;
multicastAddress.sin_port = htons(port);
multicastAddress.sin_addr.s_addr = htonl((ip0<<24)|(ip1<<16)|(ip2<<8)|ip3);
@@ -4437,7 +4385,7 @@ static int vdr_plugin_open_net (input_plugin_t *this_gen)
if(readline_control(this, tmpbuf, 256) >5 &&
!strncmp(tmpbuf, "PIPE ", 5) &&
strncmp(tmpbuf, "PIPE NONE", 9)) {
- LOGMSG("PIPE: %s", tmpbuf);
+ LOGMSG("Connecting (data) to pipe://%s", tmpbuf+5);
if((this->fd_data = open(tmpbuf+5, O_RDONLY|O_NONBLOCK)) >= 0) {
_x_io_tcp_write(this->stream, this->fd_control, "PIPE OPEN\r\n", 11);
if(readline_control(this, tmpbuf, 256) >6 &&
@@ -4462,7 +4410,7 @@ static int vdr_plugin_open_net (input_plugin_t *this_gen)
/* try RTP ? */
if(this->fd_data < 0 && !this->udp && !this->tcp) {
- LOGMSG("Connecting (data) to rtp://%s ...", host);
+ /*LOGMSG("Trying RTP connection ...");*/
/* flush control buffer (if PIPE was tried first) */
while(0 < read(this->fd_control, tmpbuf, 255)) ;
if((this->fd_data = connect_rtp_data_stream(this)) < 0) {
@@ -4478,6 +4426,7 @@ static int vdr_plugin_open_net (input_plugin_t *this_gen)
/* try UDP ? */
if(this->fd_data < 0 && !this->tcp) {
+ /*LOGMSG("Trying UDP connection ...", host);*/
LOGMSG("Connecting (data) to udp://%s ...", host);
/* flush control buffer (if RTP was tried first) */
while(0 < read(this->fd_control, tmpbuf, 255)) ;
@@ -4554,6 +4503,10 @@ static int vdr_plugin_open_net (input_plugin_t *this_gen)
return 0;
}
+ if(!(this->stream->video_out->get_capabilities(this->stream->video_out) &
+ VO_CAP_UNSCALED_OVERLAY))
+ LOGMSG("WARNING: Video output driver reports it does not support unscaled overlays !");
+
return 1;
}
@@ -4595,7 +4548,6 @@ static input_plugin_t *vdr_class_get_instance (input_class_t *cls_gen,
this->discard_index= 0;
this->guard_index = 0;
this->curpos = 0;
- this->read_delay = 0;
this->max_buffers = 10;
this->scr = NULL;
@@ -4607,7 +4559,7 @@ static input_plugin_t *vdr_class_get_instance (input_class_t *cls_gen,
this->still_mode = 0;
this->playback_finished = 0;
this->stream_start = 1;
- this->send_pts = 1;
+ this->send_pts = 0;
this->rescale_osd = 0;
this->unscaled_osd = 0;
@@ -4639,7 +4591,7 @@ static input_plugin_t *vdr_class_get_instance (input_class_t *cls_gen,
this->input_plugin.get_length = vdr_plugin_get_length;
this->input_plugin.get_blocksize = vdr_plugin_get_blocksize;
this->input_plugin.get_optional_data = vdr_plugin_get_optional_data;
-
+
if(local_mode) {
this->funcs.push_input_write = vdr_plugin_write;
this->funcs.push_input_control= vdr_plugin_parse_control;
@@ -4648,14 +4600,14 @@ static input_plugin_t *vdr_class_get_instance (input_class_t *cls_gen,
} else {
this->funcs.input_control = vdr_plugin_keypress;
}
-
+
this->mrl = strdup(mrl);
-
+
/* buffer */
this->block_buffer = _x_fifo_buffer_new(4,0x10000+64); /* dummy buf to be used before first read and for big PES frames */
this->big_buffer = NULL; /* dummy buf to be used for jumbo PES frames */
this->hd_buffer = NULL;
-
+
/* sync */
pthread_mutex_init (&this->lock, NULL);
pthread_mutex_init (&this->osd_lock, NULL);