* qatar/master: lavf: pass options from AVFormatContext to avio. avformat: Use avio_open2, pass the AVFormatContext interrupt_callback onwards avio: add avio_open2, taking an interrupt callback and options avio: add support for passing options to protocols. avio: add and use ffurl_protocol_next(). avformat: Pass the interrupt callback on to chained muxers/demuxers avio: Add an AVIOInterruptCB parameter to ffurl_open/ffurl_alloc avformat: Use ff_check_interrupt avio: Add an internal utility function for checking the new interrupt callback avio: Add AVIOInterruptCB texi2html: remove stray \n doc: prettyfy the texi2html documentation swscale: handle unaligned buffers in yuv2plane1 Conflicts: libavformat/avformat.h libavformat/avio.c libavformat/mov.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n0.9
| @@ -418,7 +418,7 @@ To list the pulse source devices and their properties you can invoke | |||
| the command @file{pactl list sources}. | |||
| @example | |||
| ffmpeg -f pulse -i default /tmp/pulse.wav | |||
| avconv -f pulse -i default /tmp/pulse.wav | |||
| @end example | |||
| @subsection @var{server} AVOption | |||
| @@ -1,15 +1,71 @@ | |||
| # no horiz rules between sections | |||
| $end_section = \&FFMPEG_end_section; | |||
| sub FFMPEG_end_section($$) | |||
| $end_section = \&FFmpeg_end_section; | |||
| sub FFmpeg_end_section($$) | |||
| { | |||
| } | |||
| $print_page_foot = \&FFMPEG_print_page_foot; | |||
| sub FFMPEG_print_page_foot($$) | |||
| $EXTRA_HEAD = | |||
| '<link rel="icon" href="favicon.png" type="image/png" /> | |||
| <link rel="stylesheet" type="text/css" href="default.css" /> | |||
| '; | |||
| $AFTER_BODY_OPEN = | |||
| '<div id="container"> | |||
| <div id="body">'; | |||
| $PRE_BODY_CLOSE = '</div></div>'; | |||
| $SMALL_RULE = ''; | |||
| $BODYTEXT = ''; | |||
| $print_page_foot = \&FFmpeg_print_page_foot; | |||
| sub FFmpeg_print_page_foot($$) | |||
| { | |||
| my $fh = shift; | |||
| print $fh "$SMALL_RULE\n"; | |||
| print $fh '<div id="footer">' . "\n"; | |||
| T2H_DEFAULT_print_page_foot($fh); | |||
| print $fh "</div>\n"; | |||
| } | |||
| $print_page_head = \&FFmpeg_print_page_head; | |||
| sub FFmpeg_print_page_head($$) | |||
| { | |||
| my $fh = shift; | |||
| my $longtitle = "$Texi2HTML::THISDOC{'title_no_texi'}"; | |||
| $longtitle .= ": $Texi2HTML::NO_TEXI{'This'}" if exists $Texi2HTML::NO_TEXI{'This'}; | |||
| my $description = $DOCUMENT_DESCRIPTION; | |||
| $description = $longtitle if (!defined($description)); | |||
| $description = "<meta name=\"description\" content=\"$description\">" if | |||
| ($description ne ''); | |||
| $description = $Texi2HTML::THISDOC{'documentdescription'} if (defined($Texi2HTML::THISDOC{'documentdescription'})); | |||
| my $encoding = ''; | |||
| $encoding = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=$ENCODING\">" if (defined($ENCODING) and ($ENCODING ne '')); | |||
| $longtitle =~ s/Documentation.*//g; | |||
| $longtitle = "FFmpeg documentation : " . $longtitle; | |||
| print $fh <<EOT; | |||
| $DOCTYPE | |||
| <html> | |||
| $Texi2HTML::THISDOC{'copying'}<!-- Created on $Texi2HTML::THISDOC{today} by $Texi2HTML::THISDOC{program} --> | |||
| <!-- | |||
| $Texi2HTML::THISDOC{program_authors} | |||
| --> | |||
| <head> | |||
| <title>$longtitle</title> | |||
| $description | |||
| <meta name="keywords" content="$longtitle"> | |||
| <meta name="resource-type" content="document"> | |||
| <meta name="distribution" content="global"> | |||
| <meta name="Generator" content="$Texi2HTML::THISDOC{program}"> | |||
| $encoding | |||
| $CSS_LINES | |||
| $EXTRA_HEAD | |||
| </head> | |||
| <body $BODYTEXT> | |||
| $AFTER_BODY_OPEN | |||
| EOT | |||
| } | |||
| # no navigation elements | |||
| @@ -99,6 +99,7 @@ typedef struct AppleHTTPContext { | |||
| int cur_seq_no; | |||
| int end_of_segment; | |||
| int first_packet; | |||
| AVIOInterruptCB *interrupt_callback; | |||
| } AppleHTTPContext; | |||
| static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) | |||
| @@ -209,7 +210,8 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, | |||
| if (!in) { | |||
| close_in = 1; | |||
| if ((ret = avio_open(&in, url, AVIO_FLAG_READ)) < 0) | |||
| if ((ret = avio_open2(&in, url, AVIO_FLAG_READ, | |||
| c->interrupt_callback, NULL)) < 0) | |||
| return ret; | |||
| } | |||
| @@ -322,13 +324,15 @@ static int open_input(struct variant *var) | |||
| { | |||
| struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no]; | |||
| if (seg->key_type == KEY_NONE) { | |||
| return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ); | |||
| return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ, | |||
| &var->parent->interrupt_callback, NULL); | |||
| } else if (seg->key_type == KEY_AES_128) { | |||
| char iv[33], key[33], url[MAX_URL_SIZE]; | |||
| int ret; | |||
| if (strcmp(seg->key, var->key_url)) { | |||
| URLContext *uc; | |||
| if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ) == 0) { | |||
| if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ, | |||
| &var->parent->interrupt_callback, NULL) == 0) { | |||
| if (ffurl_read_complete(uc, var->key, sizeof(var->key)) | |||
| != sizeof(var->key)) { | |||
| av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n", | |||
| @@ -348,11 +352,12 @@ static int open_input(struct variant *var) | |||
| snprintf(url, sizeof(url), "crypto+%s", seg->url); | |||
| else | |||
| snprintf(url, sizeof(url), "crypto:%s", seg->url); | |||
| if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ)) < 0) | |||
| if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ, | |||
| &var->parent->interrupt_callback)) < 0) | |||
| return ret; | |||
| av_opt_set(var->input->priv_data, "key", key, 0); | |||
| av_opt_set(var->input->priv_data, "iv", iv, 0); | |||
| if ((ret = ffurl_connect(var->input)) < 0) { | |||
| if ((ret = ffurl_connect(var->input, NULL)) < 0) { | |||
| ffurl_close(var->input); | |||
| var->input = NULL; | |||
| return ret; | |||
| @@ -388,7 +393,7 @@ reload: | |||
| return AVERROR_EOF; | |||
| while (av_gettime() - v->last_load_time < | |||
| v->target_duration*1000000) { | |||
| if (url_interrupt_cb()) | |||
| if (ff_check_interrupt(c->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| usleep(100*1000); | |||
| } | |||
| @@ -433,6 +438,8 @@ static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| AppleHTTPContext *c = s->priv_data; | |||
| int ret = 0, i, j, stream_offset = 0; | |||
| c->interrupt_callback = &s->interrupt_callback; | |||
| if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0) | |||
| goto fail; | |||
| @@ -114,7 +114,8 @@ static int parse_playlist(URLContext *h, const char *url) | |||
| char line[1024]; | |||
| const char *ptr; | |||
| if ((ret = avio_open(&in, url, AVIO_FLAG_READ)) < 0) | |||
| if ((ret = avio_open2(&in, url, AVIO_FLAG_READ, | |||
| &h->interrupt_callback, NULL)) < 0) | |||
| return ret; | |||
| read_chomp_line(in, line, sizeof(line)); | |||
| @@ -266,7 +267,7 @@ retry: | |||
| if (s->finished) | |||
| return AVERROR_EOF; | |||
| while (av_gettime() - s->last_load_time < s->target_duration*1000000) { | |||
| if (url_interrupt_cb()) | |||
| if (ff_check_interrupt(&h->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| usleep(100*1000); | |||
| } | |||
| @@ -274,9 +275,10 @@ retry: | |||
| } | |||
| url = s->segments[s->cur_seq_no - s->start_seq_no]->url, | |||
| av_log(h, AV_LOG_DEBUG, "opening %s\n", url); | |||
| ret = ffurl_open(&s->seg_hd, url, AVIO_FLAG_READ); | |||
| ret = ffurl_open(&s->seg_hd, url, AVIO_FLAG_READ, | |||
| &h->interrupt_callback, NULL); | |||
| if (ret < 0) { | |||
| if (url_interrupt_cb()) | |||
| if (ff_check_interrupt(&h->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| av_log(h, AV_LOG_WARNING, "Unable to open %s\n", url); | |||
| s->cur_seq_no++; | |||
| @@ -1027,12 +1027,24 @@ typedef struct AVFormatContext { | |||
| */ | |||
| int error_recognition; | |||
| /** | |||
| * Custom interrupt callbacks for the I/O layer. | |||
| * | |||
| * decoding: set by the user before avformat_open_input(). | |||
| * encoding: set by the user before avformat_write_header() | |||
| * (mainly useful for AVFMT_NOFILE formats). The callback | |||
| * should also be passed to avio_open2() if it's used to | |||
| * open the file. | |||
| */ | |||
| AVIOInterruptCB interrupt_callback; | |||
| /** | |||
| * Transport stream id. | |||
| * This will be moved into demuxer private options. Thus no API/ABI compatibility | |||
| */ | |||
| int ts_id; | |||
| /***************************************************************** | |||
| * All fields below this line are not part of the public API. They | |||
| * may not be used outside of libavformat and can be changed and | |||
| @@ -22,6 +22,7 @@ | |||
| #include <unistd.h> | |||
| #include "libavutil/avstring.h" | |||
| #include "libavutil/dict.h" | |||
| #include "libavutil/opt.h" | |||
| #include "os_support.h" | |||
| #include "avformat.h" | |||
| @@ -30,6 +31,13 @@ | |||
| #endif | |||
| #include "url.h" | |||
| static URLProtocol *first_protocol = NULL; | |||
| URLProtocol *ffurl_protocol_next(URLProtocol *prev) | |||
| { | |||
| return prev ? prev->next : first_protocol; | |||
| } | |||
| /** @name Logging context. */ | |||
| /*@{*/ | |||
| static const char *urlcontext_to_name(void *ptr) | |||
| @@ -38,33 +46,59 @@ static const char *urlcontext_to_name(void *ptr) | |||
| if(h->prot) return h->prot->name; | |||
| else return "NULL"; | |||
| } | |||
| static void *urlcontext_child_next(void *obj, void *prev) | |||
| { | |||
| URLContext *h = obj; | |||
| if (!prev && h->priv_data && h->prot->priv_data_class) | |||
| return h->priv_data; | |||
| return NULL; | |||
| } | |||
| static const AVClass *urlcontext_child_class_next(const AVClass *prev) | |||
| { | |||
| URLProtocol *p = NULL; | |||
| /* find the protocol that corresponds to prev */ | |||
| while (prev && (p = ffurl_protocol_next(p))) | |||
| if (p->priv_data_class == prev) | |||
| break; | |||
| /* find next protocol with priv options */ | |||
| while (p = ffurl_protocol_next(p)) | |||
| if (p->priv_data_class) | |||
| return p->priv_data_class; | |||
| return NULL; | |||
| } | |||
| static const AVOption options[] = {{NULL}}; | |||
| static const AVClass urlcontext_class = { | |||
| const AVClass ffurl_context_class = { | |||
| .class_name = "URLContext", | |||
| .item_name = urlcontext_to_name, | |||
| .option = options, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| .child_next = urlcontext_child_next, | |||
| .child_class_next = urlcontext_child_class_next, | |||
| }; | |||
| /*@}*/ | |||
| static int default_interrupt_cb(void); | |||
| URLProtocol *first_protocol = NULL; | |||
| int (*url_interrupt_cb)(void) = default_interrupt_cb; | |||
| URLProtocol *av_protocol_next(URLProtocol *p) | |||
| { | |||
| if(p) return p->next; | |||
| else return first_protocol; | |||
| return ffurl_protocol_next(p); | |||
| } | |||
| const char *avio_enum_protocols(void **opaque, int output) | |||
| { | |||
| URLProtocol *p = *opaque; | |||
| p = p ? p->next : first_protocol; | |||
| if (!p) return NULL; | |||
| if ((output && p->url_write) || (!output && p->url_read)) | |||
| return p->name; | |||
| URLProtocol **p = opaque; | |||
| *p = ffurl_protocol_next(*p); | |||
| if (!*p) return NULL; | |||
| if ((output && (*p)->url_write) || (!output && (*p)->url_read)) | |||
| return (*p)->name; | |||
| return avio_enum_protocols(opaque, output); | |||
| } | |||
| @@ -84,7 +118,8 @@ int ffurl_register_protocol(URLProtocol *protocol, int size) | |||
| } | |||
| static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up, | |||
| const char *filename, int flags) | |||
| const char *filename, int flags, | |||
| const AVIOInterruptCB *int_cb) | |||
| { | |||
| URLContext *uc; | |||
| int err; | |||
| @@ -98,7 +133,7 @@ static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up, | |||
| err = AVERROR(ENOMEM); | |||
| goto fail; | |||
| } | |||
| uc->av_class = &urlcontext_class; | |||
| uc->av_class = &ffurl_context_class; | |||
| uc->filename = (char *) &uc[1]; | |||
| strcpy(uc->filename, filename); | |||
| uc->prot = up; | |||
| @@ -112,6 +147,8 @@ static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up, | |||
| av_opt_set_defaults(uc->priv_data); | |||
| } | |||
| } | |||
| if (int_cb) | |||
| uc->interrupt_callback = *int_cb; | |||
| *puc = uc; | |||
| return 0; | |||
| @@ -123,9 +160,13 @@ static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up, | |||
| return err; | |||
| } | |||
| int ffurl_connect(URLContext* uc) | |||
| int ffurl_connect(URLContext* uc, AVDictionary **options) | |||
| { | |||
| int err = uc->prot->url_open(uc, uc->filename, uc->flags); | |||
| int err = | |||
| #if !FF_API_OLD_AVIO | |||
| uc->prot->url_open2 ? uc->prot->url_open2(uc, uc->filename, uc->flags, options) : | |||
| #endif | |||
| uc->prot->url_open(uc, uc->filename, uc->flags); | |||
| if (err) | |||
| return err; | |||
| uc->is_connected = 1; | |||
| @@ -143,10 +184,10 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up, | |||
| { | |||
| int ret; | |||
| ret = url_alloc_for_protocol(puc, up, filename, flags); | |||
| ret = url_alloc_for_protocol(puc, up, filename, flags, NULL); | |||
| if (ret) | |||
| goto fail; | |||
| ret = ffurl_connect(*puc); | |||
| ret = ffurl_connect(*puc, NULL); | |||
| if (!ret) | |||
| return 0; | |||
| fail: | |||
| @@ -156,15 +197,15 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up, | |||
| } | |||
| int url_alloc(URLContext **puc, const char *filename, int flags) | |||
| { | |||
| return ffurl_alloc(puc, filename, flags); | |||
| return ffurl_alloc(puc, filename, flags, NULL); | |||
| } | |||
| int url_connect(URLContext* uc) | |||
| { | |||
| return ffurl_connect(uc); | |||
| return ffurl_connect(uc, NULL); | |||
| } | |||
| int url_open(URLContext **puc, const char *filename, int flags) | |||
| { | |||
| return ffurl_open(puc, filename, flags); | |||
| return ffurl_open(puc, filename, flags, NULL, NULL); | |||
| } | |||
| int url_read(URLContext *h, unsigned char *buf, int size) | |||
| { | |||
| @@ -217,9 +258,10 @@ int av_register_protocol2(URLProtocol *protocol, int size) | |||
| "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ | |||
| "0123456789+-." | |||
| int ffurl_alloc(URLContext **puc, const char *filename, int flags) | |||
| int ffurl_alloc(URLContext **puc, const char *filename, int flags, | |||
| const AVIOInterruptCB *int_cb) | |||
| { | |||
| URLProtocol *up; | |||
| URLProtocol *up = NULL; | |||
| char proto_str[128], proto_nested[128], *ptr; | |||
| size_t proto_len = strspn(filename, URL_SCHEME_CHARS); | |||
| @@ -237,27 +279,30 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags) | |||
| if ((ptr = strchr(proto_nested, '+'))) | |||
| *ptr = '\0'; | |||
| up = first_protocol; | |||
| while (up != NULL) { | |||
| while (up = ffurl_protocol_next(up)) { | |||
| if (!strcmp(proto_str, up->name)) | |||
| return url_alloc_for_protocol (puc, up, filename, flags); | |||
| return url_alloc_for_protocol (puc, up, filename, flags, int_cb); | |||
| if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME && | |||
| !strcmp(proto_nested, up->name)) | |||
| return url_alloc_for_protocol (puc, up, filename, flags); | |||
| up = up->next; | |||
| return url_alloc_for_protocol (puc, up, filename, flags, int_cb); | |||
| } | |||
| *puc = NULL; | |||
| return AVERROR(ENOENT); | |||
| } | |||
| int ffurl_open(URLContext **puc, const char *filename, int flags) | |||
| int ffurl_open(URLContext **puc, const char *filename, int flags, | |||
| const AVIOInterruptCB *int_cb, AVDictionary **options) | |||
| { | |||
| int ret = ffurl_alloc(puc, filename, flags); | |||
| int ret = ffurl_alloc(puc, filename, flags, int_cb); | |||
| if (ret) | |||
| return ret; | |||
| ret = ffurl_connect(*puc); | |||
| if (options && (*puc)->prot->priv_data_class && | |||
| (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0) | |||
| goto fail; | |||
| ret = ffurl_connect(*puc, options); | |||
| if (!ret) | |||
| return 0; | |||
| fail: | |||
| ffurl_close(*puc); | |||
| *puc = NULL; | |||
| return ret; | |||
| @@ -287,7 +332,7 @@ static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int | |||
| if (ret) | |||
| fast_retries = FFMAX(fast_retries, 2); | |||
| len += ret; | |||
| if (len < size && url_interrupt_cb()) | |||
| if (len < size && ff_check_interrupt(&h->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| } | |||
| return len; | |||
| @@ -351,7 +396,7 @@ int ffurl_close(URLContext *h) | |||
| int url_exist(const char *filename) | |||
| { | |||
| URLContext *h; | |||
| if (ffurl_open(&h, filename, AVIO_FLAG_READ) < 0) | |||
| if (ffurl_open(&h, filename, AVIO_FLAG_READ, NULL, NULL) < 0) | |||
| return 0; | |||
| ffurl_close(h); | |||
| return 1; | |||
| @@ -361,14 +406,14 @@ int url_exist(const char *filename) | |||
| int avio_check(const char *url, int flags) | |||
| { | |||
| URLContext *h; | |||
| int ret = ffurl_alloc(&h, url, flags); | |||
| int ret = ffurl_alloc(&h, url, flags, NULL); | |||
| if (ret) | |||
| return ret; | |||
| if (h->prot->url_check) { | |||
| ret = h->prot->url_check(h, flags); | |||
| } else { | |||
| ret = ffurl_connect(h); | |||
| ret = ffurl_connect(h, NULL); | |||
| if (ret >= 0) | |||
| ret = flags; | |||
| } | |||
| @@ -411,6 +456,14 @@ void avio_set_interrupt_cb(int (*interrupt_cb)(void)) | |||
| url_interrupt_cb = interrupt_cb; | |||
| } | |||
| int ff_check_interrupt(AVIOInterruptCB *cb) | |||
| { | |||
| int ret; | |||
| if (cb && cb->callback && (ret = cb->callback(cb->opaque))) | |||
| return ret; | |||
| return url_interrupt_cb(); | |||
| } | |||
| #if FF_API_OLD_AVIO | |||
| int av_url_read_pause(URLContext *h, int pause) | |||
| { | |||
| @@ -28,6 +28,7 @@ | |||
| #include <stdint.h> | |||
| #include "libavutil/common.h" | |||
| #include "libavutil/dict.h" | |||
| #include "libavutil/log.h" | |||
| #include "libavformat/version.h" | |||
| @@ -35,6 +36,22 @@ | |||
| #define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */ | |||
| /** | |||
| * Callback for checking whether to abort blocking functions. | |||
| * AVERROR_EXIT is returned in this case by the interrupted | |||
| * function. During blocking operations, callback is called with | |||
| * opaque as parameter. If the callback returns 1, the | |||
| * blocking operation will be aborted. | |||
| * | |||
| * No members can be added to this struct without a major bump, if | |||
| * new elements have been added after this struct in AVFormatContext | |||
| * or AVIOContext. | |||
| */ | |||
| typedef struct { | |||
| int (*callback)(void*); | |||
| void *opaque; | |||
| } AVIOInterruptCB; | |||
| /** | |||
| * Bytestream IO Context. | |||
| * New fields can be added to the end with minor version bumps. | |||
| @@ -48,6 +65,21 @@ | |||
| * function pointers specified in avio_alloc_context() | |||
| */ | |||
| typedef struct { | |||
| #if !FF_API_OLD_AVIO | |||
| /** | |||
| * A class for private options. | |||
| * | |||
| * If this AVIOContext is created by avio_open2(), av_class is set and | |||
| * passes the options down to protocols. | |||
| * | |||
| * If this AVIOContext is manually allocated, then av_class may be set by | |||
| * the caller. | |||
| * | |||
| * warning -- this field can be NULL, be sure to not pass this AVIOContext | |||
| * to any av_opt_* functions in that case. | |||
| */ | |||
| AVClass *av_class; | |||
| #endif | |||
| unsigned char *buffer; /**< Start of the buffer. */ | |||
| int buffer_size; /**< Maximum buffer size */ | |||
| unsigned char *buf_ptr; /**< Current position in the buffer */ | |||
| @@ -109,6 +141,7 @@ typedef struct URLContext { | |||
| void *priv_data; | |||
| char *filename; /**< specified URL */ | |||
| int is_connected; | |||
| AVIOInterruptCB interrupt_callback; | |||
| } URLContext; | |||
| #define URL_PROTOCOL_FLAG_NESTED_SCHEME 1 /*< The protocol name can be the first part of a nested protocol scheme */ | |||
| @@ -556,6 +589,26 @@ int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen); | |||
| */ | |||
| int avio_open(AVIOContext **s, const char *url, int flags); | |||
| /** | |||
| * Create and initialize a AVIOContext for accessing the | |||
| * resource indicated by url. | |||
| * @note When the resource indicated by url has been opened in | |||
| * read+write mode, the AVIOContext can be used only for writing. | |||
| * | |||
| * @param s Used to return the pointer to the created AVIOContext. | |||
| * In case of failure the pointed to value is set to NULL. | |||
| * @param flags flags which control how the resource indicated by url | |||
| * is to be opened | |||
| * @param int_cb an interrupt callback to be used at the protocols level | |||
| * @param options A dictionary filled with protocol-private options. On return | |||
| * this parameter will be destroyed and replaced with a dict containing options | |||
| * that were not found. May be NULL. | |||
| * @return 0 in case of success, a negative value corresponding to an | |||
| * AVERROR code in case of failure | |||
| */ | |||
| int avio_open2(AVIOContext **s, const char *url, int flags, | |||
| const AVIOInterruptCB *int_cb, AVDictionary **options); | |||
| /** | |||
| * Close the resource accessed by the AVIOContext s and free it. | |||
| * This function can only be used if s was opened by avio_open(). | |||
| @@ -23,6 +23,10 @@ | |||
| #include "avio.h" | |||
| #include "url.h" | |||
| #include "libavutil/log.h" | |||
| extern const AVClass ffio_url_class; | |||
| int ffio_init_context(AVIOContext *s, | |||
| unsigned char *buffer, | |||
| int buffer_size, | |||
| @@ -20,7 +20,10 @@ | |||
| */ | |||
| #include "libavutil/crc.h" | |||
| #include "libavutil/dict.h" | |||
| #include "libavutil/intreadwrite.h" | |||
| #include "libavutil/log.h" | |||
| #include "libavutil/opt.h" | |||
| #include "avformat.h" | |||
| #include "avio.h" | |||
| #include "avio_internal.h" | |||
| @@ -37,6 +40,31 @@ | |||
| */ | |||
| #define SHORT_SEEK_THRESHOLD 4096 | |||
| #if !FF_API_OLD_AVIO | |||
| static void *ffio_url_child_next(void *obj, void *prev) | |||
| { | |||
| AVIOContext *s = obj; | |||
| return prev ? NULL : s->opaque; | |||
| } | |||
| static const AVClass *ffio_url_child_class_next(const AVClass *prev) | |||
| { | |||
| return prev ? NULL : &ffurl_context_class; | |||
| } | |||
| static const AVOption ffio_url_options[] = { | |||
| { NULL }, | |||
| }; | |||
| const AVClass ffio_url_class = { | |||
| .class_name = "AVIOContext", | |||
| .item_name = av_default_item_name, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| .option = ffio_url_options, | |||
| .child_next = ffio_url_child_next, | |||
| .child_class_next = ffio_url_child_class_next, | |||
| }; | |||
| #endif | |||
| static void fill_buffer(AVIOContext *s); | |||
| static int url_resetbuf(AVIOContext *s, int flags); | |||
| @@ -866,6 +894,9 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) | |||
| (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; | |||
| (*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; | |||
| } | |||
| #if !FF_API_OLD_AVIO | |||
| (*s)->av_class = &ffio_url_class; | |||
| #endif | |||
| return 0; | |||
| } | |||
| @@ -938,11 +969,17 @@ int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size | |||
| } | |||
| int avio_open(AVIOContext **s, const char *filename, int flags) | |||
| { | |||
| return avio_open2(s, filename, flags, NULL, NULL); | |||
| } | |||
| int avio_open2(AVIOContext **s, const char *filename, int flags, | |||
| const AVIOInterruptCB *int_cb, AVDictionary **options) | |||
| { | |||
| URLContext *h; | |||
| int err; | |||
| err = ffurl_open(&h, filename, flags); | |||
| err = ffurl_open(&h, filename, flags, int_cb, options); | |||
| if (err < 0) | |||
| return err; | |||
| err = ffio_fdopen(s, h); | |||
| @@ -72,7 +72,7 @@ static int cache_open(URLContext *h, const char *arg, int flags) | |||
| unlink(buffername); | |||
| av_free(buffername); | |||
| return ffurl_open(&c->inner, arg, flags); | |||
| return ffurl_open(&c->inner, arg, flags, &h->interrupt_callback, NULL); | |||
| } | |||
| static int cache_read(URLContext *h, unsigned char *buf, int size) | |||
| @@ -101,7 +101,8 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags) | |||
| uri += len + strspn(uri+len, AV_CAT_SEPARATOR); | |||
| /* creating URLContext */ | |||
| if ((err = ffurl_open(&uc, node_uri, flags)) < 0) | |||
| if ((err = ffurl_open(&uc, node_uri, flags, | |||
| &h->interrupt_callback, NULL)) < 0) | |||
| break; | |||
| /* creating size */ | |||
| @@ -82,7 +82,8 @@ static int crypto_open(URLContext *h, const char *uri, int flags) | |||
| ret = AVERROR(ENOSYS); | |||
| goto err; | |||
| } | |||
| if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ)) < 0) { | |||
| if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ, | |||
| &h->interrupt_callback, NULL)) < 0) { | |||
| av_log(h, AV_LOG_ERROR, "Unable to open input\n"); | |||
| goto err; | |||
| } | |||
| @@ -100,7 +100,8 @@ static int gopher_open(URLContext *h, const char *uri, int flags) | |||
| ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); | |||
| s->hd = NULL; | |||
| err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE); | |||
| err = ffurl_open(&s->hd, buf, AVIO_FLAG_READ_WRITE, | |||
| &h->interrupt_callback, NULL); | |||
| if (err < 0) | |||
| goto fail; | |||
| @@ -133,7 +133,8 @@ static int http_open_cnx(URLContext *h) | |||
| port = 80; | |||
| ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL); | |||
| err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE); | |||
| err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE, | |||
| &h->interrupt_callback, NULL); | |||
| if (err < 0) | |||
| goto fail; | |||
| @@ -310,7 +310,8 @@ static int read_packet(AVFormatContext *s1, AVPacket *pkt) | |||
| s->path, s->img_number)<0 && s->img_number > 1) | |||
| return AVERROR(EIO); | |||
| for(i=0; i<3; i++){ | |||
| if (avio_open(&f[i], filename, AVIO_FLAG_READ) < 0) { | |||
| if (avio_open2(&f[i], filename, AVIO_FLAG_READ, | |||
| &s1->interrupt_callback, NULL) < 0) { | |||
| if(i==1) | |||
| break; | |||
| av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename); | |||
| @@ -397,7 +398,8 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) | |||
| return AVERROR(EINVAL); | |||
| } | |||
| for(i=0; i<3; i++){ | |||
| if (avio_open(&pb[i], filename, AVIO_FLAG_WRITE) < 0) { | |||
| if (avio_open2(&pb[i], filename, AVIO_FLAG_WRITE, | |||
| &s->interrupt_callback, NULL) < 0) { | |||
| av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename); | |||
| return AVERROR(EIO); | |||
| } | |||
| @@ -65,7 +65,8 @@ static int md5_close(URLContext *h) | |||
| av_strstart(filename, "md5:", &filename); | |||
| if (*filename) { | |||
| err = ffurl_open(&out, filename, AVIO_FLAG_WRITE); | |||
| err = ffurl_open(&out, filename, AVIO_FLAG_WRITE, | |||
| &h->interrupt_callback, NULL); | |||
| if (err) | |||
| return err; | |||
| err = ffurl_write(out, buf, i*2+1); | |||
| @@ -234,7 +234,8 @@ static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int tim | |||
| port = 80; // default mmsh protocol port | |||
| ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path); | |||
| if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ) < 0) { | |||
| if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, | |||
| &h->interrupt_callback) < 0) { | |||
| return AVERROR(EIO); | |||
| } | |||
| @@ -249,7 +250,7 @@ static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int tim | |||
| host, port, mmsh->request_seq++); | |||
| av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0); | |||
| err = ffurl_connect(mms->mms_hd); | |||
| err = ffurl_connect(mms->mms_hd, NULL); | |||
| if (err) { | |||
| goto fail; | |||
| } | |||
| @@ -262,7 +263,8 @@ static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int tim | |||
| // close the socket and then reopen it for sending the second play request. | |||
| ffurl_close(mms->mms_hd); | |||
| memset(headers, 0, sizeof(headers)); | |||
| if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ) < 0) { | |||
| if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ, | |||
| &h->interrupt_callback) < 0) { | |||
| return AVERROR(EIO); | |||
| } | |||
| stream_selection = av_mallocz(mms->stream_num * 19 + 1); | |||
| @@ -296,7 +298,7 @@ static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int tim | |||
| av_dlog(NULL, "out_buffer is %s", headers); | |||
| av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0); | |||
| err = ffurl_connect(mms->mms_hd); | |||
| err = ffurl_connect(mms->mms_hd, NULL); | |||
| if (err) { | |||
| goto fail; | |||
| } | |||
| @@ -523,7 +523,8 @@ static int mms_open(URLContext *h, const char *uri, int flags) | |||
| // establish tcp connection. | |||
| ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); | |||
| err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE); | |||
| err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE, | |||
| &h->interrupt_callback, NULL); | |||
| if (err) | |||
| goto fail; | |||
| @@ -1837,7 +1837,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st) | |||
| } | |||
| } | |||
| static int mov_open_dref(AVIOContext **pb, const char *src, MOVDref *ref) | |||
| static int mov_open_dref(AVIOContext **pb, const char *src, MOVDref *ref, | |||
| AVIOInterruptCB *int_cb) | |||
| { | |||
| /* try relative path, we do not try the absolute because it can leak information about our | |||
| system to an attacker */ | |||
| @@ -1872,7 +1873,7 @@ static int mov_open_dref(AVIOContext **pb, const char *src, MOVDref *ref) | |||
| av_strlcat(filename, ref->path + l + 1, 1024); | |||
| if (!avio_open(pb, filename, AVIO_FLAG_READ)) | |||
| if (!avio_open2(pb, filename, AVIO_FLAG_READ, int_cb, NULL)) | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -1927,7 +1928,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) | |||
| if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { | |||
| MOVDref *dref = &sc->drefs[sc->dref_id - 1]; | |||
| if (mov_open_dref(&sc->pb, c->fc->filename, dref) < 0) | |||
| if (mov_open_dref(&sc->pb, c->fc->filename, dref, &c->fc->interrupt_callback) < 0) | |||
| av_log(c->fc, AV_LOG_ERROR, | |||
| "stream %d, error opening alias: path='%s', dir='%s', " | |||
| "filename='%s', volume='%s', nlvl_from=%d, nlvl_to=%d\n", | |||
| @@ -18,6 +18,7 @@ | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| #include "avformat.h" | |||
| #include "avio_internal.h" | |||
| #include "libavutil/opt.h" | |||
| /** | |||
| @@ -40,6 +41,10 @@ static void *format_child_next(void *obj, void *prev) | |||
| ((s->iformat && s->iformat->priv_class) || | |||
| s->oformat && s->oformat->priv_class)) | |||
| return s->priv_data; | |||
| #if !FF_API_OLD_AVIO | |||
| if (s->pb && s->pb->av_class && prev != s->pb) | |||
| return s->pb; | |||
| #endif | |||
| return NULL; | |||
| } | |||
| @@ -49,19 +54,29 @@ static const AVClass *format_child_class_next(const AVClass *prev) | |||
| AVOutputFormat *ofmt = NULL; | |||
| while (prev && (ifmt = av_iformat_next(ifmt))) | |||
| if (ifmt->priv_class == prev) | |||
| if (ifmt->priv_class == prev){ | |||
| prev = NULL; | |||
| break; | |||
| if ((prev && ifmt) || (!prev)) | |||
| } | |||
| if (!prev) | |||
| while (ifmt = av_iformat_next(ifmt)) | |||
| if (ifmt->priv_class) | |||
| return ifmt->priv_class; | |||
| while (prev && (ofmt = av_oformat_next(ofmt))) | |||
| if (ofmt->priv_class == prev) | |||
| if (ofmt->priv_class == prev){ | |||
| prev = NULL; | |||
| break; | |||
| while (ofmt = av_oformat_next(ofmt)) | |||
| if (ofmt->priv_class) | |||
| return ofmt->priv_class; | |||
| } | |||
| if (!prev) | |||
| while (ofmt = av_oformat_next(ofmt)) | |||
| if (ofmt->priv_class) | |||
| return ofmt->priv_class; | |||
| #if !FF_API_OLD_AVIO | |||
| if (prev != &ffio_url_class) | |||
| return &ffio_url_class; | |||
| #endif | |||
| return NULL; | |||
| } | |||
| @@ -817,7 +817,8 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) | |||
| port = RTMP_DEFAULT_PORT; | |||
| ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); | |||
| if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE) < 0) { | |||
| if (ffurl_open(&rt->stream, buf, AVIO_FLAG_READ_WRITE, | |||
| &s->interrupt_callback, NULL) < 0) { | |||
| av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf); | |||
| goto fail; | |||
| } | |||
| @@ -47,6 +47,8 @@ AVFormatContext *ff_rtp_chain_mux_open(AVFormatContext *s, AVStream *st, | |||
| av_free(rtpctx); | |||
| return NULL; | |||
| } | |||
| /* Pass the interrupt callback on */ | |||
| rtpctx->interrupt_callback = s->interrupt_callback; | |||
| /* Copy the max delay setting; the rtp muxer reads this. */ | |||
| rtpctx->max_delay = s->max_delay; | |||
| /* Copy other stream parameters. */ | |||
| @@ -189,7 +189,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) | |||
| build_udp_url(buf, sizeof(buf), | |||
| hostname, rtp_port, local_rtp_port, ttl, max_packet_size, | |||
| connect); | |||
| if (ffurl_open(&s->rtp_hd, buf, flags) < 0) | |||
| if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) | |||
| goto fail; | |||
| if (local_rtp_port>=0 && local_rtcp_port<0) | |||
| local_rtcp_port = ff_udp_get_local_port(s->rtp_hd) + 1; | |||
| @@ -197,7 +197,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) | |||
| build_udp_url(buf, sizeof(buf), | |||
| hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, | |||
| connect); | |||
| if (ffurl_open(&s->rtcp_hd, buf, flags) < 0) | |||
| if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) | |||
| goto fail; | |||
| /* just to ease handle access. XXX: need to suppress direct handle | |||
| @@ -227,7 +227,7 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) | |||
| struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}}; | |||
| for(;;) { | |||
| if (url_interrupt_cb()) | |||
| if (ff_check_interrupt(&h->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| /* build fdset to listen to RTP and RTCP packets */ | |||
| n = poll(p, 2, 100); | |||
| @@ -1159,7 +1159,8 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, | |||
| "?localport=%d", j); | |||
| /* we will use two ports per rtp stream (rtp and rtcp) */ | |||
| j += 2; | |||
| if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE) == 0) | |||
| if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE, | |||
| &s->interrupt_callback, NULL) == 0) | |||
| goto rtp_opened; | |||
| } | |||
| } | |||
| @@ -1306,7 +1307,8 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, | |||
| namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); | |||
| ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, | |||
| port, "?ttl=%d", ttl); | |||
| if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE) < 0) { | |||
| if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, | |||
| &s->interrupt_callback, NULL) < 0) { | |||
| err = AVERROR_INVALIDDATA; | |||
| goto fail; | |||
| } | |||
| @@ -1450,7 +1452,8 @@ redirect: | |||
| av_get_random_seed(), av_get_random_seed()); | |||
| /* GET requests */ | |||
| if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ) < 0) { | |||
| if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_FLAG_READ, | |||
| &s->interrupt_callback) < 0) { | |||
| err = AVERROR(EIO); | |||
| goto fail; | |||
| } | |||
| @@ -1465,13 +1468,14 @@ redirect: | |||
| av_opt_set(rt->rtsp_hd->priv_data, "headers", headers, 0); | |||
| /* complete the connection */ | |||
| if (ffurl_connect(rt->rtsp_hd)) { | |||
| if (ffurl_connect(rt->rtsp_hd, NULL)) { | |||
| err = AVERROR(EIO); | |||
| goto fail; | |||
| } | |||
| /* POST requests */ | |||
| if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE) < 0 ) { | |||
| if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_FLAG_WRITE, | |||
| &s->interrupt_callback) < 0 ) { | |||
| err = AVERROR(EIO); | |||
| goto fail; | |||
| } | |||
| @@ -1507,14 +1511,15 @@ redirect: | |||
| ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd); | |||
| /* complete the connection */ | |||
| if (ffurl_connect(rt->rtsp_hd_out)) { | |||
| if (ffurl_connect(rt->rtsp_hd_out, NULL)) { | |||
| err = AVERROR(EIO); | |||
| goto fail; | |||
| } | |||
| } else { | |||
| /* open the tcp connection */ | |||
| ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); | |||
| if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE) < 0) { | |||
| if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, | |||
| &s->interrupt_callback, NULL) < 0) { | |||
| err = AVERROR(EIO); | |||
| goto fail; | |||
| } | |||
| @@ -1619,7 +1624,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, | |||
| struct pollfd *p = rt->p; | |||
| for (;;) { | |||
| if (url_interrupt_cb()) | |||
| if (ff_check_interrupt(&s->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| if (wait_end && wait_end - av_gettime() < 0) | |||
| return AVERROR(EAGAIN); | |||
| @@ -1862,7 +1867,8 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| "?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port, | |||
| rtsp_st->sdp_ttl, | |||
| rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0); | |||
| if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE) < 0) { | |||
| if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, | |||
| &s->interrupt_callback, NULL) < 0) { | |||
| err = AVERROR_INVALIDDATA; | |||
| goto fail; | |||
| } | |||
| @@ -1926,7 +1932,8 @@ static int rtp_read_header(AVFormatContext *s, | |||
| if (!ff_network_init()) | |||
| return AVERROR(EIO); | |||
| ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ); | |||
| ret = ffurl_open(&in, s->filename, AVIO_FLAG_READ, | |||
| &s->interrupt_callback, NULL); | |||
| if (ret) | |||
| goto fail; | |||
| @@ -85,7 +85,8 @@ static int sap_read_header(AVFormatContext *s, | |||
| ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d", | |||
| port); | |||
| ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ); | |||
| ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ, | |||
| &s->interrupt_callback, NULL); | |||
| if (ret) | |||
| goto fail; | |||
| @@ -157,6 +158,7 @@ static int sap_read_header(AVFormatContext *s, | |||
| } | |||
| sap->sdp_ctx->max_delay = s->max_delay; | |||
| sap->sdp_ctx->pb = &sap->sdp_pb; | |||
| sap->sdp_ctx->interrupt_callback = s->interrupt_callback; | |||
| ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL); | |||
| if (ret < 0) | |||
| goto fail; | |||
| @@ -146,7 +146,7 @@ static int sap_write_header(AVFormatContext *s) | |||
| "?ttl=%d", ttl); | |||
| if (!same_port) | |||
| base_port += 2; | |||
| ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE); | |||
| ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); | |||
| if (ret) { | |||
| ret = AVERROR(EIO); | |||
| goto fail; | |||
| @@ -158,7 +158,8 @@ static int sap_write_header(AVFormatContext *s) | |||
| ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port, | |||
| "?ttl=%d&connect=1", ttl); | |||
| ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE); | |||
| ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, | |||
| &s->interrupt_callback, NULL); | |||
| if (ret) { | |||
| ret = AVERROR(EIO); | |||
| goto fail; | |||
| @@ -100,7 +100,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | |||
| struct pollfd p = {fd, POLLOUT, 0}; | |||
| ret = ff_neterrno(); | |||
| if (ret == AVERROR(EINTR)) { | |||
| if (url_interrupt_cb()) { | |||
| if (ff_check_interrupt(&h->interrupt_callback)) { | |||
| ret = AVERROR_EXIT; | |||
| goto fail1; | |||
| } | |||
| @@ -112,7 +112,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | |||
| /* wait until we are connected or until abort */ | |||
| while(timeout--) { | |||
| if (url_interrupt_cb()) { | |||
| if (ff_check_interrupt(&h->interrupt_callback)) { | |||
| ret = AVERROR_EXIT; | |||
| goto fail1; | |||
| } | |||
| @@ -97,7 +97,7 @@ static int do_tls_poll(URLContext *h, int ret) | |||
| int n = poll(&p, 1, 100); | |||
| if (n > 0) | |||
| break; | |||
| if (url_interrupt_cb()) | |||
| if (ff_check_interrupt(&h->interrupt_callback)) | |||
| return AVERROR(EINTR); | |||
| } | |||
| return 0; | |||
| @@ -123,7 +123,8 @@ static int tls_open(URLContext *h, const char *uri, int flags) | |||
| freeaddrinfo(ai); | |||
| } | |||
| ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE); | |||
| ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, | |||
| &h->interrupt_callback, NULL); | |||
| if (ret) | |||
| goto fail; | |||
| c->fd = ffurl_get_file_handle(c->tcp); | |||
| @@ -28,11 +28,16 @@ | |||
| #include "avio.h" | |||
| #include "libavformat/version.h" | |||
| #include "libavutil/dict.h" | |||
| #include "libavutil/log.h" | |||
| #if !FF_API_OLD_AVIO | |||
| #define URL_PROTOCOL_FLAG_NESTED_SCHEME 1 /*< The protocol name can be the first part of a nested protocol scheme */ | |||
| extern int (*url_interrupt_cb)(void); | |||
| extern const AVClass ffurl_context_class; | |||
| typedef struct URLContext { | |||
| const AVClass *av_class; /**< information for av_log(). Set by url_open(). */ | |||
| struct URLProtocol *prot; | |||
| @@ -42,11 +47,18 @@ typedef struct URLContext { | |||
| int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */ | |||
| int is_streamed; /**< true if streamed (no seek possible), default = false */ | |||
| int is_connected; | |||
| AVIOInterruptCB interrupt_callback; | |||
| } URLContext; | |||
| typedef struct URLProtocol { | |||
| const char *name; | |||
| int (*url_open)( URLContext *h, const char *url, int flags); | |||
| /** | |||
| * This callback is to be used by protocols which open further nested | |||
| * protocols. options are then to be passed to ffurl_open()/ffurl_connect() | |||
| * for those nested protocols. | |||
| */ | |||
| int (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options); | |||
| int (*url_read)( URLContext *h, unsigned char *buf, int size); | |||
| int (*url_write)(URLContext *h, const unsigned char *buf, int size); | |||
| int64_t (*url_seek)( URLContext *h, int64_t pos, int whence); | |||
| @@ -71,15 +83,23 @@ typedef struct URLProtocol { | |||
| * function puts the pointer to the created URLContext | |||
| * @param flags flags which control how the resource indicated by url | |||
| * is to be opened | |||
| * @param int_cb interrupt callback to use for the URLContext, may be | |||
| * NULL | |||
| * @return 0 in case of success, a negative value corresponding to an | |||
| * AVERROR code in case of failure | |||
| */ | |||
| int ffurl_alloc(URLContext **puc, const char *filename, int flags); | |||
| int ffurl_alloc(URLContext **puc, const char *filename, int flags, | |||
| const AVIOInterruptCB *int_cb); | |||
| /** | |||
| * Connect an URLContext that has been allocated by ffurl_alloc | |||
| * | |||
| * @param options A dictionary filled with options for nested protocols, | |||
| * i.e. it will be passed to url_open2() for protocols implementing it. | |||
| * This parameter will be destroyed and replaced with a dict containing options | |||
| * that were not found. May be NULL. | |||
| */ | |||
| int ffurl_connect(URLContext *uc); | |||
| int ffurl_connect(URLContext *uc, AVDictionary **options); | |||
| /** | |||
| * Create an URLContext for accessing to the resource indicated by | |||
| @@ -89,10 +109,16 @@ int ffurl_connect(URLContext *uc); | |||
| * function puts the pointer to the created URLContext | |||
| * @param flags flags which control how the resource indicated by url | |||
| * is to be opened | |||
| * @param int_cb interrupt callback to use for the URLContext, may be | |||
| * NULL | |||
| * @param options A dictionary filled with protocol-private options. On return | |||
| * this parameter will be destroyed and replaced with a dict containing options | |||
| * that were not found. May be NULL. | |||
| * @return 0 in case of success, a negative value corresponding to an | |||
| * AVERROR code in case of failure | |||
| */ | |||
| int ffurl_open(URLContext **puc, const char *filename, int flags); | |||
| int ffurl_open(URLContext **puc, const char *filename, int flags, | |||
| const AVIOInterruptCB *int_cb, AVDictionary **options); | |||
| /** | |||
| * Read up to size bytes from the resource accessed by h, and store | |||
| @@ -169,6 +195,19 @@ int ffurl_get_file_handle(URLContext *h); | |||
| */ | |||
| int ffurl_register_protocol(URLProtocol *protocol, int size); | |||
| /** | |||
| * Check if the user has requested to interrup a blocking function | |||
| * associated with cb. | |||
| */ | |||
| int ff_check_interrupt(AVIOInterruptCB *cb); | |||
| /** | |||
| * Iterate over all available protocols. | |||
| * | |||
| * @param prev result of the previous call to this functions or NULL. | |||
| */ | |||
| URLProtocol *ffurl_protocol_next(URLProtocol *prev); | |||
| /* udp.c */ | |||
| int ff_udp_set_remote_url(URLContext *h, const char *uri); | |||
| int ff_udp_get_local_port(URLContext *h); | |||
| @@ -602,7 +602,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, | |||
| #endif | |||
| /* open input file and probe the format if necessary */ | |||
| static int init_input(AVFormatContext *s, const char *filename) | |||
| static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options) | |||
| { | |||
| int ret; | |||
| AVProbeData pd = {filename, NULL, 0}; | |||
| @@ -624,7 +624,8 @@ static int init_input(AVFormatContext *s, const char *filename) | |||
| (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0)))) | |||
| return 0; | |||
| if ((ret = avio_open(&s->pb, filename, AVIO_FLAG_READ)) < 0) | |||
| if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ, | |||
| &s->interrupt_callback, options)) < 0) | |||
| return ret; | |||
| if (s->iformat) | |||
| return 0; | |||
| @@ -649,7 +650,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma | |||
| if ((ret = av_opt_set_dict(s, &tmp)) < 0) | |||
| goto fail; | |||
| if ((ret = init_input(s, filename)) < 0) | |||
| if ((ret = init_input(s, filename, &tmp)) < 0) | |||
| goto fail; | |||
| /* check filename in case an image number is expected */ | |||
| @@ -2396,7 +2397,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) | |||
| count = 0; | |||
| read_size = 0; | |||
| for(;;) { | |||
| if(url_interrupt_cb()){ | |||
| if (ff_check_interrupt(&ic->interrupt_callback)){ | |||
| ret= AVERROR_EXIT; | |||
| av_log(ic, AV_LOG_DEBUG, "interrupted\n"); | |||
| break; | |||
| @@ -720,6 +720,8 @@ yuv2planeX_fn avx, 10, 7, 5 | |||
| %macro yuv2plane1_fn 3 | |||
| cglobal yuv2plane1_%1, %3, %3, %2 | |||
| add r2, mmsize - 1 | |||
| and r2, ~(mmsize - 1) | |||
| %if %1 == 8 | |||
| add r1, r2 | |||
| %else ; %1 != 8 | |||