summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authoralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-04-02 16:25:07 +0000
committeralbeu <albeu@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-04-02 16:25:07 +0000
commit9533d5ea3ac5867127ca1f68b7823605e7cfeb65 (patch)
tree0b52b8b748f4fd9fc1c9ce8ee5fae9058a5bce97 /libmpdemux
parente2d93b4aa72a4d55deb67ad9cc2bf7dccb7a3372 (diff)
downloadmpv-9533d5ea3ac5867127ca1f68b7823605e7cfeb65.tar.bz2
mpv-9533d5ea3ac5867127ca1f68b7823605e7cfeb65.tar.xz
Stream modularization, the first step.
Only file stream are converted atm, other will come later. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9795 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/stream.c139
-rw-r--r--libmpdemux/stream.h55
-rw-r--r--libmpdemux/stream_file.c136
3 files changed, 318 insertions, 12 deletions
diff --git a/libmpdemux/stream.c b/libmpdemux/stream.c
index f89a5afd52..bd1d641a1a 100644
--- a/libmpdemux/stream.c
+++ b/libmpdemux/stream.c
@@ -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 @@ void close_cdda(stream_t* s);
#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 @@ int stream_fill_buffer(stream_t *s){
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 @@ int stream_fill_buffer(stream_t *s){
- 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 @@ off_t newpos=0;
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 @@ off_t newpos=0;
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(verbose>=3){
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 @@ if(newpos==0 || newpos!=s->pos){
#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 @@ void free_stream(stream_t *s){
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 --git a/libmpdemux/stream.h b/libmpdemux/stream.h
index 8931567e38..84d89d71fb 100644
--- a/libmpdemux/stream.h
+++ b/libmpdemux/stream.h
@@ -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 @@ void stream_reset(stream_t *s);
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 --git a/libmpdemux/stream_file.c b/libmpdemux/stream_file.c
new file mode 100644
index 0000000000..f399a659ba
--- /dev/null
+++ b/libmpdemux/stream_file.c
@@ -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
+};