From 41760a052b481e67ba31af505352860be86b94bf Mon Sep 17 00:00:00 2001 From: Stefan Holst Date: Thu, 12 Dec 2002 22:08:09 +0000 Subject: * Initial version of an rtsp input plugin. It is far from being perfect, only a few streams work for now. * A couple of fixes in pnm input plugin. * Fixed stream info in demux_real. CVS patchset: 3495 CVS date: 2002/12/12 22:08:09 --- configure.ac | 2 + src/demuxers/demux_real.c | 9 +- src/input/Makefile.am | 11 +- src/input/input_pnm.c | 24 +++- src/input/input_rtsp.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++ src/input/pnm.c | 219 +++++++++++++--------------------- src/input/pnm.h | 5 +- 7 files changed, 417 insertions(+), 150 deletions(-) create mode 100644 src/input/input_rtsp.c diff --git a/configure.ac b/configure.ac index f55d6e1ae..cf91c925c 100644 --- a/configure.ac +++ b/configure.ac @@ -1159,6 +1159,8 @@ src/dxr3/Makefile src/input/Makefile src/input/libdvdnav/Makefile src/input/libdvdread/Makefile +src/input/librtsp/Makefile +src/input/libreal/Makefile src/liba52/Makefile src/libdts/Makefile src/libfaad/Makefile diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index ec565c575..b5e7d2d5e 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -21,7 +21,7 @@ * For more information regarding the Real file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_real.c,v 1.22 2002/12/12 17:51:03 holstsn Exp $ + * $Id: demux_real.c,v 1.23 2002/12/12 22:08:11 holstsn Exp $ */ #ifdef HAVE_CONFIG_H @@ -92,7 +92,6 @@ typedef struct { int status; unsigned int duration; int packet_count; - int bitrate; int video_stream_num; uint32_t video_buf_type; @@ -328,9 +327,6 @@ static void real_parse_headers (demux_real_t *this) { mdpr = pnm_parse_mdpr (chunk_buffer); - this->bitrate = mdpr->avg_bit_rate; - this->stream->stream_info[XINE_STREAM_INFO_BITRATE] = mdpr->avg_bit_rate; - #ifdef LOG printf ("demux_real: parsing type specific data...\n"); #endif @@ -359,6 +355,8 @@ static void real_parse_headers (demux_real_t *this) { printf ("demux_real: audio detected %.3s\n", mdpr->type_specific_data+off+4); #endif + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITRATE] = mdpr->avg_bit_rate; + version = BE_16 (mdpr->type_specific_data+off); @@ -453,6 +451,7 @@ static void real_parse_headers (demux_real_t *this) { #ifdef LOG printf ("demux_real: video detected\n"); #endif + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_BITRATE] = mdpr->avg_bit_rate; /* FIXME: insert video codec detection code here */ break; /* video */ diff --git a/src/input/Makefile.am b/src/input/Makefile.am index a5d301066..d662ba379 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -3,9 +3,9 @@ ## if HAVE_DVDNAV -SUBDIRS = libdvdread +SUBDIRS = libreal librtsp libdvdread else -SUBDIRS = libdvdread libdvdnav +SUBDIRS = libreal librtsp libdvdread libdvdnav endif LIBTOOL = $(SHELL) $(top_builddir)/libtool-nofpic @@ -48,7 +48,8 @@ lib_LTLIBRARIES = \ $(in_vcd) \ xineplug_inp_mms.la \ xineplug_inp_stdin_fifo.la \ - xineplug_inp_pnm.la + xineplug_inp_pnm.la \ + xineplug_inp_rtsp.la #lib_LTLIBRARIES = \ # $(in_cda) \ @@ -102,6 +103,10 @@ xineplug_inp_pnm_la_SOURCES = input_pnm.c net_buf_ctrl.c pnm.c xineplug_inp_pnm_la_LIBADD = $(XINE_LIB) xineplug_inp_pnm_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ +xineplug_inp_rtsp_la_SOURCES = input_rtsp.c net_buf_ctrl.c +xineplug_inp_rtsp_la_LIBADD = $(XINE_LIB) libreal/libreal.la librtsp/librtsp.la +xineplug_inp_rtsp_la_LDFLAGS = -avoid-version -module @XINE_PLUGIN_MIN_SYMS@ + include_HEADERS = input_plugin.h noinst_HEADERS = net_buf_ctrl.h mms.h pnm.h diff --git a/src/input/input_pnm.c b/src/input/input_pnm.c index e30d0e721..35f4ea2d1 100644 --- a/src/input/input_pnm.c +++ b/src/input/input_pnm.c @@ -43,9 +43,11 @@ #include "pnm.h" #include "net_buf_ctrl.h" - +/* #define LOG +*/ +#define BUFSIZE 1025 extern int errno; @@ -71,7 +73,7 @@ typedef struct { nbc_t *nbc; - char scratch[1025]; + char scratch[BUFSIZE]; } pnm_input_plugin_t; @@ -121,11 +123,23 @@ static buf_element_t *pnm_plugin_read_block (input_plugin_t *this_gen, } static off_t pnm_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { - /* pnm_input_plugin_t *this = (pnm_input_plugin_t *) this_gen; - */ - return -1; + printf ("input_pnm: seek %lld bytes, origin %d\n", + offset, origin); + + /* only realtive forward-seeking is implemented */ + + if ((origin == SEEK_CUR) && (offset >= 0)) { + + for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { + this->curpos += pnm_plugin_read (this_gen, this->scratch, BUFSIZE); + } + + this->curpos += pnm_plugin_read (this_gen, this->scratch, offset); + } + + return this->curpos; } static off_t pnm_plugin_get_length (input_plugin_t *this_gen) { diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c new file mode 100644 index 000000000..ad483bde8 --- /dev/null +++ b/src/input/input_rtsp.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2002 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * rtsp input plugin + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bswap.h" + +#include "xine_internal.h" +#include "xineutils.h" +#include "input_plugin.h" + +#include "librtsp/rtsp_session.h" +#include "net_buf_ctrl.h" + +/* +#define LOG +*/ + +#define BUFSIZE 1025 + +extern int errno; + +#if !defined(NDELAY) && defined(O_NDELAY) +#define FNDELAY O_NDELAY +#endif + +typedef struct { + + input_class_t input_class; + + xine_t *xine; +} rtsp_input_class_t; + +typedef struct { + input_plugin_t input_plugin; + + rtsp_session_t *rtsp; + + char *mrl; + + off_t curpos; + + nbc_t *nbc; + + char scratch[BUFSIZE]; + +} rtsp_input_plugin_t; + + +static off_t rtsp_plugin_read (input_plugin_t *this_gen, + char *buf, off_t len) { + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + off_t n; + +#ifdef LOG + printf ("rtsp_plugin_read: %lld bytes ...\n", + len); +#endif + + nbc_check_buffers (this->nbc); + + n = rtsp_session_read (this->rtsp, buf, len); + this->curpos += n; + + return n; +} + +static buf_element_t *rtsp_plugin_read_block (input_plugin_t *this_gen, + fifo_buffer_t *fifo, off_t todo) { + /*rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; */ + buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + int total_bytes; + +#ifdef LOG + printf ("rtsp_plugin_read_block: %lld bytes...\n", + todo); +#endif + + buf->content = buf->mem; + buf->type = BUF_DEMUX_BLOCK; + + total_bytes = rtsp_plugin_read (this_gen, buf->content, todo); + + if (total_bytes != todo) { + buf->free_buffer (buf); + return NULL; + } + + buf->size = total_bytes; + + return buf; +} + +static off_t rtsp_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { + + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + printf ("input_rtsp: seek %lld bytes, origin %d\n", + offset, origin); + + /* only realtive forward-seeking is implemented */ + + if ((origin == SEEK_CUR) && (offset >= 0)) { + + for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { + this->curpos += rtsp_plugin_read (this_gen, this->scratch, BUFSIZE); + } + + this->curpos += rtsp_plugin_read (this_gen, this->scratch, offset); + } + + return this->curpos; +} + +static off_t rtsp_plugin_get_length (input_plugin_t *this_gen) { + + /* + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + off_t length; + */ + + return -1; +} + +static uint32_t rtsp_plugin_get_capabilities (input_plugin_t *this_gen) { + return INPUT_CAP_NOCAP; +} + +static uint32_t rtsp_plugin_get_blocksize (input_plugin_t *this_gen) { + return 0; +} + +static off_t rtsp_plugin_get_current_pos (input_plugin_t *this_gen){ + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + /* + printf ("current pos is %lld\n", this->curpos); + */ + + return this->curpos; +} + +static void rtsp_plugin_dispose (input_plugin_t *this_gen) { + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + if (this->rtsp) { + rtsp_session_end (this->rtsp); + this->rtsp = NULL; + } + + if (this->nbc) { + nbc_close (this->nbc); + this->nbc = NULL; + } + + if(this->mrl) + free(this->mrl); + + free (this); +} + +static char* rtsp_plugin_get_mrl (input_plugin_t *this_gen) { + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + + return this->mrl; +} + +static int rtsp_plugin_get_optional_data (input_plugin_t *this_gen, + void *data, int data_type) { + /* rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; */ + + return INPUT_OPTIONAL_UNSUPPORTED; +} + +static input_plugin_t *open_plugin (input_class_t *cls_gen, xine_stream_t *stream, + const char *data) { + + /* rtsp_input_class_t *cls = (rtsp_input_class_t *) cls_gen; */ + rtsp_input_plugin_t *this; + rtsp_session_t *rtsp; + char *mrl = strdup(data); + +#ifdef LOG + printf ("input_rtsp: trying to open '%s'\n", mrl); +#endif + + if (strncasecmp (mrl, "rtsp://", 6)) { + free (mrl); + return NULL; + } + + rtsp = rtsp_session_start(mrl); + + if (!rtsp) { + free (mrl); + return NULL; + } + + this = (rtsp_input_plugin_t *) xine_xmalloc (sizeof (rtsp_input_plugin_t)); + + this->rtsp = rtsp; + this->mrl = mrl; + this->nbc = nbc_init (stream); + + this->input_plugin.get_capabilities = rtsp_plugin_get_capabilities; + this->input_plugin.read = rtsp_plugin_read; + this->input_plugin.read_block = rtsp_plugin_read_block; + this->input_plugin.seek = rtsp_plugin_seek; + this->input_plugin.get_current_pos = rtsp_plugin_get_current_pos; + this->input_plugin.get_length = rtsp_plugin_get_length; + this->input_plugin.get_blocksize = rtsp_plugin_get_blocksize; + this->input_plugin.get_mrl = rtsp_plugin_get_mrl; + this->input_plugin.dispose = rtsp_plugin_dispose; + this->input_plugin.get_optional_data = rtsp_plugin_get_optional_data; + this->input_plugin.input_class = cls_gen; + + return &this->input_plugin; +} + +/* + * rtsp input plugin class stuff + */ + +static char *rtsp_class_get_description (input_class_t *this_gen) { + return _("rtsp streaming input plugin"); +} + +static char *rtsp_class_get_identifier (input_class_t *this_gen) { + return "rtsp"; +} + +static void rtsp_class_dispose (input_class_t *this_gen) { + rtsp_input_class_t *this = (rtsp_input_class_t *) this_gen; + + free (this); +} + +static void *init_class (xine_t *xine, void *data) { + + rtsp_input_class_t *this; + + this = (rtsp_input_class_t *) xine_xmalloc (sizeof (rtsp_input_class_t)); + + this->xine = xine; + + this->input_class.open_plugin = open_plugin; + this->input_class.get_identifier = rtsp_class_get_identifier; + this->input_class.get_description = rtsp_class_get_description; + this->input_class.get_dir = NULL; + this->input_class.get_autoplay_list = NULL; + this->input_class.dispose = rtsp_class_dispose; + this->input_class.eject_media = NULL; + + return this; +} + +/* + * exported plugin catalog entry + */ + +plugin_info_t xine_plugin_info[] = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_INPUT, 10, "rtsp", XINE_VERSION_CODE, NULL, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; + diff --git a/src/input/pnm.c b/src/input/pnm.c index 8341e23e6..419f32ccc 100644 --- a/src/input/pnm.c +++ b/src/input/pnm.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: pnm.c,v 1.1 2002/11/23 00:04:32 guenter Exp $ + * $Id: pnm.c,v 1.2 2002/12/12 22:08:14 holstsn Exp $ * * pnm protocol implementation by joschka */ @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -37,8 +36,11 @@ #include #include "pnm.h" +#include "libreal/rmff.h" +/* #define LOG +*/ #define BUF_SIZE 1024 #define HEADER_SIZE 1024 @@ -64,6 +66,8 @@ struct pnm_s { int header_read; unsigned int seq_num[4]; /* two streams with two indices */ unsigned int seq_current[2]; /* seqs of last stream chunk read */ + uint32_t ts_current; /* timestamp of current chunk */ + uint32_t ts_last[2]; /* timestamps of last chunks */ unsigned int packet; /* number of last recieved packet */ }; @@ -71,12 +75,6 @@ struct pnm_s { * utility macros */ -#define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \ - ( (long)(unsigned char)(ch3) | \ - ( (long)(unsigned char)(ch2) << 8 ) | \ - ( (long)(unsigned char)(ch1) << 16 ) | \ - ( (long)(unsigned char)(ch0) << 24 ) ) - #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ (((uint8_t*)(x))[1] << 16) | \ @@ -86,24 +84,6 @@ struct pnm_s { /* D means direct (no pointer) */ #define BE_16D(x) ((x & 0xff00) >> 8)|((x & 0x00ff) << 8) -/* - * constants - */ - -#define RMF_TAG FOURCC_TAG('.', 'R', 'M', 'F') -#define PROP_TAG FOURCC_TAG('P', 'R', 'O', 'P') -#define MDPR_TAG FOURCC_TAG('M', 'D', 'P', 'R') -#define CONT_TAG FOURCC_TAG('C', 'O', 'N', 'T') -#define DATA_TAG FOURCC_TAG('D', 'A', 'T', 'A') -#define INDX_TAG FOURCC_TAG('I', 'N', 'D', 'X') -#define PNA_TAG FOURCC_TAG('P', 'N', 'A', 0 ) - -/* prop flags */ -#define PN_SAVE_ENABLED 0x01 -#define PN_PERFECT_PLAY_ENABLED 0x02 -#define PN_LIVE_BROADCAST 0x04 - - /* sizes */ #define PREAMBLE_SIZE 8 #define CHECKSUM_SIZE 3 @@ -182,24 +162,6 @@ const uint32_t pnm_default_bandwidth=10485800; const uint32_t pnm_available_bandwidths[]={14400,19200,28800,33600,34430,57600, 115200,262200,393216,524300,1544000,10485800}; -/* some unknown chunks */ -#define PNM_AFTER_CLIENT_CAPS_SIZE 18 -const unsigned char pnm_after_client_caps[]={ - 0x00, 0x0a, 0x00, 0x00, - 0x00, 0x0c, 0x00, 0x00, - 0x00, 0x0d, 0x00, 0x00, - 0x00, 0x16, 0x00, 0x02, 0x00, 0x01 }; - -#define PNM_AFTER_BANDWIDTH_SIZE 28 -const unsigned char pnm_after_bandwidth[]={ - 0x00, 0x08, 0x00, 0x00, - 0x00, 0x0e, 0x00, 0x00, - 0x00, 0x0f, 0x00, 0x00, - 0x00, 0x11, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, - 0x00, 0x15, 0x00, 0x00, - 0x00, 0x12, 0x00, 0x00 }; - #define PNM_TWENTYFOUR_SIZE 16 unsigned char pnm_twentyfour[]={ 0xd5, 0x42, 0xa3, 0x1b, 0xef, 0x1f, 0x70, 0x24, @@ -302,7 +264,7 @@ static ssize_t rm_read(int fd, void *buf, size_t count) { FD_ZERO (&rset); FD_SET (fd, &rset); - timeout.tv_sec = 30; + timeout.tv_sec = 3; timeout.tv_usec = 0; if (select (fd+1, &rset, NULL, NULL, &timeout) <= 0) { @@ -356,23 +318,6 @@ static void hexdump (char *buf, int length) { printf ("\n"); } -/* - * basic stream reading - */ - -static char *pnm_get_string(unsigned char *data) { - - char *string; - int length; - - length=BE_16(data); - string=malloc(sizeof(char)*(length+1)); - memcpy(string,&data[2],length); - string[length]=0; - - return string; -} - /* * pnm_get_chunk gets a chunk from stream * and returns number of bytes read @@ -411,6 +356,12 @@ static unsigned int pnm_get_chunk(pnm_t *p, printf("%s\n",&data[PREAMBLE_SIZE+0x04]); exit(0); } + if (data[PREAMBLE_SIZE+0x01] == 'F') + { + printf("pnm: server error.\n"); + exit(0); + } + /* expecting following chunk format: 0x4f */ rm_read (p->s, ptr, 2); while (*ptr == 0x4f) { @@ -467,7 +418,6 @@ static int pnm_write_chunk(uint16_t chunk_id, uint16_t length, static void pnm_send_request(pnm_t *p, uint32_t bandwidth) { uint16_t i16; - uint32_t bw; int c=PNM_HEADER_SIZE; char fixme[]={0,1}; @@ -502,7 +452,7 @@ static void pnm_send_request(pnm_t *p, uint32_t bandwidth) { /* client id string */ p->buffer[c]=PNA_CLIENT_STRING; - i16=BE_16D(strlen(client_string)-1); /* dont know why do we have -1 here */ + i16=BE_16D((strlen(client_string)-1)); /* dont know why do we have -1 here */ memcpy(&p->buffer[c+1],&i16,2); memcpy(&p->buffer[c+3],client_string,strlen(client_string)+1); c=c+3+strlen(client_string)+1; @@ -551,7 +501,8 @@ static void pnm_get_headers(pnm_t *p) { uint8_t *ptr=p->header; uint8_t *prop_hdr=NULL; int chunk_size,size=0; - +/* rmff_header_t *h; */ + while(1) { if (HEADER_SIZE-size<=0) { @@ -572,13 +523,16 @@ static void pnm_get_headers(pnm_t *p) { } /* set pre-buffer to a low number */ - prop_hdr[36]=0x01; - prop_hdr[37]=0xd6; + /* prop_hdr[36]=0x01; + prop_hdr[37]=0xd6; */ + /* set data offset */ + size--; prop_hdr[42]=(size>>24)%0xff; prop_hdr[43]=(size>>16)%0xff; prop_hdr[44]=(size>>8)%0xff; prop_hdr[45]=(size)%0xff; + size++; /* read challenge */ memcpy (p->buffer, ptr, PREAMBLE_SIZE); @@ -587,7 +541,12 @@ static void pnm_get_headers(pnm_t *p) { /* now write a data header */ memcpy(ptr, pnm_data_header, PNM_DATA_HEADER_SIZE); size+=PNM_DATA_HEADER_SIZE; - +/* + h=rmff_scan_header(p->header); + rmff_fix_header(h); + p->header_len=rmff_get_header_size(h); + rmff_dump_header(h, p->header, HEADER_SIZE); +*/ p->header_len=size; } @@ -620,7 +579,7 @@ static int pnm_calc_stream(pnm_t *p) { } break; case 0: - case 2: /* both types or none possible, not so good */ + case 2: /* both types or none possible, not so good */ /* try to figure out by second index */ if ( (p->seq_current[1] == p->seq_num[1]) &&(p->seq_current[1] != p->seq_num[3])) @@ -638,8 +597,14 @@ static int pnm_calc_stream(pnm_t *p) { p->seq_num[3]++; return 1; } - /* wow, both streams match, or not. */ - /* in this case, we guess type 0 */ + /* wow, both streams match, or not. */ + /* now we try to decide by timestamps */ + if (p->ts_current < p->ts_last[1]) + return 0; + if (p->ts_current < p->ts_last[0]) + return 1; + /* does not help, we guess type 0 */ + printf("guessing stream# 0\n"); p->seq_num[0]=p->seq_current[0]+1; p->seq_num[1]=p->seq_current[1]+1; return 0; @@ -680,6 +645,9 @@ static int pnm_get_stream_chunk(pnm_t *p) { { n = rm_read (p->s, p->buffer, 8); if (n<8) return 0; +#ifdef LOG + printf("pnm: had to seek 8 bytes on 0x62\n"); +#endif } /* a server message */ @@ -692,6 +660,11 @@ static int pnm_get_stream_chunk(pnm_t *p) { printf("pnm: got message from server:\n%s\n", &p->buffer[3]); exit(0); } + if (p->buffer[0] == 'F') + { + printf("pnm: server error.\n"); + exit(0); + } /* skip bytewise to next chunk. * seems, that we dont need that, if we send enough @@ -706,8 +679,9 @@ static int pnm_get_stream_chunk(pnm_t *p) { rm_read (p->s, &p->buffer[7], 1); n++; } + if (n) printf("pnm: had to seek %i bytes to next chunk\n", n); - + /* check for 'Z's */ if ((p->buffer[0] != 0x5a)||(p->buffer[7] != 0x5a)) { @@ -735,8 +709,14 @@ static int pnm_get_stream_chunk(pnm_t *p) { /* get second index */ p->seq_current[1]=p->recv[5]; + /* get timestamp */ + p->ts_current=BE_32(&p->recv[6]); + /* get stream number */ stream=pnm_calc_stream(p); + + /* saving timestamp */ + p->ts_last[stream]=p->ts_current; /* constructing a data packet header */ @@ -843,80 +823,51 @@ pnm_t *pnm_connect(const char *mrl) { pnm_send_request(p,pnm_available_bandwidths[10]); pnm_get_headers(p); pnm_send_response(p, pnm_response); + p->ts_last[0]=0; + p->ts_last[1]=0; + + /* copy header to recv */ + + memcpy(p->recv, p->header, p->header_len); + p->recv_size = p->header_len; + p->recv_read = 0; return p; } int pnm_read (pnm_t *this, char *data, int len) { - int total; - - total = 0; - - while (total < len) { + + int to_copy=len; + char *dest=data; + char *source=this->recv + this->recv_read; + int fill=this->recv_size - this->recv_read; + + if (len < 0) return 0; + while (to_copy > fill) { + + memcpy(dest, source, fill); + to_copy -= fill; + dest += fill; + this->recv_read=0; + if (!pnm_get_stream_chunk (this)) { #ifdef LOG - printf ("libpnm: read, got %d / %d bytes\n", total, len); + printf ("libpnm: %d of %d bytes provided\n", len-to_copy, len); #endif - - if (this->header_read < this->header_len) { - int n, bytes_left ; - - printf ("libpnm: reading from header (%d<%d)\n", - this->header_read, this->header_len); - - bytes_left = this->header_len - this->header_read ; - - if ((len-total) < bytes_left) - n = len-total; - else - n = bytes_left; - - memcpy (&data[total], &this->header[this->header_read], n); - - printf ("libpnm: copied %d bytes\n", n); - - this->header_read += n; - total += n; - } else { - - int n, bytes_left ; - - printf ("libpnm: reading from chunk (%d>=%d)\n", - this->header_read, this->header_len); - - bytes_left = this->recv_size - this->recv_read; - - while (!bytes_left) { - - this->recv_read = 0; - - if (!pnm_get_stream_chunk (this)) { - printf ("libpnm: pnm_get_stream_chunk failed\n"); - return total; - } - bytes_left = this->recv_size - this->recv_read; - } - - - if ((len-total)recv[this->recv_read], n); - - printf ("libpnm: copied %d bytes\n", n); - - this->recv_read += n; - total += n; + return len-to_copy; } + source = this->recv; + fill = this->recv_size - this->recv_read; } - printf ("libpnm: total=%d\n", total); + memcpy(dest, source, to_copy); + this->recv_read += to_copy; - hexdump (data, total); +#ifdef LOG + printf ("libpnm: %d bytes provided\n", len); +#endif - return total; + return len; } int pnm_peek_header (pnm_t *this, char *data) { @@ -934,5 +885,3 @@ void pnm_close(pnm_t *p) { free(p); } - - diff --git a/src/input/pnm.h b/src/input/pnm.h index 8d07986ab..a2fb68539 100644 --- a/src/input/pnm.h +++ b/src/input/pnm.h @@ -17,16 +17,17 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: pnm.h,v 1.1 2002/11/23 00:04:32 guenter Exp $ + * $Id: pnm.h,v 1.2 2002/12/12 22:08:15 holstsn Exp $ * * pnm util functions header by joschka - * */ #ifndef HAVE_PNM_H #define HAVE_PNM_H +#ifndef __CYGWIN__ #include +#endif /*#include "xine_internal.h" */ typedef struct pnm_s pnm_t; -- cgit v1.2.3