summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-11-19 01:55:55 +0100
committerMichael Niedermayer <michaelni@gmx.at>2011-11-19 02:00:06 +0100
commite161b079dee12b11c40df67cf422edeb84772bbe (patch)
treefe5000d84e5fc4049395822c4bf8b4d600851782 /libavformat
parent36a60fad6215db39e9cd9523e3425f64464046c7 (diff)
parentff3755cbde9bdd2a4dc50e4432f72ddeef1a85ac (diff)
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.c1
-rw-r--r--libavformat/applehttp.c3
-rw-r--r--libavformat/avio.c10
-rw-r--r--libavformat/avio.h6
-rw-r--r--libavformat/http.c175
-rw-r--r--libavformat/rtmpproto.c9
-rw-r--r--libavformat/rtpdec.c10
-rw-r--r--libavformat/rtpdec.h1
-rw-r--r--libavformat/rtspdec.c2
-rw-r--r--libavformat/segafilm.c15
-rw-r--r--libavformat/tls.c17
-rw-r--r--libavformat/version.h5
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 */