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.
23 #include <sys/types.h>
26 #include <sys/ioctl.h>
33 #include <libavutil/intreadwrite.h>
34 #include <libavutil/common.h>
45 #include "osdep/shmem.h"
46 #include "osdep/timer.h"
49 #include "libmpdemux/demuxer.h"
57 char* cdrom_device
=NULL
;
58 char* dvd_device
=NULL
;
62 static int (*stream_check_interrupt_cb
)(struct input_ctx
*ctx
, int time
);
63 static struct input_ctx
*stream_check_interrupt_ctx
;
65 extern const stream_info_t stream_info_vcd
;
66 extern const stream_info_t stream_info_cdda
;
67 extern const stream_info_t stream_info_pnm
;
68 extern const stream_info_t stream_info_asf
;
69 extern const stream_info_t stream_info_rtp
;
70 extern const stream_info_t stream_info_udp
;
71 extern const stream_info_t stream_info_http1
;
72 extern const stream_info_t stream_info_http2
;
73 extern const stream_info_t stream_info_dvb
;
74 extern const stream_info_t stream_info_tv
;
75 extern const stream_info_t stream_info_radio
;
76 extern const stream_info_t stream_info_pvr
;
77 extern const stream_info_t stream_info_ftp
;
78 extern const stream_info_t stream_info_vstream
;
79 extern const stream_info_t stream_info_dvdnav
;
80 extern const stream_info_t stream_info_smb
;
82 extern const stream_info_t stream_info_cue
;
83 extern const stream_info_t stream_info_null
;
84 extern const stream_info_t stream_info_mf
;
85 extern const stream_info_t stream_info_ffmpeg
;
86 extern const stream_info_t stream_info_file
;
87 extern const stream_info_t stream_info_ifo
;
88 extern const stream_info_t stream_info_dvd
;
89 extern const stream_info_t stream_info_bluray
;
91 static const stream_info_t
* const auto_open_streams
[] = {
98 &stream_info_ffmpeg
, // use for rstp:// before http fallback
99 #ifdef CONFIG_NETWORKING
122 #ifdef CONFIG_VSTREAM
123 &stream_info_vstream
,
125 #ifdef CONFIG_LIBSMBCLIENT
129 #ifdef CONFIG_DVDREAD
136 #ifdef CONFIG_LIBBLURAY
146 static stream_t
*open_stream_plugin(const stream_info_t
*sinfo
,
147 const char *filename
,
148 int mode
, struct MPOpts
*options
,
149 int *file_format
, int *ret
,
150 char **redirected_url
)
154 m_struct_t
* desc
= (m_struct_t
*)sinfo
->opts
;
158 arg
= m_struct_alloc(desc
);
159 if(sinfo
->opts_url
) {
161 { "stream url", arg
, CONF_TYPE_CUSTOM_URL
, 0, 0 ,0, (void *)sinfo
->opts
};
162 if (m_option_parse(&url_opt
, bstr("stream url"), bstr(filename
), false, arg
) < 0) {
163 mp_tmsg(MSGT_OPEN
,MSGL_ERR
, "URL parsing failed on url %s\n",filename
);
164 m_struct_free(desc
,arg
);
169 s
= new_stream(-2,-2);
171 s
->url
=strdup(filename
);
173 *ret
= sinfo
->open(s
,mode
,arg
,file_format
);
174 if((*ret
) != STREAM_OK
) {
175 #ifdef CONFIG_NETWORKING
176 if (*ret
== STREAM_REDIRECTED
&& redirected_url
) {
177 if (s
->streaming_ctrl
&& s
->streaming_ctrl
->url
178 && s
->streaming_ctrl
->url
->url
)
179 *redirected_url
= strdup(s
->streaming_ctrl
->url
->url
);
181 *redirected_url
= NULL
;
183 streaming_ctrl_free(s
->streaming_ctrl
);
191 if (s
->streaming_ctrl
&& s
->streaming_ctrl
->buffering
) {
192 // Set default cache size to use if user does not specify it.
193 // buffer in KBytes, *5 assuming the prefill is 20% of the buffer.
194 s
->cache_size
= s
->streaming_ctrl
->prebuffer_size
/ 1024 * 5;
195 if (s
->cache_size
< 64)
200 mp_msg(MSGT_OPEN
,MSGL_WARN
, "Warning streams need a type !!!!\n");
201 if(s
->flags
& MP_STREAM_SEEK
&& !s
->seek
)
202 s
->flags
&= ~MP_STREAM_SEEK
;
203 if(s
->seek
&& !(s
->flags
& MP_STREAM_SEEK
))
204 s
->flags
|= MP_STREAM_SEEK
;
208 mp_msg(MSGT_OPEN
,MSGL_V
, "STREAM: [%s] %s\n",sinfo
->name
,filename
);
209 mp_msg(MSGT_OPEN
,MSGL_V
, "STREAM: Description: %s\n",sinfo
->info
);
210 mp_msg(MSGT_OPEN
,MSGL_V
, "STREAM: Author: %s\n", sinfo
->author
);
211 mp_msg(MSGT_OPEN
,MSGL_V
, "STREAM: Comment: %s\n", sinfo
->comment
);
217 static stream_t
*open_stream_full(const char *filename
, int mode
,
218 struct MPOpts
*options
, int *file_format
)
221 const stream_info_t
* sinfo
;
223 char *redirected_url
= NULL
;
225 for(i
= 0 ; auto_open_streams
[i
] ; i
++) {
226 sinfo
= auto_open_streams
[i
];
227 if(!sinfo
->protocols
) {
228 mp_msg(MSGT_OPEN
,MSGL_WARN
, "Stream type %s has protocols == NULL, it's a bug\n", sinfo
->name
);
231 for(j
= 0 ; sinfo
->protocols
[j
] ; j
++) {
232 l
= strlen(sinfo
->protocols
[j
]);
233 // l == 0 => Don't do protocol matching (ie network and filenames)
234 if((l
== 0 && !strstr(filename
, "://")) ||
235 ((strncasecmp(sinfo
->protocols
[j
],filename
,l
) == 0) &&
236 (strncmp("://",filename
+l
,3) == 0))) {
237 *file_format
= DEMUXER_TYPE_UNKNOWN
;
238 s
= open_stream_plugin(sinfo
,filename
,mode
,options
,file_format
,&r
,
241 if(r
== STREAM_REDIRECTED
&& redirected_url
) {
242 mp_msg(MSGT_OPEN
,MSGL_V
, "[%s] open %s redirected to %s\n",
243 sinfo
->info
, filename
, redirected_url
);
244 s
= open_stream_full(redirected_url
, mode
, options
, file_format
);
245 free(redirected_url
);
248 else if(r
!= STREAM_UNSUPPORTED
) {
249 mp_tmsg(MSGT_OPEN
,MSGL_ERR
, "Failed to open %s.\n",filename
);
257 mp_tmsg(MSGT_OPEN
,MSGL_ERR
, "No stream found to handle url %s\n", filename
);
261 stream_t
*open_stream(const char *filename
, struct MPOpts
*options
,
265 file_format
= &(int){DEMUXER_TYPE_UNKNOWN
};
266 if (*file_format
!= DEMUXER_TYPE_PLAYLIST
)
267 *file_format
= DEMUXER_TYPE_UNKNOWN
;
269 return open_stream_full(filename
, STREAM_READ
, options
, file_format
);
272 stream_t
*open_output_stream(const char *filename
, struct MPOpts
*options
)
274 int file_format
; //unused
276 mp_msg(MSGT_OPEN
,MSGL_ERR
,"open_output_stream(), NULL filename, report this bug\n");
280 return open_stream_full(filename
,STREAM_WRITE
,options
,&file_format
);
283 //=================== STREAMER =========================
285 void stream_capture_do(stream_t
*s
)
287 if (fwrite(s
->buffer
, s
->buf_len
, 1, s
->capture_file
) < 1) {
288 mp_tmsg(MSGT_GLOBAL
, MSGL_ERR
, "Error writing capture file: %s\n",
290 fclose(s
->capture_file
);
291 s
->capture_file
= NULL
;
295 int stream_read_internal(stream_t
*s
, void *buf
, int len
)
298 // we will retry even if we already reached EOF previously.
300 case STREAMTYPE_STREAM
:
301 #ifdef CONFIG_NETWORKING
302 if( s
->streaming_ctrl
!=NULL
&& s
->streaming_ctrl
->streaming_read
) {
303 len
=s
->streaming_ctrl
->streaming_read(s
->fd
, buf
, len
, s
->streaming_ctrl
);
304 if (s
->streaming_ctrl
->status
== streaming_stopped_e
)
309 len
= s
->fill_buffer(s
, buf
, len
);
311 len
= read(s
->fd
, buf
, len
);
314 len
= demux_read_data((demux_stream_t
*)s
->priv
, buf
, len
);
319 len
= s
->fill_buffer
? s
->fill_buffer(s
, buf
, len
) : 0;
323 // do not retry if this looks like proper eof
324 if (s
->eof
|| (s
->end_pos
&& pos
== s
->end_pos
))
326 // dvdnav has some horrible hacks to "suspend" reads,
327 // we need to skip this code or seeks will hang.
328 if (s
->type
== STREAMTYPE_DVDNAV
)
331 // just in case this is an error e.g. due to network
332 // timeout reset and retry
333 // Seeking is used as a hack to make network streams
334 // reopen the connection, ideally they would implement
335 // e.g. a STREAM_CTRL_RECONNECT to do this
338 if (stream_seek_internal(s
, pos
) >= 0 || s
->pos
!= pos
) // seek failed
340 // make sure EOF is set to ensure no endless loops
342 return stream_read_internal(s
, buf
, orig_len
);
348 // When reading succeeded we are obviously not at eof.
349 // This e.g. avoids issues with eof getting stuck when lavf seeks in MPEG-TS
355 int stream_fill_buffer(stream_t
*s
){
356 int len
= stream_read_internal(s
, s
->buffer
, STREAM_BUFFER_SIZE
);
361 // printf("[%d]",len);fflush(stdout);
363 stream_capture_do(s
);
367 int stream_write_buffer(stream_t
*s
, unsigned char *buf
, int len
) {
371 rd
= s
->write_buffer(s
, buf
, len
);
375 assert(rd
== len
&& "stream_write_buffer(): unexpected short write");
379 int stream_seek_internal(stream_t
*s
, off_t newpos
)
381 if(newpos
==0 || newpos
!=s
->pos
){
383 case STREAMTYPE_STREAM
:
384 //s->pos=newpos; // real seek
385 // Some streaming protocol allow to seek backward and forward
386 // A function call that return -1 can tell that the protocol
387 // doesn't support seeking.
388 #ifdef CONFIG_NETWORKING
389 if(s
->seek
) { // new stream seek is much cleaner than streaming_ctrl one
390 if(!s
->seek(s
,newpos
)) {
391 mp_tmsg(MSGT_STREAM
,MSGL_ERR
, "Seek failed\n");
397 if( s
->streaming_ctrl
!=NULL
&& s
->streaming_ctrl
->streaming_seek
) {
398 if( s
->streaming_ctrl
->streaming_seek( s
->fd
, newpos
, s
->streaming_ctrl
)<0 ) {
399 mp_tmsg(MSGT_STREAM
,MSGL_INFO
,"Stream not seekable!\n");
406 mp_tmsg(MSGT_STREAM
, MSGL_INFO
,
407 "Cannot seek backward in linear streams!\n");
412 // This should at the beginning as soon as all streams are converted
416 if(!s
->seek(s
,newpos
)) {
417 mp_tmsg(MSGT_STREAM
,MSGL_ERR
, "Seek failed\n");
421 // putchar('.');fflush(stdout);
423 // putchar('%');fflush(stdout);
428 int stream_seek_long(stream_t
*s
,off_t pos
){
432 // if( mp_msg_test(MSGT_STREAM,MSGL_DBG3) ) printf("seek_long to 0x%X\n",(unsigned int)pos);
434 s
->buf_pos
=s
->buf_len
=0;
436 if(s
->mode
== STREAM_WRITE
) {
437 if(!s
->seek
|| !s
->seek(s
,pos
))
443 newpos
= (pos
/s
->sector_size
)*s
->sector_size
;
445 newpos
= pos
&(~((off_t
)STREAM_BUFFER_SIZE
-1));
447 if( mp_msg_test(MSGT_STREAM
,MSGL_DBG3
) ){
448 mp_msg(MSGT_STREAM
,MSGL_DBG3
, "s->pos=%"PRIX64
" newpos=%"PRIX64
" new_bufpos=%"PRIX64
" buflen=%X \n",
449 (int64_t)s
->pos
,(int64_t)newpos
,(int64_t)pos
,s
->buf_len
);
453 res
= stream_seek_internal(s
, newpos
);
457 while(s
->pos
<newpos
){
458 if(stream_fill_buffer(s
)<=0) break; // EOF
461 s
->eof
= 0; // EOF reset when seek succeeds.
462 while (stream_fill_buffer(s
) > 0) {
464 s
->buf_pos
=pos
; // byte position in sector
469 // Fill failed, but seek still is a success.
474 mp_msg(MSGT_STREAM
,MSGL_V
,
475 "stream_seek: Seek to/past EOF: no buffer preloaded.\n");
480 void stream_reset(stream_t
*s
){
483 s
->buf_pos
=s
->buf_len
=0;
486 if(s
->control
) s
->control(s
,STREAM_CTRL_RESET
,NULL
);
490 int stream_control(stream_t
*s
, int cmd
, void *arg
){
491 if(!s
->control
) return STREAM_UNSUPPORTED
;
492 #ifdef CONFIG_STREAM_CACHE
494 return cache_do_control(s
, cmd
, arg
);
496 return s
->control(s
, cmd
, arg
);
499 stream_t
* new_memory_stream(unsigned char* data
,int len
){
504 s
=calloc(1, sizeof(stream_t
)+len
);
506 s
->type
=STREAMTYPE_MEMORY
;
507 s
->buf_pos
=0; s
->buf_len
=len
;
508 s
->start_pos
=0; s
->end_pos
=len
;
511 memcpy(s
->buffer
,data
,len
);
515 stream_t
* new_stream(int fd
,int type
){
516 stream_t
*s
=calloc(1, sizeof(stream_t
));
517 if(s
==NULL
) return NULL
;
522 int temp
= WSAStartup(0x0202, &wsdata
); // there might be a better place for this (-> later)
523 mp_msg(MSGT_STREAM
,MSGL_V
,"WINSOCK2 init: %i\n", temp
);
529 s
->buf_pos
=s
->buf_len
=0;
530 s
->start_pos
=s
->end_pos
=0;
538 void free_stream(stream_t
*s
){
539 // printf("\n*** free_stream() called ***\n");
540 #ifdef CONFIG_STREAM_CACHE
543 if (s
->capture_file
) {
544 fclose(s
->capture_file
);
545 s
->capture_file
= NULL
;
548 if(s
->close
) s
->close(s
);
550 /* on unix we define closesocket to close
551 on windows however we have to distinguish between
552 network socket and file */
553 if(s
->url
&& strstr(s
->url
,"://"))
558 mp_msg(MSGT_STREAM
,MSGL_V
,"WINSOCK2 uninit\n");
559 WSACleanup(); // there might be a better place for this (-> later)
561 // Disabled atm, i don't like that. s->priv can be anything after all
562 // streams should destroy their priv on close
568 stream_t
* new_ds_stream(demux_stream_t
*ds
) {
569 stream_t
* s
= new_stream(-1,STREAMTYPE_DS
);
574 void stream_set_interrupt_callback(int (*cb
)(struct input_ctx
*, int),
575 struct input_ctx
*ctx
)
577 stream_check_interrupt_cb
= cb
;
578 stream_check_interrupt_ctx
= ctx
;
581 int stream_check_interrupt(int time
) {
582 if(!stream_check_interrupt_cb
) {
583 usec_sleep(time
* 1000);
586 return stream_check_interrupt_cb(stream_check_interrupt_ctx
, time
);
590 * Helper function to read 16 bits little-endian and advance pointer
592 static uint16_t get_le16_inc(const uint8_t **buf
)
594 uint16_t v
= AV_RL16(*buf
);
600 * Helper function to read 16 bits big-endian and advance pointer
602 static uint16_t get_be16_inc(const uint8_t **buf
)
604 uint16_t v
= AV_RB16(*buf
);
610 * Find a newline character in buffer
611 * \param buf buffer to search
612 * \param len amount of bytes to search in buffer, may not overread
613 * \param utf16 chose between UTF-8/ASCII/other and LE and BE UTF-16
614 * 0 = UTF-8/ASCII/other, 1 = UTF-16-LE, 2 = UTF-16-BE
616 static const uint8_t *find_newline(const uint8_t *buf
, int len
, int utf16
)
619 const uint8_t *end
= buf
+ len
;
622 return (uint8_t *)memchr(buf
, '\n', len
);
624 while (buf
< end
- 1) {
625 GET_UTF16(c
, buf
< end
- 1 ? get_le16_inc(&buf
) : 0, return NULL
;)
626 if (buf
<= end
&& c
== '\n')
631 while (buf
< end
- 1) {
632 GET_UTF16(c
, buf
< end
- 1 ? get_be16_inc(&buf
) : 0, return NULL
;)
633 if (buf
<= end
&& c
== '\n')
642 * Copy a number of bytes, converting to UTF-8 if input is UTF-16
643 * \param dst buffer to copy to
644 * \param dstsize size of dst buffer
645 * \param src buffer to copy from
646 * \param len amount of bytes to copy from src
647 * \param utf16 chose between UTF-8/ASCII/other and LE and BE UTF-16
648 * 0 = UTF-8/ASCII/other, 1 = UTF-16-LE, 2 = UTF-16-BE
650 static int copy_characters(uint8_t *dst
, int dstsize
,
651 const uint8_t *src
, int *len
, int utf16
)
654 uint8_t *dst_end
= dst
+ dstsize
;
655 const uint8_t *end
= src
+ *len
;
660 memcpy(dst
, src
, *len
);
663 while (src
< end
- 1 && dst_end
- dst
> 8) {
665 GET_UTF16(c
, src
< end
- 1 ? get_le16_inc(&src
) : 0, ;)
666 PUT_UTF8(c
, tmp
, *dst
++ = tmp
;)
669 return dstsize
- (dst_end
- dst
);
671 while (src
< end
- 1 && dst_end
- dst
> 8) {
673 GET_UTF16(c
, src
< end
- 1 ? get_be16_inc(&src
) : 0, ;)
674 PUT_UTF8(c
, tmp
, *dst
++ = tmp
;)
677 return dstsize
- (dst_end
- dst
);
682 unsigned char* stream_read_line(stream_t
*s
,unsigned char* mem
, int max
, int utf16
) {
684 const unsigned char *end
;
685 unsigned char *ptr
= mem
;
686 if (max
< 1) return NULL
;
687 max
--; // reserve one for 0-termination
689 len
= s
->buf_len
-s
->buf_pos
;
690 // try to fill the buffer
692 (!cache_stream_fill_buffer(s
) ||
693 (len
= s
->buf_len
-s
->buf_pos
) <= 0)) break;
694 end
= find_newline(s
->buffer
+s
->buf_pos
, len
, utf16
);
695 if(end
) len
= end
- (s
->buffer
+s
->buf_pos
) + 1;
696 if(len
> 0 && max
> 0) {
697 int l
= copy_characters(ptr
, max
, s
->buffer
+s
->buf_pos
, &len
, utf16
);
706 if(s
->eof
&& ptr
== mem
) return NULL
;
710 struct bstr
stream_read_complete(struct stream
*s
, void *talloc_ctx
,
711 int max_size
, int padding_bytes
)
713 if (max_size
> 1000000000)
718 int padding
= FFMAX(padding_bytes
, 1);
720 if (s
->end_pos
> max_size
)
721 return (struct bstr
){NULL
, 0};
723 bufsize
= s
->end_pos
+ padding
;
727 buf
= talloc_realloc_size(talloc_ctx
, buf
, bufsize
);
728 int readsize
= stream_read(s
, buf
+ total_read
, bufsize
- total_read
);
729 total_read
+= readsize
;
730 if (total_read
< bufsize
)
732 if (bufsize
> max_size
) {
734 return (struct bstr
){NULL
, 0};
736 bufsize
= FFMIN(bufsize
+ (bufsize
>> 1), max_size
+ padding
);
738 buf
= talloc_realloc_size(talloc_ctx
, buf
, total_read
+ padding
);
739 return (struct bstr
){buf
, total_read
};