ad_ffmpeg: pass packet side data from libavformat
[mplayer.git] / stream / stream_file.c
blob6d436cf6f540946f2bae6ac8e6870d83bb21b5ed
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "config.h"
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <unistd.h>
27 #include "mp_msg.h"
28 #include "stream.h"
29 #include "m_option.h"
30 #include "m_struct.h"
32 static struct stream_priv_s {
33 char* filename;
34 char *filename2;
35 } stream_priv_dflts = {
36 NULL, NULL
39 #define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
40 /// URL definition
41 static const m_option_t stream_opts_fields[] = {
42 {"string", ST_OFF(filename), CONF_TYPE_STRING, 0, 0 ,0, NULL},
43 {"filename", ST_OFF(filename2), CONF_TYPE_STRING, 0, 0 ,0, NULL},
44 { NULL, NULL, 0, 0, 0, 0, NULL }
46 static const struct m_struct_st stream_opts = {
47 "file",
48 sizeof(struct stream_priv_s),
49 &stream_priv_dflts,
50 stream_opts_fields
53 static int fill_buffer(stream_t *s, char* buffer, int max_len){
54 int r = read(s->fd,buffer,max_len);
55 return (r <= 0) ? -1 : r;
58 static int write_buffer(stream_t *s, char* buffer, int len) {
59 int r;
60 int wr = 0;
61 while (wr < len) {
62 r = write(s->fd,buffer,len);
63 if (r <= 0)
64 return -1;
65 wr += r;
66 buffer += r;
68 return len;
71 static int seek(stream_t *s,off_t newpos) {
72 s->pos = newpos;
73 if(lseek(s->fd,s->pos,SEEK_SET)<0) {
74 s->eof=1;
75 return 0;
77 return 1;
80 static int seek_forward(stream_t *s,off_t newpos) {
81 if(newpos<s->pos){
82 mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n");
83 return 0;
85 while(s->pos<newpos){
86 int len=s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE);
87 if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; break; } // EOF
88 s->buf_pos=0;
89 s->buf_len=len;
90 s->pos+=len;
92 return 1;
95 static int control(stream_t *s, int cmd, void *arg) {
96 switch(cmd) {
97 case STREAM_CTRL_GET_SIZE: {
98 off_t size;
100 size = lseek(s->fd, 0, SEEK_END);
101 lseek(s->fd, s->pos, SEEK_SET);
102 if(size != (off_t)-1) {
103 *((off_t*)arg) = size;
104 return 1;
108 return STREAM_UNSUPPORTED;
111 static int open_f(stream_t *stream,int mode, void* opts, int* file_format) {
112 int f;
113 mode_t m = 0;
114 off_t len;
115 unsigned char *filename;
116 struct stream_priv_s* p = (struct stream_priv_s*)opts;
118 if(mode == STREAM_READ)
119 m = O_RDONLY;
120 else if(mode == STREAM_WRITE)
121 m = O_RDWR|O_CREAT|O_TRUNC;
122 else {
123 mp_msg(MSGT_OPEN,MSGL_ERR, "[file] Unknown open mode %d\n",mode);
124 m_struct_free(&stream_opts,opts);
125 return STREAM_UNSUPPORTED;
128 if(p->filename)
129 filename = p->filename;
130 else if(p->filename2)
131 filename = p->filename2;
132 else
133 filename = NULL;
134 if(!filename) {
135 mp_msg(MSGT_OPEN,MSGL_ERR, "[file] No filename\n");
136 m_struct_free(&stream_opts,opts);
137 return STREAM_ERROR;
140 #if HAVE_DOS_PATHS
141 // extract '/' from '/x:/path'
142 if( filename[ 0 ] == '/' && filename[ 1 ] && filename[ 2 ] == ':' )
143 filename++;
144 #endif
146 m |= O_BINARY;
148 if(!strcmp(filename,"-")){
149 if(mode == STREAM_READ) {
150 // read from stdin
151 mp_tmsg(MSGT_OPEN,MSGL_INFO,"Reading from stdin...\n");
152 f=0; // 0=stdin
153 #if HAVE_SETMODE
154 setmode(fileno(stdin),O_BINARY);
155 #endif
156 } else {
157 mp_msg(MSGT_OPEN,MSGL_INFO,"Writing to stdout\n");
158 f=1;
159 #if HAVE_SETMODE
160 setmode(fileno(stdout),O_BINARY);
161 #endif
163 } else {
164 mode_t openmode = S_IRUSR|S_IWUSR;
165 #ifndef __MINGW32__
166 openmode |= S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
167 #endif
168 f=open(filename,m, openmode);
169 if(f<0) {
170 mp_tmsg(MSGT_OPEN,MSGL_ERR,"File not found: '%s'\n",filename);
171 m_struct_free(&stream_opts,opts);
172 return STREAM_ERROR;
176 len=lseek(f,0,SEEK_END); lseek(f,0,SEEK_SET);
177 #ifdef __MINGW32__
178 // seeks on stdin incorrectly succeed on MinGW
179 if(f==0)
180 len = -1;
181 #endif
182 if(len == -1) {
183 if(mode == STREAM_READ) stream->seek = seek_forward;
184 stream->type = STREAMTYPE_STREAM; // Must be move to STREAMTYPE_FILE
185 stream->flags |= MP_STREAM_SEEK_FW;
186 } else if(len >= 0) {
187 stream->seek = seek;
188 stream->end_pos = len;
189 stream->type = STREAMTYPE_FILE;
192 mp_msg(MSGT_OPEN,MSGL_V,"[file] File size is %"PRId64" bytes\n", (int64_t)len);
194 stream->fd = f;
195 stream->fill_buffer = fill_buffer;
196 stream->write_buffer = write_buffer;
197 stream->control = control;
198 stream->read_chunk = 64*1024;
200 m_struct_free(&stream_opts,opts);
201 return STREAM_OK;
204 const stream_info_t stream_info_file = {
205 "File",
206 "file",
207 "Albeu",
208 "based on the code from ??? (probably Arpi)",
209 open_f,
210 { "file", "", NULL },
211 &stream_opts,
212 1 // Urls are an option string