# HG changeset patch # User albeu # Date 1049300707 0 # Node ID f67d87b2d3c77935f55282919cf214e2e6039d79 # Parent b2bf632d37b5fb942cb84819a7dc4ce8524110d3 Stream modularization, the first step. Only file stream are converted atm, other will come later. diff -r b2bf632d37b5 -r f67d87b2d3c7 libmpdemux/stream.c --- a/libmpdemux/stream.c Wed Apr 02 16:15:06 2003 +0000 +++ b/libmpdemux/stream.c Wed Apr 02 16:25:07 2003 +0000 @@ -9,6 +9,7 @@ #include #include #include +#include #include "config.h" #include "mp_msg.h" @@ -18,6 +19,10 @@ #include "stream.h" #include "demuxer.h" +#include "../m_option.h" +#include "../m_struct.h" + + extern int verbose; // defined in mplayer.c #include "cue_read.h" @@ -52,6 +57,100 @@ #include "libsmbclient.h" #endif +extern stream_info_t stream_info_file; + +stream_info_t* auto_open_streams[] = { + &stream_info_file, + NULL +}; + +stream_t* open_stream_plugin(stream_info_t* sinfo,char* filename,int mode, + char** options, int* file_format, int* ret) { + void* arg = NULL; + stream_t* s; + m_struct_t* desc = (m_struct_t*)sinfo->opts; + + // Parse options + if(desc) { + arg = m_struct_alloc(desc); + if(sinfo->opts_url) { + m_option_t url_opt = + { "stream url", arg , CONF_TYPE_CUSTOM_URL, 0, 0 ,0, sinfo->opts }; + if(m_option_parse(&url_opt,"stream url",filename,arg,M_CONFIG_FILE) < 0) { + mp_msg(MSGT_OPEN,MSGL_ERR, "URL parsing failed on url %s\n",filename); + m_struct_free(desc,arg); + return NULL; + } + } + if(options) { + int i; + for(i = 0 ; options[i] != NULL ; i += 2) { + mp_msg(MSGT_OPEN,MSGL_DBG2, "Set stream arg %s=%s\n", + options[i],options[i+1]); + if(!m_struct_set(desc,arg,options[i],options[i+1])) + mp_msg(MSGT_OPEN,MSGL_WARN, "Failed to set stream option %s=%s\n", + options[i],options[i+1]); + } + } + } + s = new_stream(-2,-2); + s->url=strdup(filename); + s->flags |= mode; + *ret = sinfo->open(s,mode,arg,file_format); + if((*ret) != STREAM_OK) { + free(s->url); + free(s); + return NULL; + } + if(s->type <= -2) + mp_msg(MSGT_OPEN,MSGL_WARN, "Warning streams need a type !!!!\n"); + if(s->flags & STREAM_SEEK && !s->seek) + s->flags &= ~STREAM_SEEK; + if(s->seek && !(s->flags & STREAM_SEEK)) + s->flags &= STREAM_SEEK; + + + mp_msg(MSGT_OPEN,MSGL_V, "STREAM: [%s] %s\n",sinfo->name,filename); + mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Description: %s\n",sinfo->info); + mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Author: %s\n", sinfo->author); + mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Comment: %s\n", sinfo->comment); + + return s; +} + + +stream_t* open_stream_full(char* filename,int mode, char** options, int* file_format) { + int i,j,l,r; + stream_info_t* sinfo; + stream_t* s; + + for(i = 0 ; auto_open_streams[i] ; i++) { + sinfo = auto_open_streams[i]; + if(!sinfo->protocols) { + mp_msg(MSGT_OPEN,MSGL_WARN, "Stream type %s have protocols == NULL, it's a bug\n"); + continue; + } + for(j = 0 ; sinfo->protocols[j] ; j++) { + l = strlen(sinfo->protocols[j]); + // l == 0 => Don't do protocol matching (ie network and filenames) + if((l == 0) || ((strncmp(sinfo->protocols[j],filename,l) == 0) && + (strncmp("://",filename+l,3) == 0))) { + *file_format = DEMUXER_TYPE_UNKNOWN; + s = open_stream_plugin(sinfo,filename,mode,options,file_format,&r); + if(s) return s; + if(r != STREAM_UNSUPORTED) { + mp_msg(MSGT_OPEN,MSGL_ERR, "Failed to open %s\n",filename); + return NULL; + } + break; + } + } + } + + mp_msg(MSGT_OPEN,MSGL_ERR, "No stream found to handle url %s\n",filename); + return NULL; +} + //=================== STREAMER ========================= int stream_fill_buffer(stream_t *s){ @@ -63,9 +162,7 @@ len=smbc_read(s->fd,s->buffer,STREAM_BUFFER_SIZE); break; #endif - case STREAMTYPE_FILE: case STREAMTYPE_STREAM: - case STREAMTYPE_PLAYLIST: #ifdef STREAMING if( s->streaming_ctrl!=NULL ) { len=s->streaming_ctrl->streaming_read(s->fd,s->buffer,STREAM_BUFFER_SIZE, s->streaming_ctrl);break; @@ -115,7 +212,8 @@ - default: len=0; + default: + len= s->fill_buffer ? s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE) : 0; } if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; } s->buf_pos=0; @@ -133,7 +231,6 @@ s->buf_pos=s->buf_len=0; switch(s->type){ - case STREAMTYPE_FILE: case STREAMTYPE_SMB: case STREAMTYPE_STREAM: #ifdef _LARGEFILE_SOURCE @@ -151,6 +248,18 @@ case STREAMTYPE_CDDA: newpos=(pos/VCD_SECTOR_SIZE)*VCD_SECTOR_SIZE;break; #endif + default: + // Round on sector size + if(s->sector_size) + newpos=(pos/s->sector_size)*s->sector_size; + else { // Otherwise on the buffer size +#ifdef _LARGEFILE_SOURCE + newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break; +#else + newpos=pos&(~(STREAM_BUFFER_SIZE-1));break; +#endif + } + break; } if(verbose>=3){ @@ -167,10 +276,6 @@ if(newpos==0 || newpos!=s->pos){ switch(s->type){ - case STREAMTYPE_FILE: - s->pos=newpos; // real seek - if(lseek(s->fd,s->pos,SEEK_SET)<0) s->eof=1; - break; #ifdef LIBSMBCLIENT case STREAMTYPE_SMB: s->pos=newpos; // real seek @@ -236,7 +341,14 @@ #endif break; default: - return 0; + // This should at the beginning as soon as all streams are converted + if(!s->seek) + return 0; + // Now seek + if(!s->seek(s,newpos)) { + mp_msg(MSGT_STREAM,MSGL_ERR, "Seek failed\n"); + return 0; + } } // putchar('.');fflush(stdout); //} else { @@ -328,8 +440,13 @@ case STREAMTYPE_DVD: dvd_close(s->priv); #endif - } - if(s->priv) free(s->priv); + default: + if(s->close) s->close(s); + } + // Disabled atm, i don't like that. s->priv can be anything after all + // streams should destroy their priv on close + //if(s->priv) free(s->priv); + if(s->url) free(s->url); free(s); } diff -r b2bf632d37b5 -r f67d87b2d3c7 libmpdemux/stream.h --- a/libmpdemux/stream.h Wed Apr 02 16:15:06 2003 +0000 +++ b/libmpdemux/stream.h Wed Apr 02 16:25:07 2003 +0000 @@ -26,6 +26,26 @@ #define VCD_SECTOR_OFFS 24 #define VCD_SECTOR_DATA 2324 +/// atm it will always use mode == STREAM_READ +/// streams that use the new api should check the mode at open +#define STREAM_READ 0 +#define STREAM_WRITE 1 +/// Seek flags, if not mannualy set and s->seek isn't NULL +/// STREAM_SEEK is automaticly set +#define STREAM_SEEK_BW 2 +#define STREAM_SEEK_FW 4 +#define STREAM_SEEK (STREAM_SEEK_BW|STREAM_SEEK_FW) + +//////////// Open return code +/// This can't open the requested protocol (used by stream wich have a +/// * protocol when they don't know the requested protocol) +#define STREAM_UNSUPORTED -1 +#define STREAM_ERROR 0 +#define STREAM_OK 1 + +#define MAX_STREAM_PROTOCOLS 10 + + #ifdef STREAMING #include "network.h" #endif @@ -33,9 +53,41 @@ int vcd_seek_to_track(int fd,int track); void vcd_read_toc(int fd); +struct stream_st; +typedef struct stream_info_st { + const char *info; + const char *name; + const char *author; + const char *comment; + /// mode isn't used atm (ie always READ) but it shouldn't be ignored + /// opts is at least in it's defaults settings and may have been + /// altered by url parsing if enabled and the options string parsing. + int (*open)(struct stream_st* st, int mode, void* opts, int* file_format); + char* protocols[MAX_STREAM_PROTOCOLS]; + void* opts; + int opts_url; /* If this is 1 we will parse the url as an option string + * too. Otherwise options are only parsed from the + * options string given to open_stream_plugin */ +} stream_info_t; + typedef struct stream_st { + // Read + int (*fill_buffer)(struct stream_st *s, char* buffer, int max_len); + // Write + int (*write_buffer)(struct stream_st *s, char* buffer, int len); + // Seek + int (*seek)(struct stream_st *s,off_t pos); + // Control + // Will be later used to let streams like dvd and cdda report + // their structure (ie tracks, chapters, etc) + int (*control)(struct stream_st *s,int cmd,void* arg); + // Close + void (*close)(struct stream_st *s); + int fd; // file descriptor, see man open(2) int type; // see STREAMTYPE_* + int flags; + int sector_size; // sector size (seek will be aligned on this size if non 0) unsigned int buf_pos,buf_len; off_t pos,start_pos,end_pos; int eof; @@ -187,7 +239,8 @@ stream_t* new_stream(int fd,int type); void free_stream(stream_t *s); stream_t* new_memory_stream(unsigned char* data,int len); -stream_t* open_stream(char* filename,int vcd_track,int* file_format); +stream_t* open_stream(char* filename,char** options,int* file_format); +stream_t* open_stream_full(char* filename,int mode, char** options, int* file_format); //#ifdef USE_DVDREAD struct config; diff -r b2bf632d37b5 -r f67d87b2d3c7 libmpdemux/stream_file.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmpdemux/stream_file.c Wed Apr 02 16:25:07 2003 +0000 @@ -0,0 +1,136 @@ + +#include "config.h" + +#include +#include +#include +#include + +#include "mp_msg.h" +#include "stream.h" +#include "help_mp.h" +#include "../m_option.h" +#include "../m_struct.h" + +static struct stream_priv_s { + char* filename; +} stream_priv_dflts = { + NULL +}; + +#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) +/// URL definition +static m_option_t stream_opts_fields[] = { + {"filename", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL}, + { NULL, NULL, 0, 0, 0, 0, NULL } +}; +static struct m_struct_st stream_opts = { + "file", + sizeof(struct stream_priv_s), + &stream_priv_dflts, + stream_opts_fields +}; + +static int fill_buffer(stream_t *s, char* buffer, int max_len){ + int r = read(s->fd,buffer,max_len); + return (r <= 0) ? -1 : r; +} + +static int write_buffer(stream_t *s, char* buffer, int len) { + int r = write(s->fd,buffer,len); + return (r <= 0) ? -1 : r; +} + +static int seek(stream_t *s,off_t newpos) { + s->pos = newpos; + if(lseek(s->fd,s->pos,SEEK_SET)<0) { + s->eof=1; + return 0; + } + return 1; +} + +static int seek_forward(stream_t *s,off_t newpos) { + if(newpospos){ + mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n"); + return 0; + } + while(s->posfill_buffer(s,s->buffer,STREAM_BUFFER_SIZE)<=0) break; // EOF + } + return 1; +} + +static int open_f(stream_t *stream,int mode, void* opts, int* file_format) { + int f; + mode_t m = 0; + off_t len; + struct stream_priv_s* p = (struct stream_priv_s*)opts; + + if(mode == STREAM_READ) + m = O_RDONLY; + else if(mode == STREAM_WRITE) + m = O_WRONLY; + else { + mp_msg(MSGT_OPEN,MSGL_ERR, "[file] Unknow open mode %d\n",mode); + m_struct_free(&stream_opts,opts); + return STREAM_UNSUPORTED; + } + +#if defined(__CYGWIN__)|| defined(__MINGW32__) + m |= O_BINARY; +#endif + + if(!strcmp(p->filename,"-")){ + if(mode == STREAM_READ) { + // read from stdin + mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ReadSTDIN); + f=0; // 0=stdin + } else { + mp_msg(MSGT_OPEN,MSGL_INFO,"Writing to stdout\n"); + f=1; + } + } else { + f=open(p->filename,m); + if(f<0) { + mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,p->filename); + m_struct_free(&stream_opts,opts); + return -1; + } + } + + len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET); + if(len == -1) { + stream->seek = seek_forward; + stream->type = STREAMTYPE_STREAM; // Must be move to STREAMTYPE_FILE + stream->flags |= STREAM_SEEK_FW; + } else if(len >= 0) { + stream->seek = seek; + stream->end_pos = len; + stream->type = STREAMTYPE_FILE; + } + +#ifdef _LARGEFILE_SOURCE + mp_msg(MSGT_OPEN,MSGL_V,"[file] File size is %lld bytes\n", (long long)len); +#else + mp_msg(MSGT_OPEN,MSGL_V,"[file] File size is %u bytes\n", (unsigned int)len); +#endif + + stream->fd = f; + stream->fill_buffer = fill_buffer; + stream->write_buffer = write_buffer; + + m_struct_free(&stream_opts,opts); + return STREAM_OK; +} + +stream_info_t stream_info_file = { + "File", + "file", + "Albeu", + "based on the code from ??? (probably Arpi)", + open_f, + { "file", "", NULL }, + &stream_opts, + 1 // Urls are an option string +};