changeset 9794:f67d87b2d3c7

Stream modularization, the first step. Only file stream are converted atm, other will come later.
author albeu
date Wed, 02 Apr 2003 16:25:07 +0000
parents b2bf632d37b5
children 20f8944a6e0c
files libmpdemux/stream.c libmpdemux/stream.h libmpdemux/stream_file.c
diffstat 3 files changed, 318 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- 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 <sys/wait.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <strings.h>
 
 #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);
 }
 
--- 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;
--- /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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#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(newpos<s->pos){
+    mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n");
+    return 0;
+  }
+  while(s->pos<newpos){
+    if(s->fill_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
+};