Mercurial > mplayer.hg
view stream/stream_file.c @ 36855:5cee3aefde4f
Fix previous sync error
author | jrash |
---|---|
date | Wed, 26 Feb 2014 21:57:48 +0000 |
parents | cb25e73ac822 |
children |
line wrap: on
line source
/* * This file is part of MPlayer. * * MPlayer 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. * * MPlayer 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 MPlayer; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #if HAVE_SETMODE #include <io.h> #endif #ifdef __MINGW32__ #include <windows.h> #include <share.h> #endif #include "mp_msg.h" #include "stream.h" #include "help_mp.h" #include "m_option.h" #include "m_struct.h" #include "osdep/osdep.h" #include "libmpdemux/demuxer.h" static struct stream_priv_s { char* filename; char *filename2; } stream_priv_dflts = { NULL, NULL }; #define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f) /// URL definition static const m_option_t stream_opts_fields[] = { {"string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL}, {"filename", ST_OFF(filename2), CONF_TYPE_STRING, 0, 0 ,0, NULL}, { NULL, NULL, 0, 0, 0, 0, NULL } }; static const 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); // We are certain this is EOF, do not retry if (max_len && r == 0) s->eof = 1; return (r <= 0) ? -1 : r; } static int write_buffer(stream_t *s, char* buffer, int len) { int r; int wr = 0; while (wr < len) { r = write(s->fd,buffer,len); if (r <= 0) return -1; wr += r; buffer += r; } return len; } static int seek(stream_t *s, int64_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, int64_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){ int len=s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE); if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; break; } // EOF s->buf_pos=0; s->buf_len=len; s->pos+=len; } return 1; } static int control(stream_t *s, int cmd, void *arg) { switch(cmd) { case STREAM_CTRL_GET_SIZE: { off_t size; size = lseek(s->fd, 0, SEEK_END); lseek(s->fd, s->pos, SEEK_SET); if(size != (off_t)-1) { *(uint64_t*)arg = size; return 1; } } } return STREAM_UNSUPPORTED; } #ifdef __MINGW32__ static int win32_open(const char *fname, int m, int omode) { int cnt; int fd = -1; wchar_t fname_w[MAX_PATH]; int WINAPI (*mb2wc)(UINT, DWORD, LPCSTR, int, LPWSTR, int) = NULL; HMODULE kernel32 = GetModuleHandle("Kernel32.dll"); if (!kernel32) goto fallback; mb2wc = GetProcAddress(kernel32, "MultiByteToWideChar"); if (!mb2wc) goto fallback; cnt = mb2wc(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, fname_w, sizeof(fname_w) / sizeof(*fname_w)); if (cnt <= 0) goto fallback; fd = _wsopen(fname_w, m, SH_DENYNO, omode); if (fd != -1 || (m & O_CREAT)) return fd; fallback: return _sopen(fname, m, SH_DENYNO, omode); } #endif static int open_f(stream_t *stream,int mode, void* opts, int* file_format) { int f; mode_t m = 0; int64_t len; unsigned char *filename; struct stream_priv_s* p = (struct stream_priv_s*)opts; if(mode == STREAM_READ) m = O_RDONLY; else if(mode == STREAM_WRITE) m = O_RDWR|O_CREAT|O_TRUNC; else { mp_msg(MSGT_OPEN,MSGL_ERR, "[file] Unknown open mode %d\n",mode); m_struct_free(&stream_opts,opts); return STREAM_UNSUPPORTED; } if(p->filename) filename = p->filename; else if(p->filename2) filename = p->filename2; else filename = NULL; if(!filename) { mp_msg(MSGT_OPEN,MSGL_ERR, "[file] No filename\n"); m_struct_free(&stream_opts,opts); return STREAM_ERROR; } #if HAVE_DOS_PATHS // extract '/' from '/x:/path' if( filename[ 0 ] == '/' && filename[ 1 ] && filename[ 2 ] == ':' ) filename++; #endif m |= O_BINARY; if(!strcmp(filename,"-")){ if(mode == STREAM_READ) { // read from stdin mp_msg(MSGT_OPEN,MSGL_INFO,MSGTR_ReadSTDIN); f=0; // 0=stdin #if HAVE_SETMODE setmode(fileno(stdin),O_BINARY); #endif } else { mp_msg(MSGT_OPEN,MSGL_INFO,"Writing to stdout\n"); f=1; #if HAVE_SETMODE setmode(fileno(stdout),O_BINARY); #endif } } else { mode_t openmode = S_IRUSR|S_IWUSR; #ifdef __MINGW32__ f = win32_open(filename, m, openmode); #else openmode |= S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; f=open(filename,m, openmode); #endif if(f<0) { mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_FileNotFound,filename); m_struct_free(&stream_opts,opts); return STREAM_ERROR; } } len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET); #ifdef __MINGW32__ // seeks on stdin incorrectly succeed on MinGW if(f==0) len = -1; #endif if(len == -1) { if(mode == STREAM_READ) stream->seek = seek_forward; stream->type = STREAMTYPE_STREAM; // Must be move to STREAMTYPE_FILE stream->flags |= MP_STREAM_SEEK_FW; } else if(len >= 0) { stream->seek = seek; stream->end_pos = len; stream->type = STREAMTYPE_FILE; } // support sdp:// also via FFmpeg if live555 was not compiled in if (stream->url && !strncmp(stream->url, "sdp://", 6)) { *file_format = DEMUXER_TYPE_LAVF; stream->type = STREAMTYPE_SDP; stream->flags = STREAM_NON_CACHEABLE; } mp_msg(MSGT_OPEN,MSGL_V,"[file] File size is %"PRId64" bytes\n", (int64_t)len); stream->fd = f; stream->fill_buffer = fill_buffer; stream->write_buffer = write_buffer; stream->control = control; stream->read_chunk = 64*1024; m_struct_free(&stream_opts,opts); return STREAM_OK; } const stream_info_t stream_info_file = { "File", "file", "Albeu", "based on the code from ??? (probably Arpi)", open_f, { "file", "", "sdp", NULL }, &stream_opts, 1 // Urls are an option string };