diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-11-19 01:55:55 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-11-19 02:00:06 +0100 |
commit | e161b079dee12b11c40df67cf422edeb84772bbe (patch) | |
tree | fe5000d84e5fc4049395822c4bf8b4d600851782 /libavformat | |
parent | 36a60fad6215db39e9cd9523e3425f64464046c7 (diff) | |
parent | ff3755cbde9bdd2a4dc50e4432f72ddeef1a85ac (diff) | |
download | ffmpeg-e161b079dee12b11c40df67cf422edeb84772bbe.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master: (22 commits)
configure: add check for w32threads to enable it automatically
rtmp: do not hardcode invoke numbers
cinepack: return non-generic errors
fate-lavf-ts: use -mpegts_transport_stream_id option.
Add an APIchanges entry and a minor bump for avio changes.
avio: Mark the old interrupt callback mechanism as deprecated
avplay: Set the new interrupt callback
avconv: Set new interrupt callbacks for all AVFormatContexts, use avio_open2() everywhere
cinepak: remove redundant coordinate checks
cinepak: check strip_size
cinepak, simplify, use AV_RB24()
cinepak: simplify, use FFMIN()
cinepak: Fix division by zero, ask for sample if encoded_buf_size is 0
applehttp: Fix seeking in streams not starting at DTS=0
http: Don't use the normal http proxy mechanism for https
tls: Handle connection via a http proxy
http: Reorder two code blocks
http: Add a new protocol for opening connections via http proxies
http: Split out the non-chunked buffer reading part from http_read
segafilm: add support for raw videos
...
Conflicts:
avconv.c
configure
doc/APIchanges
libavcodec/cinepak.c
libavformat/applehttp.c
libavformat/version.h
tests/lavf-regression.sh
tests/ref/lavf/ts
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/allformats.c | 1 | ||||
-rw-r--r-- | libavformat/applehttp.c | 3 | ||||
-rw-r--r-- | libavformat/avio.c | 10 | ||||
-rw-r--r-- | libavformat/avio.h | 6 | ||||
-rw-r--r-- | libavformat/http.c | 175 | ||||
-rw-r--r-- | libavformat/rtmpproto.c | 9 | ||||
-rw-r--r-- | libavformat/rtpdec.c | 10 | ||||
-rw-r--r-- | libavformat/rtpdec.h | 1 | ||||
-rw-r--r-- | libavformat/rtspdec.c | 2 | ||||
-rw-r--r-- | libavformat/segafilm.c | 15 | ||||
-rw-r--r-- | libavformat/tls.c | 17 | ||||
-rw-r--r-- | libavformat/version.h | 5 |
12 files changed, 217 insertions, 37 deletions
diff --git a/libavformat/allformats.c b/libavformat/allformats.c index c4b27e43cd..31fa5060f7 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -259,6 +259,7 @@ void av_register_all(void) REGISTER_PROTOCOL (FILE, file); REGISTER_PROTOCOL (GOPHER, gopher); REGISTER_PROTOCOL (HTTP, http); + REGISTER_PROTOCOL (HTTPPROXY, httpproxy); REGISTER_PROTOCOL (HTTPS, https); REGISTER_PROTOCOL (MMSH, mmsh); REGISTER_PROTOCOL (MMST, mmst); diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c index 7c41d9893c..1694096d9b 100644 --- a/libavformat/applehttp.c +++ b/libavformat/applehttp.c @@ -644,7 +644,8 @@ static int applehttp_read_seek(AVFormatContext *s, int stream_index, for (i = 0; i < c->n_variants; i++) { /* Reset reading */ struct variant *var = c->variants[i]; - int64_t pos = av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ? + int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 : + av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); diff --git a/libavformat/avio.c b/libavformat/avio.c index 879844aefc..b2b39b32d7 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -83,9 +83,11 @@ const AVClass ffurl_context_class = { }; /*@}*/ -static int default_interrupt_cb(void); +#if FF_API_OLD_INTERRUPT_CB +static int default_interrupt_cb(void); int (*url_interrupt_cb)(void) = default_interrupt_cb; +#endif URLProtocol *av_protocol_next(URLProtocol *p) { @@ -444,6 +446,7 @@ int ffurl_get_file_handle(URLContext *h) return h->prot->url_get_file_handle(h); } +#if FF_API_OLD_INTERRUPT_CB static int default_interrupt_cb(void) { return 0; @@ -455,13 +458,18 @@ void avio_set_interrupt_cb(int (*interrupt_cb)(void)) interrupt_cb = default_interrupt_cb; url_interrupt_cb = interrupt_cb; } +#endif int ff_check_interrupt(AVIOInterruptCB *cb) { int ret; if (cb && cb->callback && (ret = cb->callback(cb->opaque))) return ret; +#if FF_API_OLD_INTERRUPT_CB return url_interrupt_cb(); +#else + return 0; +#endif } #if FF_API_OLD_AVIO diff --git a/libavformat/avio.h b/libavformat/avio.h index 14f3b7b292..88fe1577ff 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -386,13 +386,17 @@ attribute_deprecated int url_exist(const char *url); */ int avio_check(const char *url, int flags); +#if FF_API_OLD_INTERRUPT_CB /** * The callback is called in blocking functions to test regulary if * asynchronous interruption is needed. AVERROR_EXIT is returned * in this case by the interrupted function. 'NULL' means no interrupt * callback is given. + * @deprecated Use interrupt_callback in AVFormatContext/avio_open2 + * instead. */ -void avio_set_interrupt_cb(int (*interrupt_cb)(void)); +attribute_deprecated void avio_set_interrupt_cb(int (*interrupt_cb)(void)); +#endif /** * Allocate and initialize an AVIOContext for buffered I/O. It must be later diff --git a/libavformat/http.c b/libavformat/http.c index ad4018085c..d45ef22616 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -110,6 +110,15 @@ static int http_open_cnx(URLContext *h) path1, sizeof(path1), s->location); ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL); + if (!strcmp(proto, "https")) { + lower_proto = "tls"; + use_proxy = 0; + if (port < 0) + port = 443; + } + if (port < 0) + port = 80; + if (path1[0] == '\0') path = "/"; else @@ -124,13 +133,6 @@ static int http_open_cnx(URLContext *h) av_url_split(NULL, 0, proxyauth, sizeof(proxyauth), hostname, sizeof(hostname), &port, NULL, 0, proxy_path); } - if (!strcmp(proto, "https")) { - lower_proto = "tls"; - if (port < 0) - port = 443; - } - if (port < 0) - port = 80; ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL); err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE, @@ -413,10 +415,33 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, } -static int http_read(URLContext *h, uint8_t *buf, int size) +static int http_buf_read(URLContext *h, uint8_t *buf, int size) { HTTPContext *s = h->priv_data; int len; + /* read bytes from input buffer first */ + len = s->buf_end - s->buf_ptr; + if (len > 0) { + if (len > size) + len = size; + memcpy(buf, s->buf_ptr, len); + s->buf_ptr += len; + } else { + if (!s->willclose && s->filesize >= 0 && s->off >= s->filesize) + return AVERROR_EOF; + len = ffurl_read(s->hd, buf, size); + } + if (len > 0) { + s->off += len; + if (s->chunksize > 0) + s->chunksize -= len; + } + return len; +} + +static int http_read(URLContext *h, uint8_t *buf, int size) +{ + HTTPContext *s = h->priv_data; if (s->chunksize >= 0) { if (!s->chunksize) { @@ -439,24 +464,7 @@ static int http_read(URLContext *h, uint8_t *buf, int size) } size = FFMIN(size, s->chunksize); } - /* read bytes from input buffer first */ - len = s->buf_end - s->buf_ptr; - if (len > 0) { - if (len > size) - len = size; - memcpy(buf, s->buf_ptr, len); - s->buf_ptr += len; - } else { - if (!s->willclose && s->filesize >= 0 && s->off >= s->filesize) - return AVERROR_EOF; - len = ffurl_read(s->hd, buf, size); - } - if (len > 0) { - s->off += len; - if (s->chunksize > 0) - s->chunksize -= len; - } - return len; + return http_buf_read(h, buf, size); } /* used only when posting data */ @@ -572,3 +580,118 @@ URLProtocol ff_https_protocol = { .priv_data_class = &https_context_class, }; #endif + +#if CONFIG_HTTPPROXY_PROTOCOL +static int http_proxy_close(URLContext *h) +{ + HTTPContext *s = h->priv_data; + if (s->hd) + ffurl_close(s->hd); + return 0; +} + +static int http_proxy_open(URLContext *h, const char *uri, int flags) +{ + HTTPContext *s = h->priv_data; + char hostname[1024], hoststr[1024]; + char auth[1024], pathbuf[1024], *path; + char line[1024], lower_url[100]; + int port, ret = 0; + HTTPAuthType cur_auth_type; + char *authstr; + + h->is_streamed = 1; + + av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, + pathbuf, sizeof(pathbuf), uri); + ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL); + path = pathbuf; + if (*path == '/') + path++; + + ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port, + NULL); +redo: + ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE, + &h->interrupt_callback, NULL); + if (ret < 0) + return ret; + + authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth, + path, "CONNECT"); + snprintf(s->buffer, sizeof(s->buffer), + "CONNECT %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Connection: close\r\n" + "%s%s" + "\r\n", + path, + hoststr, + authstr ? "Proxy-" : "", authstr ? authstr : ""); + av_freep(&authstr); + + if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0) + goto fail; + + s->buf_ptr = s->buffer; + s->buf_end = s->buffer; + s->line_count = 0; + s->filesize = -1; + cur_auth_type = s->proxy_auth_state.auth_type; + + for (;;) { + int new_loc; + // Note: This uses buffering, potentially reading more than the + // HTTP header. If tunneling a protocol where the server starts + // the conversation, we might buffer part of that here, too. + // Reading that requires using the proper ffurl_read() function + // on this URLContext, not using the fd directly (as the tls + // protocol does). This shouldn't be an issue for tls though, + // since the client starts the conversation there, so there + // is no extra data that we might buffer up here. + if (http_get_line(s, line, sizeof(line)) < 0) { + ret = AVERROR(EIO); + goto fail; + } + + av_dlog(h, "header='%s'\n", line); + + ret = process_line(h, line, s->line_count, &new_loc); + if (ret < 0) + goto fail; + if (ret == 0) + break; + s->line_count++; + } + if (s->http_code == 407 && cur_auth_type == HTTP_AUTH_NONE && + s->proxy_auth_state.auth_type != HTTP_AUTH_NONE) { + ffurl_close(s->hd); + s->hd = NULL; + goto redo; + } + + if (s->http_code < 400) + return 0; + ret = AVERROR(EIO); + +fail: + http_proxy_close(h); + return ret; +} + +static int http_proxy_write(URLContext *h, const uint8_t *buf, int size) +{ + HTTPContext *s = h->priv_data; + return ffurl_write(s->hd, buf, size); +} + +URLProtocol ff_httpproxy_protocol = { + .name = "httpproxy", + .url_open = http_proxy_open, + .url_read = http_buf_read, + .url_write = http_proxy_write, + .url_close = http_proxy_close, + .url_get_file_handle = http_get_file_handle, + .priv_data_size = sizeof(HTTPContext), +}; +#endif diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index e73158f12c..8935f56369 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -74,6 +74,7 @@ typedef struct RTMPContext { int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call uint8_t flv_header[11]; ///< partial incoming flv packet header int flv_header_bytes; ///< number of initialized bytes in flv_header + int nb_invokes; ///< keeps track of invoke messages } RTMPContext; #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing @@ -166,7 +167,7 @@ static void gen_release_stream(URLContext *s, RTMPContext *rt) av_log(s, AV_LOG_DEBUG, "Releasing stream...\n"); p = pkt.data; ff_amf_write_string(&p, "releaseStream"); - ff_amf_write_number(&p, 2.0); + ff_amf_write_number(&p, ++rt->nb_invokes); ff_amf_write_null(&p); ff_amf_write_string(&p, rt->playpath); @@ -189,7 +190,7 @@ static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt) av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n"); p = pkt.data; ff_amf_write_string(&p, "FCPublish"); - ff_amf_write_number(&p, 3.0); + ff_amf_write_number(&p, ++rt->nb_invokes); ff_amf_write_null(&p); ff_amf_write_string(&p, rt->playpath); @@ -212,7 +213,7 @@ static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt) av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n"); p = pkt.data; ff_amf_write_string(&p, "FCUnpublish"); - ff_amf_write_number(&p, 5.0); + ff_amf_write_number(&p, ++rt->nb_invokes); ff_amf_write_null(&p); ff_amf_write_string(&p, rt->playpath); @@ -234,7 +235,7 @@ static void gen_create_stream(URLContext *s, RTMPContext *rt) p = pkt.data; ff_amf_write_string(&p, "createStream"); - ff_amf_write_number(&p, rt->is_input ? 3.0 : 4.0); + ff_amf_write_number(&p, ++rt->nb_invokes); ff_amf_write_null(&p); ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]); diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index f264efe92e..95a1edaa55 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -429,7 +429,7 @@ static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestam if (timestamp == RTP_NOTS_VALUE) return; - if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) { + if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE && s->ic->nb_streams > 1) { int64_t addend; int delta_timestamp; @@ -444,7 +444,13 @@ static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestam if (!s->base_timestamp) s->base_timestamp = timestamp; - pkt->pts = s->range_start_offset + timestamp - s->base_timestamp; + /* assume that the difference is INT32_MIN < x < INT32_MAX, but allow the first timestamp to exceed INT32_MAX */ + if (!s->timestamp) + s->unwrapped_timestamp += timestamp; + else + s->unwrapped_timestamp += (int32_t)(timestamp - s->timestamp); + s->timestamp = timestamp; + pkt->pts = s->unwrapped_timestamp + s->range_start_offset - s->base_timestamp; } static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt, diff --git a/libavformat/rtpdec.h b/libavformat/rtpdec.h index dbb45f5709..eb468be9e5 100644 --- a/libavformat/rtpdec.h +++ b/libavformat/rtpdec.h @@ -151,6 +151,7 @@ struct RTPDemuxContext { uint32_t timestamp; uint32_t base_timestamp; uint32_t cur_timestamp; + int64_t unwrapped_timestamp; int64_t range_start_offset; int max_payload_size; struct MpegTSContext *ts; /* only used for MP2T payloads */ diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index f55b8cf2a2..8699f77918 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -52,6 +52,8 @@ static int rtsp_read_play(AVFormatContext *s) rtpctx->last_rtcp_ntp_time = AV_NOPTS_VALUE; rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE; rtpctx->base_timestamp = 0; + rtpctx->timestamp = 0; + rtpctx->unwrapped_timestamp = 0; rtpctx->rtcp_ts_offset = 0; } } diff --git a/libavformat/segafilm.c b/libavformat/segafilm.c index 1ae105eb77..0199ee1f5f 100644 --- a/libavformat/segafilm.c +++ b/libavformat/segafilm.c @@ -34,6 +34,7 @@ #define FDSC_TAG MKBETAG('F', 'D', 'S', 'C') #define STAB_TAG MKBETAG('S', 'T', 'A', 'B') #define CVID_TAG MKBETAG('c', 'v', 'i', 'd') +#define RAW_TAG MKBETAG('r', 'a', 'w', ' ') typedef struct { int stream; @@ -129,8 +130,11 @@ static int film_read_header(AVFormatContext *s, if (AV_RB32(&scratch[8]) == CVID_TAG) { film->video_type = CODEC_ID_CINEPAK; - } else + } else if (AV_RB32(&scratch[8]) == RAW_TAG) { + film->video_type = CODEC_ID_RAWVIDEO; + } else { film->video_type = CODEC_ID_NONE; + } /* initialize the decoder streams */ if (film->video_type) { @@ -143,6 +147,15 @@ static int film_read_header(AVFormatContext *s, st->codec->codec_tag = 0; /* no fourcc */ st->codec->width = AV_RB32(&scratch[16]); st->codec->height = AV_RB32(&scratch[12]); + + if (film->video_type == CODEC_ID_RAWVIDEO) { + if (scratch[20] == 24) { + st->codec->pix_fmt = PIX_FMT_RGB24; + } else { + av_log(s, AV_LOG_ERROR, "raw video is using unhandled %dbpp\n", scratch[20]); + return -1; + } + } } if (film->audio_type) { diff --git a/libavformat/tls.c b/libavformat/tls.c index 72c2b85016..339b799322 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -111,9 +111,15 @@ static int tls_open(URLContext *h, const char *uri, int flags) char buf[200], host[200]; int numerichost = 0; struct addrinfo hints = { 0 }, *ai = NULL; + const char *proxy_path; + int use_proxy; ff_tls_init(); + proxy_path = getenv("http_proxy"); + use_proxy = (proxy_path != NULL) && !getenv("no_proxy") && + av_strstart(proxy_path, "http://", NULL); + av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, uri); ff_url_join(buf, sizeof(buf), "tcp", NULL, host, port, NULL); @@ -123,6 +129,17 @@ static int tls_open(URLContext *h, const char *uri, int flags) freeaddrinfo(ai); } + if (use_proxy) { + char proxy_host[200], proxy_auth[200], dest[200]; + int proxy_port; + av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth), + proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0, + proxy_path); + ff_url_join(dest, sizeof(dest), NULL, NULL, host, port, NULL); + ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host, + proxy_port, "/%s", dest); + } + ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, NULL); if (ret) diff --git a/libavformat/version.h b/libavformat/version.h index 954d87a88e..5c7ed6863e 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -24,7 +24,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 53 -#define LIBAVFORMAT_VERSION_MINOR 20 +#define LIBAVFORMAT_VERSION_MINOR 21 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -113,5 +113,8 @@ #ifndef FF_API_REORDER_PRIVATE #define FF_API_REORDER_PRIVATE (LIBAVFORMAT_VERSION_MAJOR < 54) #endif +#ifndef FF_API_OLD_INTERRUPT_CB +#define FF_API_OLD_INTERRUPT_CB (LIBAVFORMAT_VERSION_MAJOR < 54) +#endif #endif /* AVFORMAT_VERSION_H */ |