summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libavformat/avio.c7
-rw-r--r--libavformat/avio.h6
-rw-r--r--libavformat/aviobuf.c19
-rw-r--r--libavformat/http.c8
-rw-r--r--libavformat/tcp.c21
-rw-r--r--libavformat/url.h8
6 files changed, 68 insertions, 1 deletions
diff --git a/libavformat/avio.c b/libavformat/avio.c
index 3606eb0..62233a6 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -645,6 +645,13 @@ int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
return h->prot->url_get_multi_file_handle(h, handles, numhandles);
}
+int ffurl_get_short_seek(URLContext *h)
+{
+ if (!h->prot->url_get_short_seek)
+ return AVERROR(ENOSYS);
+ return h->prot->url_get_short_seek(h);
+}
+
int ffurl_shutdown(URLContext *h, int flags)
{
if (!h->prot->url_shutdown)
diff --git a/libavformat/avio.h b/libavformat/avio.h
index e2cb4af..8040094 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -313,6 +313,12 @@ typedef struct AVIOContext {
*/
enum AVIODataMarkerType current_type;
int64_t last_time;
+
+ /**
+ * A callback that is used instead of short_seek_threshold.
+ * This is current internal only, do not use from outside.
+ */
+ int (*short_seek_get)(void *opaque);
} AVIOContext;
/**
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index bf7e5f8..4ade4d0 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -119,6 +119,7 @@ int ffio_init_context(AVIOContext *s,
s->ignore_boundary_point = 0;
s->current_type = AVIO_DATA_MARKER_UNKNOWN;
s->last_time = AV_NOPTS_VALUE;
+ s->short_seek_get = NULL;
return 0;
}
@@ -233,6 +234,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
int64_t pos;
int force = whence & AVSEEK_FORCE;
int buffer_size;
+ int short_seek;
whence &= ~AVSEEK_FORCE;
if(!s)
@@ -254,13 +256,21 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
if (offset < 0)
return AVERROR(EINVAL);
+ if (s->short_seek_get) {
+ short_seek = s->short_seek_get(s->opaque);
+ /* fallback to default short seek */
+ if (short_seek <= 0)
+ short_seek = s->short_seek_threshold;
+ } else
+ short_seek = s->short_seek_threshold;
+
offset1 = offset - pos; // "offset1" is the relative offset from the beginning of s->buffer
if (!s->must_flush && (!s->direct || !s->seek) &&
offset1 >= 0 && offset1 <= buffer_size - s->write_flag) {
/* can do the seek inside the buffer */
s->buf_ptr = s->buffer + offset1;
} else if ((!s->seekable ||
- offset1 <= buffer_size + s->short_seek_threshold) &&
+ offset1 <= buffer_size + short_seek) &&
!s->write_flag && offset1 >= 0 &&
(!s->direct || !s->seek) &&
(whence != SEEK_END || force)) {
@@ -858,6 +868,12 @@ static int64_t io_seek(void *opaque, int64_t offset, int whence)
return ffurl_seek(internal->h, offset, whence);
}
+static int io_short_seek(void *opaque)
+{
+ AVIOInternal *internal = opaque;
+ return ffurl_get_short_seek(internal->h);
+}
+
static int io_read_pause(void *opaque, int pause)
{
AVIOInternal *internal = opaque;
@@ -919,6 +935,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
(*s)->read_pause = io_read_pause;
(*s)->read_seek = io_read_seek;
}
+ (*s)->short_seek_get = io_short_seek;
(*s)->av_class = &ff_avio_class;
return 0;
fail:
diff --git a/libavformat/http.c b/libavformat/http.c
index bd1be3f..293a8a7 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -1533,6 +1533,12 @@ static int http_get_file_handle(URLContext *h)
return ffurl_get_file_handle(s->hd);
}
+static int http_get_short_seek(URLContext *h)
+{
+ HTTPContext *s = h->priv_data;
+ return ffurl_get_short_seek(s->hd);
+}
+
#define HTTP_CLASS(flavor) \
static const AVClass flavor ## _context_class = { \
.class_name = # flavor, \
@@ -1554,6 +1560,7 @@ const URLProtocol ff_http_protocol = {
.url_seek = http_seek,
.url_close = http_close,
.url_get_file_handle = http_get_file_handle,
+ .url_get_short_seek = http_get_short_seek,
.url_shutdown = http_shutdown,
.priv_data_size = sizeof(HTTPContext),
.priv_data_class = &http_context_class,
@@ -1573,6 +1580,7 @@ const URLProtocol ff_https_protocol = {
.url_seek = http_seek,
.url_close = http_close,
.url_get_file_handle = http_get_file_handle,
+ .url_get_short_seek = http_get_short_seek,
.url_shutdown = http_shutdown,
.priv_data_size = sizeof(HTTPContext),
.priv_data_class = &https_context_class,
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 5f00ba7..3055e48 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -266,6 +266,26 @@ static int tcp_get_file_handle(URLContext *h)
return s->fd;
}
+static int tcp_get_window_size(URLContext *h)
+{
+ TCPContext *s = h->priv_data;
+ int avail;
+ int avail_len = sizeof(avail);
+
+#if HAVE_WINSOCK2_H
+ /* SO_RCVBUF with winsock only reports the actual TCP window size when
+ auto-tuning has been disabled via setting SO_RCVBUF */
+ if (s->recv_buffer_size < 0) {
+ return AVERROR(ENOSYS);
+ }
+#endif
+
+ if (getsockopt(s->fd, SOL_SOCKET, SO_RCVBUF, &avail, &avail_len)) {
+ return ff_neterrno();
+ }
+ return avail;
+}
+
const URLProtocol ff_tcp_protocol = {
.name = "tcp",
.url_open = tcp_open,
@@ -274,6 +294,7 @@ const URLProtocol ff_tcp_protocol = {
.url_write = tcp_write,
.url_close = tcp_close,
.url_get_file_handle = tcp_get_file_handle,
+ .url_get_short_seek = tcp_get_window_size,
.url_shutdown = tcp_shutdown,
.priv_data_size = sizeof(TCPContext),
.flags = URL_PROTOCOL_FLAG_NETWORK,
diff --git a/libavformat/url.h b/libavformat/url.h
index 5c50245..910f1e0 100644
--- a/libavformat/url.h
+++ b/libavformat/url.h
@@ -84,6 +84,7 @@ typedef struct URLProtocol {
int (*url_get_file_handle)(URLContext *h);
int (*url_get_multi_file_handle)(URLContext *h, int **handles,
int *numhandles);
+ int (*url_get_short_seek)(URLContext *h);
int (*url_shutdown)(URLContext *h, int flags);
int priv_data_size;
const AVClass *priv_data_class;
@@ -249,6 +250,13 @@ int ffurl_get_file_handle(URLContext *h);
int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles);
/**
+ * Return the current short seek threshold value for this URL.
+ *
+ * @return threshold (>0) on success or <=0 on error.
+ */
+int ffurl_get_short_seek(URLContext *h);
+
+/**
* Signal the URLContext that we are done reading or writing the stream.
*
* @param h pointer to the resource
OpenPOWER on IntegriCloud