diff --git a/INSTALL b/INSTALL index 8cd22bd441..9549346302 100644 --- a/INSTALL +++ b/INSTALL @@ -9,3 +9,7 @@ path when launching 'configure', e.g. '/ffmpegdir/ffmpeg/configure'. 2) Then type 'make' to build FFmpeg. GNU Make 3.81 or later is required. 3) Type 'make install' to install all binaries and libraries you built. + +NOTICE + + - Non system dependencies (e.g. libx264, libvpx) are disabled by default. diff --git a/doc/protocols.texi b/doc/protocols.texi index 3c57129ce0..a71c262368 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -402,6 +402,23 @@ ffplay sap://[ff0e::2:7ffe] Trasmission Control Protocol. +The required syntax for a TCP url is: +@example +tcp://@var{hostname}:@var{port}[?@var{options}] +@end example + +@table @option + +@item listen +Listen for an incoming connection + +@example +ffmpeg -i @var{input} -f @var{format} tcp://@var{hostname}:@var{port}?listen +ffplay tcp://@var{hostname}:@var{port} +@end example + +@end table + @section udp User Datagram Protocol. diff --git a/ffmpeg.c b/ffmpeg.c index e147363011..40e5e67ee4 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -2569,7 +2569,7 @@ static int transcode(AVFormatContext **output_files, if (!using_stdin) { if(verbose >= 0) fprintf(stderr, "Press [q] to stop encoding\n"); - url_set_interrupt_cb(decode_interrupt_cb); + avio_set_interrupt_cb(decode_interrupt_cb); } term_init(); @@ -3887,7 +3887,7 @@ static void opt_output_file(const char *filename) } /* open the file */ - if ((err = avio_open(&oc->pb, filename, URL_WRONLY)) < 0) { + if ((err = avio_open(&oc->pb, filename, AVIO_WRONLY)) < 0) { print_error(filename, err); ffmpeg_exit(1); } @@ -4426,7 +4426,7 @@ int main(int argc, char **argv) #if HAVE_ISATTY if(isatty(STDIN_FILENO)) - url_set_interrupt_cb(decode_interrupt_cb); + avio_set_interrupt_cb(decode_interrupt_cb); #endif init_opts(); diff --git a/ffplay.c b/ffplay.c index e3e6e378dc..cd515fa565 100644 --- a/ffplay.c +++ b/ffplay.c @@ -2406,7 +2406,7 @@ static int decode_thread(void *arg) is->subtitle_stream = -1; global_video_state = is; - url_set_interrupt_cb(decode_interrupt_cb); + avio_set_interrupt_cb(decode_interrupt_cb); memset(ap, 0, sizeof(*ap)); @@ -2626,7 +2626,7 @@ static int decode_thread(void *arg) av_close_input_file(is->ic); is->ic = NULL; /* safety */ } - url_set_interrupt_cb(NULL); + avio_set_interrupt_cb(NULL); if (ret != 0) { SDL_Event event; diff --git a/ffserver.c b/ffserver.c index 50f050ce30..6e429799ae 100644 --- a/ffserver.c +++ b/ffserver.c @@ -3427,7 +3427,7 @@ static int rtp_new_av_stream(HTTPContext *c, "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port)); } - if (url_open(&h, ctx->filename, URL_WRONLY) < 0) + if (url_open(&h, ctx->filename, AVIO_WRONLY) < 0) goto fail; c->rtp_handles[stream_index] = h; max_packet_size = url_get_max_packet_size(h); @@ -3767,7 +3767,7 @@ static void build_feed_streams(void) } /* only write the header of the ffm file */ - if (avio_open(&s->pb, feed->feed_filename, URL_WRONLY) < 0) { + if (avio_open(&s->pb, feed->feed_filename, AVIO_WRONLY) < 0) { http_log("Could not open output feed file '%s'\n", feed->feed_filename); exit(1); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c6fb2efaf4..f3d255c75e 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2601,7 +2601,7 @@ typedef struct AVCodecContext { */ int64_t timecode_frame_start; -#if LIBAVCODEC_VERSION_MAJOR < 53 +#if FF_API_REQUEST_CHANNELS /** * Decoder should decode to this many channels if it can (0 for default) * - encoding: unused diff --git a/libavcodec/options.c b/libavcodec/options.c index f6010bc638..404398fed6 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -408,7 +408,9 @@ static const AVOption options[]={ {"timecode_frame_start", "GOP timecode frame start number, in non drop frame format", OFFSET(timecode_frame_start), FF_OPT_TYPE_INT64, 0, 0, INT64_MAX, V|E}, {"drop_frame_timecode", NULL, 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_DROP_FRAME_TIMECODE, INT_MIN, INT_MAX, V|E, "flags2"}, {"non_linear_q", "use non linear quantizer", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_NON_LINEAR_QUANT, INT_MIN, INT_MAX, V|E, "flags2"}, +#if FF_API_REQUEST_CHANNELS {"request_channels", "set desired number of audio channels", OFFSET(request_channels), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, A|D}, +#endif {"drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), FF_OPT_TYPE_FLOAT, 1.0, 0.0, 1.0, A|D}, {"reservoir", "use bit reservoir", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_BIT_RESERVOIR, INT_MIN, INT_MAX, A|E, "flags2"}, {"mbtree", "use macroblock tree ratecontrol (x264 only)", 0, FF_OPT_TYPE_CONST, CODEC_FLAG2_MBTREE, INT_MIN, INT_MAX, V|E, "flags2"}, diff --git a/libavcodec/version.h b/libavcodec/version.h index b93e7534bb..b60e264d7f 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -83,5 +83,8 @@ #ifndef FF_API_ANTIALIAS_ALGO #define FF_API_ANTIALIAS_ALGO (LIBAVCODEC_VERSION_MAJOR < 54) #endif +#ifndef FF_API_REQUEST_CHANNELS +#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 53) +#endif #endif /* AVCODEC_VERSION_H */ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index ba4eac35e1..f0e98eddbe 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -21,6 +21,7 @@ #include "avformat.h" #include "rtp.h" #include "rdt.h" +#include "url.h" #define REGISTER_MUXER(X,x) { \ extern AVOutputFormat ff_##x##_muxer; \ @@ -34,7 +35,7 @@ #define REGISTER_PROTOCOL(X,x) { \ extern URLProtocol ff_##x##_protocol; \ - if(CONFIG_##X##_PROTOCOL) av_register_protocol2(&ff_##x##_protocol, sizeof(ff_##x##_protocol)); } + if(CONFIG_##X##_PROTOCOL) ffurl_register_protocol(&ff_##x##_protocol, sizeof(ff_##x##_protocol)); } void av_register_all(void) { diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c index 639cfcdce4..44a27a510e 100644 --- a/libavformat/applehttp.c +++ b/libavformat/applehttp.c @@ -31,6 +31,7 @@ #include "internal.h" #include #include "avio_internal.h" +#include "url.h" #define INITIAL_BUFFER_SIZE 32768 @@ -169,7 +170,7 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, if (!in) { close_in = 1; - if ((ret = avio_open(&in, url, URL_RDONLY)) < 0) + if ((ret = avio_open(&in, url, AVIO_RDONLY)) < 0) return ret; } @@ -292,7 +293,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size) ret = url_open(&v->input, v->segments[v->cur_seq_no - v->start_seq_no]->url, - URL_RDONLY); + AVIO_RDONLY); if (ret < 0) return ret; } diff --git a/libavformat/applehttpproto.c b/libavformat/applehttpproto.c index 168b2513bb..850292af2d 100644 --- a/libavformat/applehttpproto.c +++ b/libavformat/applehttpproto.c @@ -115,7 +115,7 @@ static int parse_playlist(URLContext *h, const char *url) char line[1024]; const char *ptr; - if ((ret = avio_open(&in, url, URL_RDONLY)) < 0) + if ((ret = avio_open(&in, url, AVIO_RDONLY)) < 0) return ret; read_chomp_line(in, line, sizeof(line)); @@ -180,7 +180,7 @@ static int applehttp_open(URLContext *h, const char *uri, int flags) int ret, i; const char *nested_url; - if (flags & (URL_WRONLY | URL_RDWR)) + if (flags & (AVIO_WRONLY | AVIO_RDWR)) return AVERROR(ENOSYS); s = av_mallocz(sizeof(AppleHTTPContext)); @@ -275,7 +275,7 @@ static int applehttp_read(URLContext *h, uint8_t *buf, int size) } url = s->segments[s->cur_seq_no - s->start_seq_no]->url, av_log(NULL, AV_LOG_DEBUG, "opening %s\n", url); - ret = ffurl_open(&s->seg_hd, url, URL_RDONLY); + ret = ffurl_open(&s->seg_hd, url, AVIO_RDONLY); if (ret < 0) { if (url_interrupt_cb()) return AVERROR_EXIT; diff --git a/libavformat/avio.c b/libavformat/avio.c index ddaafc84ea..7b066e3c08 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -57,7 +57,7 @@ URLProtocol *av_protocol_next(URLProtocol *p) else return first_protocol; } -int av_register_protocol2(URLProtocol *protocol, int size) +int ffurl_register_protocol(URLProtocol *protocol, int size) { URLProtocol **p; if (size < sizeof(URLProtocol)) { @@ -86,12 +86,12 @@ struct URLProtocol_compat { int av_register_protocol(URLProtocol *protocol) { - return av_register_protocol2(protocol, sizeof(struct URLProtocol_compat)); + return ffurl_register_protocol(protocol, sizeof(struct URLProtocol_compat)); } int register_protocol(URLProtocol *protocol) { - return av_register_protocol2(protocol, sizeof(struct URLProtocol_compat)); + return ffurl_register_protocol(protocol, sizeof(struct URLProtocol_compat)); } #endif @@ -144,7 +144,7 @@ int ffurl_connect(URLContext* uc) return err; uc->is_connected = 1; //We must be careful here as ffurl_seek() could be slow, for example for http - if( (uc->flags & (URL_WRONLY | URL_RDWR)) + if( (uc->flags & (AVIO_WRONLY | AVIO_RDWR)) || !strcmp(uc->prot->name, "file")) if(!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0) uc->is_streamed= 1; @@ -216,6 +216,14 @@ void url_get_filename(URLContext *h, char *buf, int buf_size) { av_strlcpy(buf, h->filename, buf_size); } +void url_set_interrupt_cb(URLInterruptCB *interrupt_cb) +{ + avio_set_interrupt_cb(interrupt_cb); +} +int av_register_protocol2(URLProtocol *protocol, int size) +{ + return ffurl_register_protocol(protocol, size); +} #endif #define URL_SCHEME_CHARS \ @@ -275,7 +283,7 @@ static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int ret = transfer_func(h, buf+len, size-len); if (ret == AVERROR(EINTR)) continue; - if (h->flags & URL_FLAG_NONBLOCK) + if (h->flags & AVIO_FLAG_NONBLOCK) return ret; if (ret == AVERROR(EAGAIN)) { ret = 0; @@ -296,21 +304,21 @@ static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int int ffurl_read(URLContext *h, unsigned char *buf, int size) { - if (h->flags & URL_WRONLY) + if (h->flags & AVIO_WRONLY) return AVERROR(EIO); return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read); } int ffurl_read_complete(URLContext *h, unsigned char *buf, int size) { - if (h->flags & URL_WRONLY) + if (h->flags & AVIO_WRONLY) return AVERROR(EIO); return retry_transfer_wrapper(h, buf, size, size, h->prot->url_read); } int ffurl_write(URLContext *h, const unsigned char *buf, int size) { - if (!(h->flags & (URL_WRONLY | URL_RDWR))) + if (!(h->flags & (AVIO_WRONLY | AVIO_RDWR))) return AVERROR(EIO); /* avoid sending too big packets */ if (h->max_packet_size && size > h->max_packet_size) @@ -348,7 +356,7 @@ int ffurl_close(URLContext *h) int url_exist(const char *filename) { URLContext *h; - if (ffurl_open(&h, filename, URL_RDONLY) < 0) + if (ffurl_open(&h, filename, AVIO_RDONLY) < 0) return 0; ffurl_close(h); return 1; @@ -381,7 +389,7 @@ static int default_interrupt_cb(void) return 0; } -void url_set_interrupt_cb(URLInterruptCB *interrupt_cb) +void avio_set_interrupt_cb(URLInterruptCB *interrupt_cb) { if (!interrupt_cb) interrupt_cb = default_interrupt_cb; diff --git a/libavformat/avio.h b/libavformat/avio.h index dd22acfed7..03b6f6f5ec 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -63,7 +63,6 @@ typedef struct URLPollEntry { int events; int revents; } URLPollEntry; -#endif /** * @defgroup open_modes URL open modes @@ -91,6 +90,7 @@ typedef struct URLPollEntry { * silently ignored. */ #define URL_FLAG_NONBLOCK 4 +#endif typedef int URLInterruptCB(void); @@ -117,6 +117,7 @@ attribute_deprecated void url_get_filename(URLContext *h, char *buf, int buf_siz attribute_deprecated int av_url_read_pause(URLContext *h, int pause); attribute_deprecated int64_t av_url_read_seek(URLContext *h, int stream_index, int64_t timestamp, int flags); +attribute_deprecated void url_set_interrupt_cb(URLInterruptCB *interrupt_cb); #endif /** @@ -131,7 +132,7 @@ int url_exist(const char *url); * in this case by the interrupted function. 'NULL' means no interrupt * callback is given. */ -void url_set_interrupt_cb(URLInterruptCB *interrupt_cb); +void avio_set_interrupt_cb(URLInterruptCB *interrupt_cb); #if FF_API_OLD_AVIO /* not implemented */ @@ -162,7 +163,9 @@ typedef struct URLProtocol { extern URLProtocol *first_protocol; #endif +#if FF_API_OLD_AVIO extern URLInterruptCB *url_interrupt_cb; +#endif /** * If protocol is NULL, returns the first registered protocol, @@ -183,12 +186,14 @@ attribute_deprecated int register_protocol(URLProtocol *protocol); attribute_deprecated int av_register_protocol(URLProtocol *protocol); #endif +#if FF_API_OLD_AVIO /** * Register the URLProtocol protocol. * * @param size the size of the URLProtocol struct referenced */ -int av_register_protocol2(URLProtocol *protocol, int size); +attribute_deprecated int av_register_protocol2(URLProtocol *protocol, int size); +#endif #define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */ @@ -510,6 +515,33 @@ attribute_deprecated static inline int url_is_streamed(AVIOContext *s) int url_resetbuf(AVIOContext *s, int flags); #endif +/** + * @defgroup open_modes URL open modes + * The flags argument to avio_open must be one of the following + * constants, optionally ORed with other flags. + * @{ + */ +#define AVIO_RDONLY 0 /**< read-only */ +#define AVIO_WRONLY 1 /**< write-only */ +#define AVIO_RDWR 2 /**< read-write */ +/** + * @} + */ + +/** + * Use non-blocking mode. + * If this flag is set, operations on the context will return + * AVERROR(EAGAIN) if they can not be performed immediately. + * If this flag is not set, operations on the context will never return + * AVERROR(EAGAIN). + * Note that this flag does not affect the opening/connecting of the + * context. Connecting a protocol will always block if necessary (e.g. on + * network protocols) but never hang (e.g. on busy devices). + * Warning: non-blocking protocols is work-in-progress; this flag may be + * silently ignored. + */ +#define AVIO_FLAG_NONBLOCK 4 + /** * Create and initialize a AVIOContext for accessing the * resource indicated by url. diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 1472380acf..fb6a0c7b69 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -55,7 +55,7 @@ int ffio_init_context(AVIOContext *s, s->buffer_size = buffer_size; s->buf_ptr = buffer; s->opaque = opaque; - url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY); + url_resetbuf(s, write_flag ? AVIO_WRONLY : AVIO_RDONLY); s->write_packet = write_packet; s->read_packet = read_packet; s->seek = seek; @@ -854,7 +854,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) } if (ffio_init_context(*s, buffer, buffer_size, - (h->flags & URL_WRONLY || h->flags & URL_RDWR), h, + (h->flags & AVIO_WRONLY || h->flags & AVIO_RDWR), h, ffurl_read, ffurl_write, ffurl_seek) < 0) { av_free(buffer); av_freep(s); @@ -883,7 +883,7 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size) s->buffer = buffer; s->buffer_size = buf_size; s->buf_ptr = buffer; - url_resetbuf(s, s->write_flag ? URL_WRONLY : URL_RDONLY); + url_resetbuf(s, s->write_flag ? AVIO_WRONLY : AVIO_RDONLY); return 0; } @@ -894,13 +894,13 @@ static int url_resetbuf(AVIOContext *s, int flags) #endif { #if FF_API_URL_RESETBUF - if (flags & URL_RDWR) + if (flags & AVIO_RDWR) return AVERROR(EINVAL); #else - assert(flags == URL_WRONLY || flags == URL_RDONLY); + assert(flags == AVIO_WRONLY || flags == AVIO_RDONLY); #endif - if (flags & URL_WRONLY) { + if (flags & AVIO_WRONLY) { s->buf_end = s->buffer + s->buffer_size; s->write_flag = 1; } else { @@ -1058,7 +1058,7 @@ int url_open_buf(AVIOContext **s, uint8_t *buf, int buf_size, int flags) if(!*s) return AVERROR(ENOMEM); ret = ffio_init_context(*s, buf, buf_size, - (flags & URL_WRONLY || flags & URL_RDWR), + (flags & AVIO_WRONLY || flags & AVIO_RDWR), NULL, NULL, NULL, NULL); if(ret != 0) av_freep(s); diff --git a/libavformat/file.c b/libavformat/file.c index 4f14b9f6c6..b8c7c4c9d4 100644 --- a/libavformat/file.c +++ b/libavformat/file.c @@ -59,9 +59,9 @@ static int file_open(URLContext *h, const char *filename, int flags) av_strstart(filename, "file:", &filename); - if (flags & URL_RDWR) { + if (flags & AVIO_RDWR) { access = O_CREAT | O_TRUNC | O_RDWR; - } else if (flags & URL_WRONLY) { + } else if (flags & AVIO_WRONLY) { access = O_CREAT | O_TRUNC | O_WRONLY; } else { access = O_RDONLY; @@ -116,7 +116,7 @@ static int pipe_open(URLContext *h, const char *filename, int flags) fd = strtol(filename, &final, 10); if((filename == final) || *final ) {/* No digits found, or something like 10ab */ - if (flags & URL_WRONLY) { + if (flags & AVIO_WRONLY) { fd = 1; } else { fd = 0; diff --git a/libavformat/gopher.c b/libavformat/gopher.c index 85a9d965c4..6f80c1bc84 100644 --- a/libavformat/gopher.c +++ b/libavformat/gopher.c @@ -100,7 +100,7 @@ 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, URL_RDWR); + err = ffurl_open(&s->hd, buf, AVIO_RDWR); if (err < 0) goto fail; diff --git a/libavformat/http.c b/libavformat/http.c index 8c6181417a..51e84850f2 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -124,7 +124,7 @@ static int http_open_cnx(URLContext *h) port = 80; ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); - err = ffurl_open(&hd, buf, URL_RDWR); + err = ffurl_open(&hd, buf, AVIO_RDWR); if (err < 0) goto fail; @@ -296,7 +296,7 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr, /* send http header */ - post = h->flags & URL_WRONLY; + post = h->flags & AVIO_WRONLY; authstr = ff_http_auth_create_response(&s->auth_state, auth, path, post ? "POST" : "GET"); @@ -451,7 +451,7 @@ static int http_close(URLContext *h) HTTPContext *s = h->priv_data; /* signal end of chunked encoding if used */ - if ((h->flags & URL_WRONLY) && s->chunksize != -1) { + if ((h->flags & AVIO_WRONLY) && s->chunksize != -1) { ret = ffurl_write(s->hd, footer, sizeof(footer) - 1); ret = ret > 0 ? 0 : ret; } diff --git a/libavformat/img2.c b/libavformat/img2.c index 7480d43bfe..4e55c22ccc 100644 --- a/libavformat/img2.c +++ b/libavformat/img2.c @@ -274,7 +274,7 @@ 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, URL_RDONLY) < 0) { + if (avio_open(&f[i], filename, AVIO_RDONLY) < 0) { if(i==1) break; av_log(s1, AV_LOG_ERROR, "Could not open file : %s\n",filename); @@ -361,7 +361,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EIO); } for(i=0; i<3; i++){ - if (avio_open(&pb[i], filename, URL_WRONLY) < 0) { + if (avio_open(&pb[i], filename, AVIO_WRONLY) < 0) { av_log(s, AV_LOG_ERROR, "Could not open file : %s\n",filename); return AVERROR(EIO); } diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c index 632ac95dd3..352d58fd4b 100644 --- a/libavformat/librtmp.c +++ b/libavformat/librtmp.c @@ -93,7 +93,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) goto fail; } - if (flags & URL_WRONLY) + if (flags & AVIO_WRONLY) RTMP_EnableWrite(r); if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) { diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index e69b848f78..55f62b8f6f 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1333,7 +1333,7 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) && track->codec_priv.size >= 14 && track->codec_priv.data != NULL) { ffio_init_context(&b, track->codec_priv.data, track->codec_priv.size, - URL_RDONLY, NULL, NULL, NULL, NULL); + AVIO_RDONLY, NULL, NULL, NULL, NULL); ff_get_wav_header(&b, st->codec, track->codec_priv.size); codec_id = st->codec->codec_id; extradata_offset = FFMIN(track->codec_priv.size, 18); diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 732a5855ab..5ce2a541da 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1144,10 +1144,13 @@ static int mkv_write_trailer(AVFormatContext *s) } if (pb->seekable) { - cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); + if (mkv->cues->num_entries) { + cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); + + ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES, cuespos); + if (ret < 0) return ret; + } - ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , cuespos); - if (ret < 0) return ret; mkv_write_seekhead(pb, mkv->main_seekhead); // update the duration diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c index 421808bb8a..35a0d31305 100644 --- a/libavformat/md5proto.c +++ b/libavformat/md5proto.c @@ -36,7 +36,7 @@ static int md5_open(URLContext *h, const char *filename, int flags) return -1; } - if (flags != URL_WRONLY) + if (flags != AVIO_WRONLY) return AVERROR(EINVAL); av_md5_init(h->priv_data); @@ -65,7 +65,7 @@ static int md5_close(URLContext *h) av_strstart(filename, "md5:", &filename); if (*filename) { - err = ffurl_open(&out, filename, URL_WRONLY); + err = ffurl_open(&out, filename, AVIO_WRONLY); if (err) return err; err = ffurl_write(out, buf, i*2+1); diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index 476596c78f..70664b9776 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -233,7 +233,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) port = 80; // default mmsh protocol port ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, path); - if (ffurl_alloc(&mms->mms_hd, httpname, URL_RDONLY) < 0) { + if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_RDONLY) < 0) { return AVERROR(EIO); } @@ -261,7 +261,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) // 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, URL_RDONLY) < 0) { + if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_RDONLY) < 0) { return AVERROR(EIO); } stream_selection = av_mallocz(mms->stream_num * 19 + 1); diff --git a/libavformat/mmst.c b/libavformat/mmst.c index d7a1dda5bd..55a41e6a9c 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -523,7 +523,7 @@ 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, URL_RDWR); + err = ffurl_open(&mms->mms_hd, tcpname, AVIO_RDWR); if (err) goto fail; diff --git a/libavformat/mov.c b/libavformat/mov.c index a4cd4d6b28..89b9adc7af 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1722,7 +1722,7 @@ static int mov_open_dref(AVIOContext **pb, char *src, MOVDref *ref) av_strlcat(filename, ref->path + l + 1, 1024); - if (!avio_open(pb, filename, URL_RDONLY)) + if (!avio_open(pb, filename, AVIO_RDONLY)) return 0; } } diff --git a/libavformat/network.h b/libavformat/network.h index 58a8e80e72..74e6f0bbcc 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -22,6 +22,7 @@ #define AVFORMAT_NETWORK_H #include "config.h" +#include "os_support.h" #if HAVE_WINSOCK2_H #include @@ -55,6 +56,10 @@ static inline int ff_neterrno() { #include #endif +#if HAVE_POLL_H +#include +#endif + int ff_socket_nonblock(int socket, int enable); static inline int ff_network_init(void) @@ -67,6 +72,15 @@ static inline int ff_network_init(void) return 1; } +static inline int ff_network_wait_fd(int fd, int write) +{ + int ev = write ? POLLOUT : POLLIN; + struct pollfd p = { .fd = fd, .events = ev, .revents = 0 }; + int ret; + ret = poll(&p, 1, 100); + return ret < 0 ? ff_neterrno() : p.revents & ev ? 0 : AVERROR(EAGAIN); +} + static inline void ff_network_close(void) { #if HAVE_WINSOCK2_H diff --git a/libavformat/output-example.c b/libavformat/output-example.c index b6be2b97db..27db78c658 100644 --- a/libavformat/output-example.c +++ b/libavformat/output-example.c @@ -492,7 +492,7 @@ int main(int argc, char **argv) /* open the output file, if needed */ if (!(fmt->flags & AVFMT_NOFILE)) { - if (avio_open(&oc->pb, filename, URL_WRONLY) < 0) { + if (avio_open(&oc->pb, filename, AVIO_WRONLY) < 0) { fprintf(stderr, "Could not open '%s'\n", filename); exit(1); } diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 3309038b34..73bb4d2f69 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -812,7 +812,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) if (!rt) return AVERROR(ENOMEM); s->priv_data = rt; - rt->is_input = !(flags & URL_WRONLY); + rt->is_input = !(flags & AVIO_WRONLY); av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), s->filename); @@ -821,7 +821,7 @@ 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, URL_RDWR) < 0) { + if (ffurl_open(&rt->stream, buf, AVIO_RDWR) < 0) { av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot open connection %s\n", buf); goto fail; } diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 08f6c0a1e1..3e582c1937 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -145,7 +145,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) char path[1024]; const char *p; - is_output = (flags & URL_WRONLY); + is_output = (flags & AVIO_WRONLY); s = av_mallocz(sizeof(RTPContext)); if (!s) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 1eba0cbcfe..8afca34240 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1116,14 +1116,14 @@ 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, URL_RDWR) == 0) + if (ffurl_open(&rtsp_st->rtp_handle, buf, AVIO_RDWR) == 0) goto rtp_opened; } } #if 0 /* then try on any port */ - if (ffurl_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { + if (ffurl_open(&rtsp_st->rtp_handle, "rtp://", AVIO_RDONLY) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1269,7 +1269,7 @@ 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, URL_RDWR) < 0) { + if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1396,7 +1396,7 @@ int ff_rtsp_connect(AVFormatContext *s) av_get_random_seed(), av_get_random_seed()); /* GET requests */ - if (ffurl_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) { + if (ffurl_alloc(&rt->rtsp_hd, httpname, AVIO_RDONLY) < 0) { err = AVERROR(EIO); goto fail; } @@ -1417,7 +1417,7 @@ int ff_rtsp_connect(AVFormatContext *s) } /* POST requests */ - if (ffurl_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) { + if (ffurl_alloc(&rt->rtsp_hd_out, httpname, AVIO_WRONLY) < 0 ) { err = AVERROR(EIO); goto fail; } @@ -1460,7 +1460,7 @@ int ff_rtsp_connect(AVFormatContext *s) } else { /* open the tcp connection */ ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); - if (ffurl_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) { + if (ffurl_open(&rt->rtsp_hd, tcpname, AVIO_RDWR) < 0) { err = AVERROR(EIO); goto fail; } @@ -1807,7 +1807,7 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) namebuf, rtsp_st->sdp_port, "?localport=%d&ttl=%d", rtsp_st->sdp_port, rtsp_st->sdp_ttl); - if (ffurl_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { + if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1863,7 +1863,7 @@ static int rtp_read_header(AVFormatContext *s, if (!ff_network_init()) return AVERROR(EIO); - ret = ffurl_open(&in, s->filename, URL_RDONLY); + ret = ffurl_open(&in, s->filename, AVIO_RDONLY); if (ret) goto fail; diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c index 42507d34f1..2c4bc8689e 100644 --- a/libavformat/sapdec.c +++ b/libavformat/sapdec.c @@ -85,7 +85,7 @@ 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, URL_RDONLY); + ret = ffurl_open(&sap->ann_fd, url, AVIO_RDONLY); if (ret) goto fail; diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 0569d790ce..e538bbb4a2 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -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, URL_WRONLY); + ret = ffurl_open(&fd, url, AVIO_WRONLY); if (ret) { ret = AVERROR(EIO); goto fail; @@ -158,7 +158,7 @@ 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, URL_WRONLY); + ret = ffurl_open(&sap->ann_fd, url, AVIO_WRONLY); if (ret) { ret = AVERROR(EIO); goto fail; diff --git a/libavformat/tcp.c b/libavformat/tcp.c index fb94b63984..f0d1c4556f 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -19,10 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" +#include "libavutil/parseutils.h" #include #include "internal.h" #include "network.h" #include "os_support.h" +#include "url.h" #if HAVE_POLL_H #include #endif @@ -38,6 +40,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) struct addrinfo hints, *ai, *cur_ai; int port, fd = -1; TCPContext *s = NULL; + int listen_socket = 0; + const char *p; + char buf[256]; int ret; socklen_t optlen; char hostname[1024],proto[1024],path[1024]; @@ -48,6 +53,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) return AVERROR(EINVAL); + p = strchr(uri, '?'); + if (p) { + if (av_find_info_tag(buf, sizeof(buf), "listen", p)) + listen_socket = 1; + } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; @@ -66,10 +76,21 @@ static int tcp_open(URLContext *h, const char *uri, int flags) fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; - ff_socket_nonblock(fd, 1); + if (listen_socket) { + int fd1; + ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); + listen(fd, 1); + fd1 = accept(fd, NULL, NULL); + closesocket(fd); + fd = fd1; + } else { redo: - ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); + ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); + } + + ff_socket_nonblock(fd, 1); + if (ret < 0) { int timeout=50; struct pollfd p = {fd, POLLOUT, 0}; @@ -138,23 +159,13 @@ static int tcp_open(URLContext *h, const char *uri, int flags) return ret; } -static int tcp_wait_fd(int fd, int write) -{ - int ev = write ? POLLOUT : POLLIN; - struct pollfd p = { .fd = fd, .events = ev, .revents = 0 }; - int ret; - - ret = poll(&p, 1, 100); - return ret < 0 ? ff_neterrno() : p.revents & ev ? 0 : AVERROR(EAGAIN); -} - static int tcp_read(URLContext *h, uint8_t *buf, int size) { TCPContext *s = h->priv_data; int ret; - if (!(h->flags & URL_FLAG_NONBLOCK)) { - ret = tcp_wait_fd(s->fd, 0); + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = ff_network_wait_fd(s->fd, 0); if (ret < 0) return ret; } @@ -167,8 +178,8 @@ static int tcp_write(URLContext *h, const uint8_t *buf, int size) TCPContext *s = h->priv_data; int ret; - if (!(h->flags & URL_FLAG_NONBLOCK)) { - ret = tcp_wait_fd(s->fd, 1); + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = ff_network_wait_fd(s->fd, 1); if (ret < 0) return ret; } diff --git a/libavformat/udp.c b/libavformat/udp.c index 25541845a9..fd0640fd88 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -33,9 +33,7 @@ #include "internal.h" #include "network.h" #include "os_support.h" -#if HAVE_POLL_H -#include -#endif +#include "url.h" #include #ifndef IPV6_ADD_MEMBERSHIP @@ -320,7 +318,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) h->is_streamed = 1; h->max_packet_size = 1472; - is_output = (flags & URL_WRONLY); + is_output = (flags & AVIO_WRONLY); s = av_mallocz(sizeof(UDPContext)); if (!s) @@ -363,14 +361,14 @@ static int udp_open(URLContext *h, const char *uri, int flags) /* XXX: fix av_url_split */ if (hostname[0] == '\0' || hostname[0] == '?') { /* only accepts null hostname if input */ - if (flags & URL_WRONLY) + if (flags & AVIO_WRONLY) goto fail; } else { if (ff_udp_set_remote_url(h, uri) < 0) goto fail; } - if (s->is_multicast && !(h->flags & URL_WRONLY)) + if (s->is_multicast && !(h->flags & AVIO_WRONLY)) s->local_port = port; udp_fd = udp_socket_create(s, &my_addr, &len); if (udp_fd < 0) @@ -387,7 +385,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) /* the bind is needed to give a port to the socket now */ /* if multicast, try the multicast address bind first */ - if (s->is_multicast && !(h->flags & URL_WRONLY)) { + if (s->is_multicast && !(h->flags & AVIO_WRONLY)) { bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len); } /* bind to the local address if not multicast or if the multicast @@ -400,7 +398,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) s->local_port = udp_port(&my_addr, len); if (s->is_multicast) { - if (h->flags & URL_WRONLY) { + if (h->flags & AVIO_WRONLY) { /* output */ if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0) goto fail; @@ -447,31 +445,15 @@ static int udp_open(URLContext *h, const char *uri, int flags) static int udp_read(URLContext *h, uint8_t *buf, int size) { UDPContext *s = h->priv_data; - struct pollfd p = {s->udp_fd, POLLIN, 0}; - int len; int ret; - for(;;) { - if (url_interrupt_cb()) - return AVERROR_EXIT; - ret = poll(&p, 1, 100); - if (ret < 0) { - if (ff_neterrno() == AVERROR(EINTR)) - continue; - return AVERROR(EIO); - } - if (!(ret == 1 && p.revents & POLLIN)) - continue; - len = recv(s->udp_fd, buf, size, 0); - if (len < 0) { - if (ff_neterrno() != AVERROR(EAGAIN) && - ff_neterrno() != AVERROR(EINTR)) - return AVERROR(EIO); - } else { - break; - } + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = ff_network_wait_fd(s->udp_fd, 0); + if (ret < 0) + return ret; } - return len; + ret = recv(s->udp_fd, buf, size, 0); + return ret < 0 ? ff_neterrno() : ret; } static int udp_write(URLContext *h, const uint8_t *buf, int size) @@ -479,29 +461,27 @@ static int udp_write(URLContext *h, const uint8_t *buf, int size) UDPContext *s = h->priv_data; int ret; - for(;;) { - if (!s->is_connected) { - ret = sendto (s->udp_fd, buf, size, 0, - (struct sockaddr *) &s->dest_addr, - s->dest_addr_len); - } else - ret = send(s->udp_fd, buf, size, 0); - if (ret < 0) { - if (ff_neterrno() != AVERROR(EINTR) && - ff_neterrno() != AVERROR(EAGAIN)) - return ff_neterrno(); - } else { - break; - } + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = ff_network_wait_fd(s->udp_fd, 1); + if (ret < 0) + return ret; } - return size; + + if (!s->is_connected) { + ret = sendto (s->udp_fd, buf, size, 0, + (struct sockaddr *) &s->dest_addr, + s->dest_addr_len); + } else + ret = send(s->udp_fd, buf, size, 0); + + return ret < 0 ? ff_neterrno() : ret; } static int udp_close(URLContext *h) { UDPContext *s = h->priv_data; - if (s->is_multicast && !(h->flags & URL_WRONLY)) + if (s->is_multicast && !(h->flags & AVIO_WRONLY)) udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr); closesocket(s->udp_fd); av_free(s); diff --git a/libavformat/url.h b/libavformat/url.h index 97652bb972..9f97db594f 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -30,6 +30,8 @@ #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 URLInterruptCB *url_interrupt_cb; #endif /** @@ -131,4 +133,11 @@ int64_t ffurl_size(URLContext *h); */ int ffurl_get_file_handle(URLContext *h); +/** + * Register the URLProtocol protocol. + * + * @param size the size of the URLProtocol struct referenced + */ +int ffurl_register_protocol(URLProtocol *protocol, int size); + #endif //AVFORMAT_URL_H diff --git a/libavformat/utils.c b/libavformat/utils.c index 0ea209c93c..d9aa6f1173 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -32,6 +32,7 @@ #include "libavutil/avstring.h" #include "riff.h" #include "audiointerleave.h" +#include "url.h" #include #include #include @@ -636,7 +637,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, hack needed to handle RTSP/TCP */ if (!fmt || !(fmt->flags & AVFMT_NOFILE)) { /* if no file needed do not try to open one */ - if ((err=avio_open(&pb, filename, URL_RDONLY)) < 0) { + if ((err=avio_open(&pb, filename, AVIO_RDONLY)) < 0) { goto fail; } if (buf_size > 0) { diff --git a/tests/ref/acodec/pcm b/tests/ref/acodec/pcm index 1d876e4aca..033f8bc8c6 100644 --- a/tests/ref/acodec/pcm +++ b/tests/ref/acodec/pcm @@ -22,12 +22,12 @@ stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 1058444 ./tests/data/acodec/pcm_s16le.wav 95e54b261530a1bcf6de6fe3b21dc5f6 *./tests/data/pcm.acodec.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 -352a6bcf51d0f3ca4bf27c423a3d4d14 *./tests/data/acodec/pcm_s16be.mkv - 1060650 ./tests/data/acodec/pcm_s16be.mkv +af717ca95eaca310772eb1238c745d1b *./tests/data/acodec/pcm_s16be.mkv +1060638 ./tests/data/acodec/pcm_s16be.mkv 95e54b261530a1bcf6de6fe3b21dc5f6 *./tests/data/pcm.acodec.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 -2c089d83b2699c02c9358415e00a9707 *./tests/data/acodec/pcm_s16le.mkv - 1060650 ./tests/data/acodec/pcm_s16le.mkv +c4f51bf32fad2f7af8ea5beedb56168b *./tests/data/acodec/pcm_s16le.mkv +1060638 ./tests/data/acodec/pcm_s16le.mkv 95e54b261530a1bcf6de6fe3b21dc5f6 *./tests/data/pcm.acodec.out.wav stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 1058400/ 1058400 07ffe7ffb78f3648b6524debdde5aec1 *./tests/data/acodec/pcm_s24be.mov