Mercurial > mplayer.hg
comparison stream/stream.c @ 19271:64d82a45a05d
introduce new 'stream' directory for all stream layer related components and split them from libmpdemux
author | ben |
---|---|
date | Mon, 31 Jul 2006 17:39:17 +0000 |
parents | libmpdemux/stream.c@73b8f5ff772d |
children | 11ec1cb3a7ea |
comparison
equal
deleted
inserted
replaced
19270:7d39b911f0bd | 19271:64d82a45a05d |
---|---|
1 | |
2 #include <stdio.h> | |
3 #include <stdlib.h> | |
4 #include <unistd.h> | |
5 | |
6 #include <sys/types.h> | |
7 #include <sys/stat.h> | |
8 #ifndef __MINGW32__ | |
9 #include <sys/ioctl.h> | |
10 #include <sys/wait.h> | |
11 #endif | |
12 #include <fcntl.h> | |
13 #include <signal.h> | |
14 #include <strings.h> | |
15 | |
16 #include "config.h" | |
17 | |
18 #ifndef HAVE_WINSOCK2 | |
19 #define closesocket close | |
20 #else | |
21 #include <winsock2.h> | |
22 #endif | |
23 | |
24 #include "mp_msg.h" | |
25 #include "help_mp.h" | |
26 #include "osdep/shmem.h" | |
27 | |
28 #include "stream.h" | |
29 #include "demuxer.h" | |
30 | |
31 #include "m_option.h" | |
32 #include "m_struct.h" | |
33 | |
34 | |
35 void cache_uninit(stream_t *s); // defined in cache2.c | |
36 | |
37 //#include "vcd_read_bincue.h" | |
38 | |
39 #ifdef HAVE_VCD | |
40 extern stream_info_t stream_info_vcd; | |
41 #endif | |
42 #ifdef HAVE_CDDA | |
43 extern stream_info_t stream_info_cdda; | |
44 #endif | |
45 #ifdef MPLAYER_NETWORK | |
46 extern stream_info_t stream_info_netstream; | |
47 extern stream_info_t stream_info_pnm; | |
48 extern stream_info_t stream_info_asf; | |
49 extern stream_info_t stream_info_rtsp; | |
50 extern stream_info_t stream_info_rtp_udp; | |
51 extern stream_info_t stream_info_http1; | |
52 extern stream_info_t stream_info_http2; | |
53 #endif | |
54 #ifdef HAS_DVBIN_SUPPORT | |
55 extern stream_info_t stream_info_dvb; | |
56 #endif | |
57 #ifdef HAVE_PVR | |
58 extern stream_info_t stream_info_pvr; | |
59 #endif | |
60 #ifdef HAVE_FTP | |
61 extern stream_info_t stream_info_ftp; | |
62 #endif | |
63 #ifdef HAVE_VSTREAM | |
64 extern stream_info_t stream_info_vstream; | |
65 #endif | |
66 #ifdef USE_DVDNAV | |
67 extern stream_info_t stream_info_dvdnav; | |
68 #endif | |
69 #ifdef LIBSMBCLIENT | |
70 extern stream_info_t stream_info_smb; | |
71 #endif | |
72 #ifdef STREAMING_LIVE555 | |
73 extern stream_info_t stream_info_sdp; | |
74 extern stream_info_t stream_info_rtsp_sip; | |
75 #endif | |
76 | |
77 extern stream_info_t stream_info_cue; | |
78 extern stream_info_t stream_info_null; | |
79 extern stream_info_t stream_info_file; | |
80 #ifdef HAVE_DVD | |
81 extern stream_info_t stream_info_dvd; | |
82 #endif | |
83 | |
84 stream_info_t* auto_open_streams[] = { | |
85 #ifdef HAVE_VCD | |
86 &stream_info_vcd, | |
87 #endif | |
88 #ifdef HAVE_CDDA | |
89 &stream_info_cdda, | |
90 #endif | |
91 #ifdef MPLAYER_NETWORK | |
92 &stream_info_netstream, | |
93 &stream_info_http1, | |
94 &stream_info_asf, | |
95 &stream_info_pnm, | |
96 &stream_info_rtsp, | |
97 #ifdef STREAMING_LIVE555 | |
98 &stream_info_sdp, | |
99 &stream_info_rtsp_sip, | |
100 #endif | |
101 &stream_info_rtp_udp, | |
102 &stream_info_http2, | |
103 #endif | |
104 #ifdef HAS_DVBIN_SUPPORT | |
105 &stream_info_dvb, | |
106 #endif | |
107 #ifdef HAVE_PVR | |
108 &stream_info_pvr, | |
109 #endif | |
110 #ifdef HAVE_FTP | |
111 &stream_info_ftp, | |
112 #endif | |
113 #ifdef HAVE_VSTREAM | |
114 &stream_info_vstream, | |
115 #endif | |
116 #ifdef LIBSMBCLIENT | |
117 &stream_info_smb, | |
118 #endif | |
119 &stream_info_cue, | |
120 #ifdef HAVE_DVD | |
121 &stream_info_dvd, | |
122 #endif | |
123 #ifdef USE_DVDNAV | |
124 &stream_info_dvdnav, | |
125 #endif | |
126 | |
127 &stream_info_null, | |
128 &stream_info_file, | |
129 NULL | |
130 }; | |
131 | |
132 stream_t* open_stream_plugin(stream_info_t* sinfo,char* filename,int mode, | |
133 char** options, int* file_format, int* ret) { | |
134 void* arg = NULL; | |
135 stream_t* s; | |
136 m_struct_t* desc = (m_struct_t*)sinfo->opts; | |
137 | |
138 // Parse options | |
139 if(desc) { | |
140 arg = m_struct_alloc(desc); | |
141 if(sinfo->opts_url) { | |
142 m_option_t url_opt = | |
143 { "stream url", arg , CONF_TYPE_CUSTOM_URL, 0, 0 ,0, sinfo->opts }; | |
144 if(m_option_parse(&url_opt,"stream url",filename,arg,M_CONFIG_FILE) < 0) { | |
145 mp_msg(MSGT_OPEN,MSGL_ERR, "URL parsing failed on url %s\n",filename); | |
146 m_struct_free(desc,arg); | |
147 return NULL; | |
148 } | |
149 } | |
150 if(options) { | |
151 int i; | |
152 for(i = 0 ; options[i] != NULL ; i += 2) { | |
153 mp_msg(MSGT_OPEN,MSGL_DBG2, "Set stream arg %s=%s\n", | |
154 options[i],options[i+1]); | |
155 if(!m_struct_set(desc,arg,options[i],options[i+1])) | |
156 mp_msg(MSGT_OPEN,MSGL_WARN, "Failed to set stream option %s=%s\n", | |
157 options[i],options[i+1]); | |
158 } | |
159 } | |
160 } | |
161 s = new_stream(-2,-2); | |
162 s->url=strdup(filename); | |
163 s->flags |= mode; | |
164 *ret = sinfo->open(s,mode,arg,file_format); | |
165 if((*ret) != STREAM_OK) { | |
166 free(s->url); | |
167 free(s); | |
168 return NULL; | |
169 } | |
170 if(s->type <= -2) | |
171 mp_msg(MSGT_OPEN,MSGL_WARN, "Warning streams need a type !!!!\n"); | |
172 if(s->flags & STREAM_SEEK && !s->seek) | |
173 s->flags &= ~STREAM_SEEK; | |
174 if(s->seek && !(s->flags & STREAM_SEEK)) | |
175 s->flags |= STREAM_SEEK; | |
176 | |
177 | |
178 mp_msg(MSGT_OPEN,MSGL_V, "STREAM: [%s] %s\n",sinfo->name,filename); | |
179 mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Description: %s\n",sinfo->info); | |
180 mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Author: %s\n", sinfo->author); | |
181 mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Comment: %s\n", sinfo->comment); | |
182 | |
183 return s; | |
184 } | |
185 | |
186 | |
187 stream_t* open_stream_full(char* filename,int mode, char** options, int* file_format) { | |
188 int i,j,l,r; | |
189 stream_info_t* sinfo; | |
190 stream_t* s; | |
191 | |
192 for(i = 0 ; auto_open_streams[i] ; i++) { | |
193 sinfo = auto_open_streams[i]; | |
194 if(!sinfo->protocols) { | |
195 mp_msg(MSGT_OPEN,MSGL_WARN, "Stream type %s has protocols == NULL, it's a bug\n", sinfo->name); | |
196 continue; | |
197 } | |
198 for(j = 0 ; sinfo->protocols[j] ; j++) { | |
199 l = strlen(sinfo->protocols[j]); | |
200 // l == 0 => Don't do protocol matching (ie network and filenames) | |
201 if((l == 0) || ((strncmp(sinfo->protocols[j],filename,l) == 0) && | |
202 (strncmp("://",filename+l,3) == 0))) { | |
203 *file_format = DEMUXER_TYPE_UNKNOWN; | |
204 s = open_stream_plugin(sinfo,filename,mode,options,file_format,&r); | |
205 if(s) return s; | |
206 if(r != STREAM_UNSUPORTED) { | |
207 mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_FailedToOpen,filename); | |
208 return NULL; | |
209 } | |
210 break; | |
211 } | |
212 } | |
213 } | |
214 | |
215 mp_msg(MSGT_OPEN,MSGL_ERR, "No stream found to handle url %s\n",filename); | |
216 return NULL; | |
217 } | |
218 | |
219 //=================== STREAMER ========================= | |
220 | |
221 int stream_fill_buffer(stream_t *s){ | |
222 int len; | |
223 if (/*s->fd == NULL ||*/ s->eof) { s->buf_pos = s->buf_len = 0; return 0; } | |
224 switch(s->type){ | |
225 case STREAMTYPE_STREAM: | |
226 #ifdef MPLAYER_NETWORK | |
227 if( s->streaming_ctrl!=NULL ) { | |
228 len=s->streaming_ctrl->streaming_read(s->fd,s->buffer,STREAM_BUFFER_SIZE, s->streaming_ctrl);break; | |
229 } else { | |
230 len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break; | |
231 } | |
232 #else | |
233 len=read(s->fd,s->buffer,STREAM_BUFFER_SIZE);break; | |
234 #endif | |
235 case STREAMTYPE_DS: | |
236 len = demux_read_data((demux_stream_t*)s->priv,s->buffer,STREAM_BUFFER_SIZE); | |
237 break; | |
238 | |
239 | |
240 default: | |
241 len= s->fill_buffer ? s->fill_buffer(s,s->buffer,STREAM_BUFFER_SIZE) : 0; | |
242 } | |
243 if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; } | |
244 s->buf_pos=0; | |
245 s->buf_len=len; | |
246 s->pos+=len; | |
247 // printf("[%d]",len);fflush(stdout); | |
248 return len; | |
249 } | |
250 | |
251 int stream_seek_long(stream_t *s,off_t pos){ | |
252 off_t newpos=0; | |
253 | |
254 // if( mp_msg_test(MSGT_STREAM,MSGL_DBG3) ) printf("seek_long to 0x%X\n",(unsigned int)pos); | |
255 | |
256 s->buf_pos=s->buf_len=0; | |
257 | |
258 switch(s->type){ | |
259 case STREAMTYPE_STREAM: | |
260 #ifdef _LARGEFILE_SOURCE | |
261 newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break; | |
262 #else | |
263 newpos=pos&(~(STREAM_BUFFER_SIZE-1));break; | |
264 #endif | |
265 default: | |
266 // Round on sector size | |
267 if(s->sector_size) | |
268 newpos=(pos/s->sector_size)*s->sector_size; | |
269 else { // Otherwise on the buffer size | |
270 #ifdef _LARGEFILE_SOURCE | |
271 newpos=pos&(~((long long)STREAM_BUFFER_SIZE-1));break; | |
272 #else | |
273 newpos=pos&(~(STREAM_BUFFER_SIZE-1));break; | |
274 #endif | |
275 } | |
276 break; | |
277 } | |
278 | |
279 if( mp_msg_test(MSGT_STREAM,MSGL_DBG3) ){ | |
280 mp_msg(MSGT_STREAM,MSGL_DBG3, "s->pos=%"PRIX64" newpos=%"PRIX64" new_bufpos=%"PRIX64" buflen=%X \n", | |
281 (int64_t)s->pos,(int64_t)newpos,(int64_t)pos,s->buf_len); | |
282 } | |
283 pos-=newpos; | |
284 | |
285 if(newpos==0 || newpos!=s->pos){ | |
286 switch(s->type){ | |
287 case STREAMTYPE_STREAM: | |
288 //s->pos=newpos; // real seek | |
289 // Some streaming protocol allow to seek backward and forward | |
290 // A function call that return -1 can tell that the protocol | |
291 // doesn't support seeking. | |
292 #ifdef MPLAYER_NETWORK | |
293 if(s->seek) { // new stream seek is much cleaner than streaming_ctrl one | |
294 if(!s->seek(s,newpos)) { | |
295 mp_msg(MSGT_STREAM,MSGL_ERR, "Seek failed\n"); | |
296 return 0; | |
297 } | |
298 break; | |
299 } | |
300 | |
301 if( s->streaming_ctrl!=NULL && s->streaming_ctrl->streaming_seek ) { | |
302 if( s->streaming_ctrl->streaming_seek( s->fd, pos, s->streaming_ctrl )<0 ) { | |
303 mp_msg(MSGT_STREAM,MSGL_INFO,"Stream not seekable!\n"); | |
304 return 1; | |
305 } | |
306 } | |
307 #else | |
308 if(newpos<s->pos){ | |
309 mp_msg(MSGT_STREAM,MSGL_INFO,"Cannot seek backward in linear streams!\n"); | |
310 return 1; | |
311 } | |
312 while(s->pos<newpos){ | |
313 if(stream_fill_buffer(s)<=0) break; // EOF | |
314 } | |
315 #endif | |
316 break; | |
317 default: | |
318 // This should at the beginning as soon as all streams are converted | |
319 if(!s->seek) | |
320 return 0; | |
321 // Now seek | |
322 if(!s->seek(s,newpos)) { | |
323 mp_msg(MSGT_STREAM,MSGL_ERR, "Seek failed\n"); | |
324 return 0; | |
325 } | |
326 } | |
327 // putchar('.');fflush(stdout); | |
328 //} else { | |
329 // putchar('%');fflush(stdout); | |
330 } | |
331 | |
332 while(stream_fill_buffer(s) > 0 && pos >= 0) { | |
333 if(pos<=s->buf_len){ | |
334 s->buf_pos=pos; // byte position in sector | |
335 return 1; | |
336 } | |
337 pos -= s->buf_len; | |
338 } | |
339 | |
340 // if(pos==s->buf_len) printf("XXX Seek to last byte of file -> EOF\n"); | |
341 | |
342 mp_msg(MSGT_STREAM,MSGL_V,"stream_seek: WARNING! Can't seek to 0x%"PRIX64" !\n",(int64_t)(pos+newpos)); | |
343 return 0; | |
344 } | |
345 | |
346 | |
347 void stream_reset(stream_t *s){ | |
348 if(s->eof){ | |
349 s->pos=0; //ftell(f); | |
350 // s->buf_pos=s->buf_len=0; | |
351 s->eof=0; | |
352 } | |
353 if(s->control) s->control(s,STREAM_CTRL_RESET,NULL); | |
354 //stream_seek(s,0); | |
355 } | |
356 | |
357 int stream_control(stream_t *s, int cmd, void *arg){ | |
358 if(!s->control) return STREAM_UNSUPORTED; | |
359 return s->control(s, cmd, arg); | |
360 } | |
361 | |
362 stream_t* new_memory_stream(unsigned char* data,int len){ | |
363 stream_t *s; | |
364 | |
365 if(len < 0) | |
366 return NULL; | |
367 s=malloc(sizeof(stream_t)+len); | |
368 memset(s,0,sizeof(stream_t)); | |
369 s->fd=-1; | |
370 s->type=STREAMTYPE_MEMORY; | |
371 s->buf_pos=0; s->buf_len=len; | |
372 s->start_pos=0; s->end_pos=len; | |
373 stream_reset(s); | |
374 s->pos=len; | |
375 memcpy(s->buffer,data,len); | |
376 return s; | |
377 } | |
378 | |
379 stream_t* new_stream(int fd,int type){ | |
380 stream_t *s=malloc(sizeof(stream_t)); | |
381 if(s==NULL) return NULL; | |
382 memset(s,0,sizeof(stream_t)); | |
383 | |
384 #ifdef HAVE_WINSOCK2 | |
385 { | |
386 WSADATA wsdata; | |
387 int temp = WSAStartup(0x0202, &wsdata); // there might be a better place for this (-> later) | |
388 mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 init: %i\n", temp); | |
389 } | |
390 #endif | |
391 | |
392 s->fd=fd; | |
393 s->type=type; | |
394 s->buf_pos=s->buf_len=0; | |
395 s->start_pos=s->end_pos=0; | |
396 s->priv=NULL; | |
397 s->url=NULL; | |
398 s->cache_pid=0; | |
399 stream_reset(s); | |
400 return s; | |
401 } | |
402 | |
403 void free_stream(stream_t *s){ | |
404 // printf("\n*** free_stream() called ***\n"); | |
405 #ifdef USE_STREAM_CACHE | |
406 if(s->cache_pid) { | |
407 cache_uninit(s); | |
408 } | |
409 #endif | |
410 if(s->close) s->close(s); | |
411 if(s->fd>0){ | |
412 /* on unix we define closesocket to close | |
413 on windows however we have to distinguish between | |
414 network socket and file */ | |
415 if(s->url && strstr(s->url,"://")) | |
416 closesocket(s->fd); | |
417 else close(s->fd); | |
418 } | |
419 #ifdef HAVE_WINSOCK2 | |
420 mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 uninit\n"); | |
421 WSACleanup(); // there might be a better place for this (-> later) | |
422 #endif | |
423 // Disabled atm, i don't like that. s->priv can be anything after all | |
424 // streams should destroy their priv on close | |
425 //if(s->priv) free(s->priv); | |
426 if(s->url) free(s->url); | |
427 free(s); | |
428 } | |
429 | |
430 stream_t* new_ds_stream(demux_stream_t *ds) { | |
431 stream_t* s = new_stream(-1,STREAMTYPE_DS); | |
432 s->priv = ds; | |
433 return s; | |
434 } |