diff options
-rw-r--r-- | xine_input_vdr.c | 215 |
1 files changed, 152 insertions, 63 deletions
diff --git a/xine_input_vdr.c b/xine_input_vdr.c index 2dbae7cc..42100b58 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.64 2006-12-19 16:57:21 phintuka Exp $ + * $Id: xine_input_vdr.c,v 1.65 2006-12-19 17:09:26 phintuka Exp $ * */ @@ -661,7 +661,7 @@ 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; - int num_vbufs = 0; + /*int num_vbufs = 0;*/ if(this->hd_stream && this->hd_buffer) { num_free += this->hd_buffer->num_free(this->hd_buffer); @@ -706,17 +706,20 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this) (if clock is not paused we will got a lot of discarded frames as those are decoded too late according to running SCR) */ - this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); +#if 0 + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); num_vbufs = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_BUFS_IN_FIFO); - this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); - + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); if(num_vbufs < 3) { LOGSCR("SCR paused by adjust_speed (vbufs=%d)", num_vbufs); +#endif scr_tunning_set_paused(this); +#if 0 } else { - LOGSCR("adjust_speed: no pause, enough vbufs queued"); + LOGSCR("adjust_speed: no pause, enough vbufs queued (%d)", num_vbufs); } +#endif /* If currently paused, revert to normal if buffer > 50% */ } else if( scr_tunning == SCR_TUNNING_PAUSED) { @@ -728,10 +731,12 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this) - First I-frame can be delivered as soon as it is decoded -> illusion of faster channel switches */ - this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); +#if 0 + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 0); num_vbufs = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_BUFS_IN_FIFO); - this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 0); +#endif this->paused_frames++; if( num_used/2 > num_free @@ -739,13 +744,13 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this) || this->paused_frames > 200 || (this->paused_frames > 100 && this->pause_start + 400 < monotonic_time_ms()) - || num_vbufs > 5 + /*|| 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, this->paused_frames, + /*num_vbufs*/0, this->paused_frames, monotonic_time_ms() - this->pause_start); this->paused_frames = 0; @@ -959,25 +964,31 @@ static void printf_control(vdr_input_plugin_t *this, const char *fmt, ...) va_end(argp); } -static int readline_control(vdr_input_plugin_t *this, char *buf, int maxlen) +static int readline_control(vdr_input_plugin_t *this, char *buf, int maxlen, + int timeout) { int num_bytes = 0, total_bytes = 0, err; *buf = 0; while(total_bytes < maxlen-1 ) { - if(!this->control_running) + if(!this->control_running && timeout<0) return -1; pthread_testcancel(); err = io_select_rd(this->fd_control); pthread_testcancel(); - if(!this->control_running) + if(!this->control_running && timeout<0) return -1; - if(err == XIO_TIMEOUT) - continue; + if(err == XIO_TIMEOUT) { + if(timeout==0) + return 0; + if(timeout>0) + timeout--; + continue; + } if(err == XIO_ABORTED) { LOGERR("readline_control: XIO_ABORTED at [%d]", num_bytes); continue; @@ -991,7 +1002,7 @@ static int readline_control(vdr_input_plugin_t *this, char *buf, int maxlen) num_bytes = read (this->fd_control, buf + total_bytes, 1); pthread_testcancel(); - if(!this->control_running) + if(!this->control_running && timeout<0) return -1; if (num_bytes <= 0) { @@ -2415,9 +2426,35 @@ static int handle_control_playfile(vdr_input_plugin_t *this, const char *cmd) handle_control_playfile(this, "PLAYFILE 0"); LOGMSG("PLAYFILE (Loop: %d, Offset: %ds, File: %s %s)", - loop, pos, *filename ? av:"", *filename ? filename : "<STOP>"); - - subs = FindSubFile(filename); + loop, pos, av, filename); + + /* check if it is really a file (not mrl) and try to access it */ + if(filename[0] == '/') { + struct stat st; + errno = 0; + if(stat(filename, &st)) { + if(errno == EACCES || errno == ELOOP) + LOGERR("Can't access file !"); + if(errno == ENOENT || errno == ENOTDIR) + LOGERR("File not found !"); + if(this->fd_control > 0) { + char mrl[512]; + char *phost = strdup(strstr(this->mrl, "//") + 2); + char *port = strchr(phost, ':'); + int iport; + if(port) *port++ = 0; + iport = port ? atoi(port) : DEFAULT_VDR_PORT; + sprintf(mrl, "http://%s:%d/PLAYFILE", + phost, iport); + free(phost); + LOGMSG(" -> trying to stream from server (%s) ...", mrl); + strcpy(filename, mrl); + } + } else { + subs = FindSubFile(filename); + } + } + if(subs) { LOGMSG("Found subtitles: %s", subs); strcat(filename, "#subtitle:"); @@ -3217,10 +3254,13 @@ static int vdr_plugin_parse_control(input_plugin_t *this_gen, const char *cmd) err = handle_control_substream(this, cmd); } else if(!strncasecmp(cmd, "POST ", 5)) { + /* lock demuxer thread out of adjust_realtime_speed */ + pthread_mutex_lock(&this->lock); if(!this->funcs.fe_control) LOGMSG("No fe_control function! %s failed.", cmd); else this->funcs.fe_control(this->funcs.fe_handle, cmd); + pthread_mutex_unlock(&this->lock); } else if(!strncasecmp(cmd, "PLAYFILE ", 9)) { err = handle_control_playfile(this, cmd); @@ -3319,7 +3359,7 @@ static void *vdr_control_thread(void *this_gen) /* read next command */ line[0] = 0; pthread_testcancel(); - if((err=readline_control(this, line, sizeof(line)-1)) <= 0) { + if((err=readline_control(this, line, sizeof(line)-1, -1)) <= 0) { if(err < 0) break; continue; @@ -4784,7 +4824,6 @@ static int connect_control_stream(vdr_input_plugin_t *this, const char *host, this->fd_control = saved_fd; return -1; } - this->control_running = 1; /* request control connection */ if(_x_io_tcp_write(this->stream, fd_control, "CONTROL\r\n", 9) < 0) { @@ -4793,7 +4832,7 @@ static int connect_control_stream(vdr_input_plugin_t *this, const char *host, } /* Check server greeting */ - if(readline_control(this, tmpbuf, 256) <= 0) { + if(readline_control(this, tmpbuf, sizeof(tmpbuf)-1, 4) <= 0) { LOGMSG("Server not replying"); close(fd_control); this->fd_control = saved_fd; @@ -4821,9 +4860,9 @@ static int connect_control_stream(vdr_input_plugin_t *this, const char *host, } /* Store our client-id */ - if(readline_control(this, tmpbuf, 256) > 0 && + if(readline_control(this, tmpbuf, sizeof(tmpbuf)-1, 4) > 0 && !strncmp(tmpbuf, "CLIENT-ID ", 10)) { - LOGMSG("Got Client-ID: %s", tmpbuf+10); + LOGDBG("Got Client-ID: %s", tmpbuf+10); if(client_id) if(1 != sscanf(tmpbuf+10, "%d", client_id)) *client_id = -1; @@ -4843,7 +4882,7 @@ static int connect_control_stream(vdr_input_plugin_t *this, const char *host, static int connect_rtp_data_stream(vdr_input_plugin_t *this) { - char cmd[64]; + char cmd[256]; unsigned int ip0, ip1, ip2, ip3, port; int fd=-1, one = 1, retries = 0, n; struct sockaddr_in multicastAddress; @@ -4868,7 +4907,7 @@ static int connect_rtp_data_stream(vdr_input_plugin_t *this) } cmd[0] = 0; - if(readline_control(this, cmd, 256) < 8 || + if(readline_control(this, cmd, sizeof(cmd)-1, 4) < 8 || strncmp(cmd, "RTP ", 4)) { LOGMSG("Server does not support RTP ? (%s)", cmd); return -1; @@ -4977,7 +5016,7 @@ retry_recvfrom: static int connect_udp_data_stream(vdr_input_plugin_t *this) { - char cmd[64]; + char cmd[256]; struct sockaddr_in server_address, sin; socklen_t len = sizeof(sin); uint32_t tmp_ip; @@ -5013,6 +5052,13 @@ retry_request: return -1; } + cmd[0] = 0; + if(readline_control(this, cmd, sizeof(cmd)-1, 4) < 6 || + strncmp(cmd, "UDP OK", 6)) { + LOGMSG("Server does not support UDP ? (%s)", cmd); + return -1; + } + retry_select: /* wait until server sends first UDP packet */ @@ -5059,8 +5105,11 @@ retry_recvfrom: static int connect_tcp_data_stream(vdr_input_plugin_t *this, const char *host, int port) { + struct sockaddr_in sinc; + socklen_t len = sizeof(sinc); + uint32_t ipc; char tmpbuf[256]; - int fd_data; + int fd_data, n; /* Connect to server */ fd_data = _x_io_tcp_connect(this->stream, host, port); @@ -5072,18 +5121,28 @@ static int connect_tcp_data_stream(vdr_input_plugin_t *this, const char *host, return -1; } - set_recv_buffer_size(fd_data, KILOBYTE(64)); + set_recv_buffer_size(fd_data, KILOBYTE(128)); /* request data connection */ - sprintf(tmpbuf, "DATA %d\r\n", this->client_id); + + getsockname(this->fd_control, (struct sockaddr *)&sinc, &len); + ipc = ntohl(sinc.sin_addr.s_addr); + sprintf(tmpbuf, + "DATA %d 0x%x:%u %d.%d.%d.%d\r\n", + this->client_id, + (unsigned int)ipc, + (unsigned int)ntohs(sinc.sin_port), + ((ipc>>24)&0xff), ((ipc>>16)&0xff), ((ipc>>8)&0xff), ((ipc)&0xff) + ); if(_x_io_tcp_write(this->stream, fd_data, tmpbuf, strlen(tmpbuf)) < 0) { - LOGERR("Data stream write error"); + LOGERR("Data stream write error (TCP)"); } else if( XIO_READY != io_select_rd(fd_data)) { - LOGERR("Data stream connection failed (TCP, select)"); - } else if(read(fd_data, tmpbuf, 6) != 6) { - LOGERR("Data stream connection failed (TCP, read)"); - } else if(strncmp(tmpbuf, "DATA\r\n", 6)) { - LOGMSG("Data stream connection failed (TCP, token). Got: %6s", tmpbuf); + LOGERR("Data stream poll failed (TCP)"); + } else if((n=read(fd_data, tmpbuf, sizeof(tmpbuf))) <= 0) { + LOGERR("Data stream read failed (TCP)"); + } else if(n<6 || strncmp(tmpbuf, "DATA\r\n", 6)) { + tmpbuf[n] = 0; + LOGMSG("Server does not support TCP ? (%s)", tmpbuf); } else { /* succeed */ /* set socket to non-blocking mode */ @@ -5095,11 +5154,62 @@ static int connect_tcp_data_stream(vdr_input_plugin_t *this, const char *host, return -1; } +static int connect_pipe_data_stream(vdr_input_plugin_t *this) +{ + char tmpbuf[256]; + int fd_data = -1; + + /* check if IP address matches */ + if(!strstr(this->mrl, "127.0.0.1")) { + struct sockaddr_in sinc; + struct sockaddr_in sins; + socklen_t len = sizeof(sinc); + getsockname(this->fd_control, &sinc, &len); + getpeername(this->fd_control, &sins, &len); + if(sinc.sin_addr.s_addr != sins.sin_addr.s_addr) { + LOGMSG("connect_pipe_data_stream: client ip=0x%x != server ip=0x%x !", + (unsigned int)sinc.sin_addr.s_addr, (unsigned int)sins.sin_addr.s_addr); +#if 0 + LOGMSG(" different host, pipe won't work"); + return -1; +#endif + } + } + + _x_io_tcp_write(this->stream, this->fd_control, "PIPE\r\n", 6); + + if(readline_control(this, tmpbuf, sizeof(tmpbuf), 4) <= 0) { + LOGMSG("Pipe request failed"); + } else if(strncmp(tmpbuf, "PIPE /", 6)) { + LOGMSG("Server does not support pipes ? (%s)", tmpbuf); + } else { + + LOGMSG("Connecting (data) to pipe://%s", tmpbuf+5); + if((fd_data = open(tmpbuf+5, O_RDONLY|O_NONBLOCK)) < 0) { + if(errno == ENOENT) + LOGMSG("Pipe not found"); + else + LOGERR("Pipe opening failed"); + } else { + _x_io_tcp_write(this->stream, this->fd_control, "PIPE OPEN\r\n", 11); + if(readline_control(this, tmpbuf, sizeof(tmpbuf)-1, 4) >6 && + !strncmp(tmpbuf, "PIPE OK", 7)) { + fcntl (fd_data, F_SETFL, fcntl (fd_data, F_GETFL) | O_NONBLOCK); + return fd_data; + } + LOGMSG("Data stream connection failed (PIPE)"); + } + } + + close(fd_data); + return -1; +} + static int vdr_plugin_open_net (input_plugin_t *this_gen) { vdr_input_plugin_t *this = (vdr_input_plugin_t *) this_gen; - int err; char tmpbuf[256]; + int err; LOGDBG("vdr_plugin_open_net %s", this->mrl); @@ -5140,42 +5250,21 @@ static int vdr_plugin_open_net (input_plugin_t *this_gen) /* try pipe ? */ if(!this->tcp && !this->udp && !this->rtp) { - LOGMSG("Trying pipe (data) ..."); - _x_io_tcp_write(this->stream, this->fd_control, "PIPE\r\n", 6); - *tmpbuf=0; - if(readline_control(this, tmpbuf, 256) >5 && - !strncmp(tmpbuf, "PIPE ", 5) && - strncmp(tmpbuf, "PIPE NONE", 9)) { - 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 && - !strncmp(tmpbuf, "PIPE OK", 7)) { - fcntl (this->fd_data, F_SETFL, - fcntl (this->fd_data, F_GETFL) | O_NONBLOCK); - this->tcp = this->udp = this->tcp = 0; - LOGMSG("Pipe connected (data)"); - } else { - close(this->fd_data); - this->fd_data = -1; - LOGMSG("Pipe connection failed."); - } - } else { - LOGERR("Pipe opening failed"); - } + if((this->fd_data = connect_pipe_data_stream(this)) < 0) { + LOGMSG("Data stream connection failed (PIPE)"); } else { - LOGMSG("Server does not support pipes."); + this->tcp = this->udp = this->tcp = 0; + LOGMSG("Data stream connected (PIPE)"); } } /* try RTP ? */ if(this->fd_data < 0 && !this->udp && !this->tcp) { - /*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) { - LOGMSG("connect_rtp_data_stream failed"); + LOGMSG("Data stream connection failed (RTP)"); this->rtp = 0; } else { this->rtp = 1; |