| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Unbuffered io for ffmpeg system | 
					
						
							| 
									
										
										
										
											2002-05-25 22:34:32 +00:00
										 |  |  |  * Copyright (c) 2001 Fabrice Bellard | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * This file is part of FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							| 
									
										
										
										
											2002-05-25 22:34:32 +00:00
										 |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2002-05-25 22:34:32 +00:00
										 |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2002-05-25 22:34:32 +00:00
										 |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2006-01-12 22:43:26 +00:00
										 |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-05-09 11:56:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "libavutil/avstring.h"
 | 
					
						
							|  |  |  | #include "libavcodec/opt.h"
 | 
					
						
							| 
									
										
										
										
											2008-10-10 16:59:37 +00:00
										 |  |  | #include "os_support.h"
 | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | #include "avformat.h"
 | 
					
						
							| 
									
										
										
										
											2008-03-10 19:03:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if LIBAVFORMAT_VERSION_MAJOR >= 53
 | 
					
						
							|  |  |  | /** @name Logging context. */ | 
					
						
							|  |  |  | /*@{*/ | 
					
						
							|  |  |  | static const char *urlcontext_to_name(void *ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     URLContext *h = (URLContext *)ptr; | 
					
						
							|  |  |  |     if(h->prot) return h->prot->name; | 
					
						
							|  |  |  |     else        return "NULL"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static const AVOption options[] = {{NULL}}; | 
					
						
							|  |  |  | static const AVClass urlcontext_class = | 
					
						
							|  |  |  |         { "URLContext", urlcontext_to_name, options }; | 
					
						
							|  |  |  | /*@}*/ | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-17 10:25:36 +00:00
										 |  |  | static int default_interrupt_cb(void); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | URLProtocol *first_protocol = NULL; | 
					
						
							| 
									
										
										
										
											2003-07-17 10:25:36 +00:00
										 |  |  | URLInterruptCB *url_interrupt_cb = default_interrupt_cb; | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-12 19:01:58 +00:00
										 |  |  | URLProtocol *av_protocol_next(URLProtocol *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(p) return p->next; | 
					
						
							|  |  |  |     else  return first_protocol; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-15 14:25:23 +00:00
										 |  |  | int av_register_protocol(URLProtocol *protocol) | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     URLProtocol **p; | 
					
						
							|  |  |  |     p = &first_protocol; | 
					
						
							|  |  |  |     while (*p != NULL) p = &(*p)->next; | 
					
						
							|  |  |  |     *p = protocol; | 
					
						
							|  |  |  |     protocol->next = NULL; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-15 14:25:23 +00:00
										 |  |  | #if LIBAVFORMAT_VERSION_MAJOR < 53
 | 
					
						
							|  |  |  | int register_protocol(URLProtocol *protocol) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return av_register_protocol(protocol); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 23:44:23 +00:00
										 |  |  | int url_open_protocol (URLContext **puc, struct URLProtocol *up, | 
					
						
							|  |  |  |                        const char *filename, int flags) | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     URLContext *uc; | 
					
						
							|  |  |  |     int err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-14 22:07:19 +00:00
										 |  |  |     uc = av_malloc(sizeof(URLContext) + strlen(filename) + 1); | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  |     if (!uc) { | 
					
						
							| 
									
										
										
										
											2007-02-13 18:26:14 +00:00
										 |  |  |         err = AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-03-10 19:03:39 +00:00
										 |  |  | #if LIBAVFORMAT_VERSION_MAJOR >= 53
 | 
					
						
							|  |  |  |     uc->av_class = &urlcontext_class; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-01-14 22:07:19 +00:00
										 |  |  |     uc->filename = (char *) &uc[1]; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:59:17 +00:00
										 |  |  |     strcpy(uc->filename, filename); | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     uc->prot = up; | 
					
						
							|  |  |  |     uc->flags = flags; | 
					
						
							|  |  |  |     uc->is_streamed = 0; /* default = not streamed */ | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  |     uc->max_packet_size = 0; /* default: stream file */ | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     err = up->url_open(uc, filename, flags); | 
					
						
							|  |  |  |     if (err < 0) { | 
					
						
							| 
									
										
										
										
											2002-05-18 23:11:09 +00:00
										 |  |  |         av_free(uc); | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |         *puc = NULL; | 
					
						
							|  |  |  |         return err; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-05-05 09:17:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-17 13:39:34 +00:00
										 |  |  |     //We must be careful here as url_seek() could be slow, for example for http
 | 
					
						
							| 
									
										
										
										
											2008-05-05 09:17:56 +00:00
										 |  |  |     if(   (flags & (URL_WRONLY | URL_RDWR)) | 
					
						
							| 
									
										
										
										
											2008-08-19 23:44:23 +00:00
										 |  |  |        || !strcmp(up->name, "file")) | 
					
						
							| 
									
										
										
										
											2008-05-05 09:17:56 +00:00
										 |  |  |         if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0) | 
					
						
							|  |  |  |             uc->is_streamed= 1; | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     *puc = uc; | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  |  fail: | 
					
						
							|  |  |  |     *puc = NULL; | 
					
						
							|  |  |  |     return err; | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 23:44:23 +00:00
										 |  |  | int url_open(URLContext **puc, const char *filename, int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     URLProtocol *up; | 
					
						
							|  |  |  |     const char *p; | 
					
						
							|  |  |  |     char proto_str[128], *q; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     p = filename; | 
					
						
							|  |  |  |     q = proto_str; | 
					
						
							|  |  |  |     while (*p != '\0' && *p != ':') { | 
					
						
							|  |  |  |         /* protocols can only contain alphabetic chars */ | 
					
						
							|  |  |  |         if (!isalpha(*p)) | 
					
						
							|  |  |  |             goto file_proto; | 
					
						
							|  |  |  |         if ((q - proto_str) < sizeof(proto_str) - 1) | 
					
						
							|  |  |  |             *q++ = *p; | 
					
						
							|  |  |  |         p++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if the protocol has length 1, we consider it is a dos drive */ | 
					
						
							| 
									
										
										
										
											2008-10-10 16:59:37 +00:00
										 |  |  |     if (*p == '\0' || is_dos_path(filename)) { | 
					
						
							| 
									
										
										
										
											2008-08-19 23:44:23 +00:00
										 |  |  |     file_proto: | 
					
						
							|  |  |  |         strcpy(proto_str, "file"); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         *q = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     up = first_protocol; | 
					
						
							|  |  |  |     while (up != NULL) { | 
					
						
							|  |  |  |         if (!strcmp(proto_str, up->name)) | 
					
						
							|  |  |  |             return url_open_protocol (puc, up, filename, flags); | 
					
						
							|  |  |  |         up = up->next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     *puc = NULL; | 
					
						
							|  |  |  |     return AVERROR(ENOENT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | int url_read(URLContext *h, unsigned char *buf, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     if (h->flags & URL_WRONLY) | 
					
						
							| 
									
										
										
										
											2007-07-19 15:23:32 +00:00
										 |  |  |         return AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     ret = h->prot->url_read(h, buf, size); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-04 06:25:53 +00:00
										 |  |  | int url_read_complete(URLContext *h, unsigned char *buf, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret, len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     len = 0; | 
					
						
							|  |  |  |     while (len < size) { | 
					
						
							|  |  |  |         ret = url_read(h, buf+len, size-len); | 
					
						
							| 
									
										
										
										
											2010-01-23 10:23:47 +00:00
										 |  |  |         if (ret == AVERROR(EAGAIN)) { | 
					
						
							|  |  |  |             ret = 0; | 
					
						
							|  |  |  |         } else if (ret < 1) | 
					
						
							|  |  |  |             return ret < 0 ? ret : len; | 
					
						
							| 
									
										
										
										
											2009-06-04 06:25:53 +00:00
										 |  |  |         len += ret; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | int url_write(URLContext *h, unsigned char *buf, int size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  |     if (!(h->flags & (URL_WRONLY | URL_RDWR))) | 
					
						
							| 
									
										
										
										
											2007-07-19 15:23:32 +00:00
										 |  |  |         return AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  |     /* avoid sending too big packets */ | 
					
						
							|  |  |  |     if (h->max_packet_size && size > h->max_packet_size) | 
					
						
							| 
									
										
										
										
											2007-07-19 15:23:32 +00:00
										 |  |  |         return AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     ret = h->prot->url_write(h, buf, size); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-03 10:16:29 +00:00
										 |  |  | int64_t url_seek(URLContext *h, int64_t pos, int whence) | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-03 10:16:29 +00:00
										 |  |  |     int64_t ret; | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!h->prot->url_seek) | 
					
						
							| 
									
										
										
										
											2007-02-13 18:26:14 +00:00
										 |  |  |         return AVERROR(EPIPE); | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     ret = h->prot->url_seek(h, pos, whence); | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int url_close(URLContext *h) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-11-16 00:14:48 +00:00
										 |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2007-11-07 08:34:00 +00:00
										 |  |  |     if (!h) return 0; /* can happen when url_open fails */ | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-16 00:14:48 +00:00
										 |  |  |     if (h->prot->url_close) | 
					
						
							|  |  |  |         ret = h->prot->url_close(h); | 
					
						
							| 
									
										
										
										
											2002-05-18 23:11:09 +00:00
										 |  |  |     av_free(h); | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int url_exist(const char *filename) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     URLContext *h; | 
					
						
							|  |  |  |     if (url_open(&h, filename, URL_RDONLY) < 0) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     url_close(h); | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-03 10:16:29 +00:00
										 |  |  | int64_t url_filesize(URLContext *h) | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-03 10:16:29 +00:00
										 |  |  |     int64_t pos, size; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-01 21:49:09 +00:00
										 |  |  |     size= url_seek(h, 0, AVSEEK_SIZE); | 
					
						
							|  |  |  |     if(size<0){ | 
					
						
							| 
									
										
										
										
											2007-01-01 21:49:50 +00:00
										 |  |  |         pos = url_seek(h, 0, SEEK_CUR); | 
					
						
							| 
									
										
										
										
											2007-01-30 10:37:52 +00:00
										 |  |  |         if ((size = url_seek(h, -1, SEEK_END)) < 0) | 
					
						
							|  |  |  |             return size; | 
					
						
							|  |  |  |         size++; | 
					
						
							| 
									
										
										
										
											2007-01-01 21:49:50 +00:00
										 |  |  |         url_seek(h, pos, SEEK_SET); | 
					
						
							| 
									
										
										
										
											2007-01-01 21:49:09 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-07-22 14:18:56 +00:00
										 |  |  |     return size; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 17:04:51 +00:00
										 |  |  | int url_get_file_handle(URLContext *h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!h->prot->url_get_file_handle) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     return h->prot->url_get_file_handle(h); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-24 17:50:23 +00:00
										 |  |  | int url_get_max_packet_size(URLContext *h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return h->max_packet_size; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2003-01-11 04:59:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void url_get_filename(URLContext *h, char *buf, int buf_size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-06-23 23:10:32 +00:00
										 |  |  |     av_strlcpy(buf, h->filename, buf_size); | 
					
						
							| 
									
										
										
										
											2003-01-11 04:59:17 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2003-07-17 10:25:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int default_interrupt_cb(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void url_set_interrupt_cb(URLInterruptCB *interrupt_cb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!interrupt_cb) | 
					
						
							|  |  |  |         interrupt_cb = default_interrupt_cb; | 
					
						
							|  |  |  |     url_interrupt_cb = interrupt_cb; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-11-24 07:09:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-19 20:57:13 +00:00
										 |  |  | int av_url_read_pause(URLContext *h, int pause) | 
					
						
							| 
									
										
										
										
											2007-11-24 07:09:32 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!h->prot->url_read_pause) | 
					
						
							|  |  |  |         return AVERROR(ENOSYS); | 
					
						
							| 
									
										
										
										
											2007-12-19 20:57:13 +00:00
										 |  |  |     return h->prot->url_read_pause(h, pause); | 
					
						
							| 
									
										
										
										
											2007-11-24 07:09:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-03 10:16:29 +00:00
										 |  |  | int64_t av_url_read_seek(URLContext *h, | 
					
						
							| 
									
										
										
										
											2007-11-24 07:09:32 +00:00
										 |  |  |         int stream_index, int64_t timestamp, int flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!h->prot->url_read_seek) | 
					
						
							|  |  |  |         return AVERROR(ENOSYS); | 
					
						
							|  |  |  |     return h->prot->url_read_seek(h, stream_index, timestamp, flags); | 
					
						
							|  |  |  | } |