Hi,
what would be the correct way to create patches that won't be corrupted? I
merely tried to copy what I have seen on the mailing-list before,
apparently I didn't do a very good job ;)
Regards,
Stephan Holljes
On Sun, Mar 22, 2015 at 12:24 AM, Michael Niedermayer <[email protected]>
wrote:
> On Sat, Mar 21, 2015 at 11:00:09PM +0100, Stephan Holljes wrote:
> > Hi,
> >
> > this is a patch for a proof-of-concept for an http server.
> >
> > Usage on the server side:
> >
> > ffmpeg -i test.mp3 -c copy -listen 1 -f mp3 http://0.0.0.0
> >
> > Usage on the client side:
> >
> > ffplay http://localhost:8080
> >
> > I looked at tls.c and tcp.c and copied parts of the code.
> > Please comment.
> >
> > Regards,
> > Stephan Holljes
> >
> > ---
> > libavformat/http.c | 113
> > ++++++++++++++++++++++++++++++++++++++--------------
> > 1 file changed, 83 insertions(+), 30 deletions(-)
> >
> > diff --git a/libavformat/http.c b/libavformat/http.c
> > index da3c9be..d61e4e2 100644
> > --- a/libavformat/http.c
> > +++ b/libavformat/http.c
> > @@ -96,8 +96,12 @@ typedef struct HTTPContext {
> > int send_expect_100;
> > char *method;
> > int reconnect;
> > + int listen;
> > + int fd;
> > + int header_sent;
> > } HTTPContext;
> >
> > +
> > #define OFFSET(x) offsetof(HTTPContext, x)
> > #define D AV_OPT_FLAG_DECODING_PARAM
> > #define E AV_OPT_FLAG_ENCODING_PARAM
> > @@ -127,6 +131,7 @@ static const AVOption options[] = {
> > { "end_offset", "try to limit the request to bytes preceding this
> > offset", OFFSET(end_off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
> D
> > },
> > { "method", "Override the HTTP method", OFFSET(method),
> > AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
> > { "reconnect", "auto reconnect after disconnect before EOF",
> > OFFSET(reconnect), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D },
> > + { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, {
> .i64
> > = 0 }, 0, 1, D },
>
> it appears this patch has been corrupted by extra newlines from
> word/line wrap
>
> please resend as an attachment
>
> [...]
> --
> Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Breaking DRM is a little like attempting to break through a door even
> though the window is wide open and the only thing in the house is a bunch
> of things you dont want and which you would get tomorrow for free anyway
>
> _______________________________________________
> ffmpeg-devel mailing list
> [email protected]
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>
diff --git a/libavformat/http.c b/libavformat/http.c
index da3c9be..d61e4e2 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -96,8 +96,12 @@ typedef struct HTTPContext {
int send_expect_100;
char *method;
int reconnect;
+ int listen;
+ int fd;
+ int header_sent;
} HTTPContext;
+
#define OFFSET(x) offsetof(HTTPContext, x)
#define D AV_OPT_FLAG_DECODING_PARAM
#define E AV_OPT_FLAG_ENCODING_PARAM
@@ -127,6 +131,7 @@ static const AVOption options[] = {
{ "end_offset", "try to limit the request to bytes preceding this offset", OFFSET(end_off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D },
{ "method", "Override the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
{ "reconnect", "auto reconnect after disconnect before EOF", OFFSET(reconnect), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D },
+ { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D },
{ NULL }
};
@@ -299,8 +304,10 @@ int ff_http_averror(int status_code, int default_averror)
static int http_open(URLContext *h, const char *uri, int flags,
AVDictionary **options)
{
+ struct addrinfo hints = { 0 }, *ai;
HTTPContext *s = h->priv_data;
- int ret;
+ int ret = -1, fd;
+ char portstr[] = "8080"; // allow non-root users for now
if( s->seekable == 1 )
h->is_streamed = 0;
@@ -320,11 +327,39 @@ static int http_open(URLContext *h, const char *uri, int flags,
av_log(h, AV_LOG_WARNING,
"No trailing CRLF found in HTTP header.\n");
}
+ if (s->listen) {
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags |= AI_PASSIVE;
+ ret = getaddrinfo(NULL, portstr, &hints, &ai);
+ if (ret) {
+ av_log(h, AV_LOG_ERROR, "borked");
+ return AVERROR(EIO);
+ }
+ fd = ff_socket(ai->ai_family,
+ ai->ai_socktype,
+ ai->ai_protocol);
+ if (fd < 0) {
+ ret = ff_neterrno();
+ freeaddrinfo(ai);
+ return -1;
+ }
- ret = http_open_cnx(h, options);
- if (ret < 0)
- av_dict_free(&s->chained_options);
- return ret;
+ fd = ff_listen_bind(fd, ai->ai_addr, ai->ai_addrlen, -1, h);
+ if (fd < 0) {
+ freeaddrinfo(ai);
+ return fd;
+ }
+ h->is_streamed = 1;
+ s->fd = fd;
+ freeaddrinfo(ai);
+ return 0;
+ } else {
+ ret = http_open_cnx(h, options);
+ if (ret < 0)
+ av_dict_free(&s->chained_options);
+ return ret;
+ }
}
static int http_getc(HTTPContext *s)
@@ -1102,25 +1137,40 @@ static int http_write(URLContext *h, const uint8_t *buf, int size)
char temp[11] = ""; /* 32-bit hex + CRLF + nul */
int ret;
char crlf[] = "\r\n";
+ char header[] = "HTTP 200 OK\r\n\r\n";
HTTPContext *s = h->priv_data;
+ if (!s->listen) {
+ if (!s->chunked_post) {
+ /* non-chunked data is sent without any special encoding */
+ return ffurl_write(s->hd, buf, size);
+ }
- if (!s->chunked_post) {
- /* non-chunked data is sent without any special encoding */
- return ffurl_write(s->hd, buf, size);
- }
-
- /* silently ignore zero-size data since chunk encoding that would
- * signal EOF */
- if (size > 0) {
- /* upload data using chunked encoding */
- snprintf(temp, sizeof(temp), "%x\r\n", size);
+ /* silently ignore zero-size data since chunk encoding that would
+ * signal EOF */
+ if (size > 0) {
+ /* upload data using chunked encoding */
+ snprintf(temp, sizeof(temp), "%x\r\n", size);
- if ((ret = ffurl_write(s->hd, temp, strlen(temp))) < 0 ||
- (ret = ffurl_write(s->hd, buf, size)) < 0 ||
- (ret = ffurl_write(s->hd, crlf, sizeof(crlf) - 1)) < 0)
- return ret;
+ if ((ret = ffurl_write(s->hd, temp, strlen(temp))) < 0 ||
+ (ret = ffurl_write(s->hd, buf, size)) < 0 ||
+ (ret = ffurl_write(s->hd, crlf, sizeof(crlf) - 1)) < 0)
+ return ret;
+ }
+ return size;
+ } else {
+ if (!s->header_sent) {
+ ret = send(s->fd, header, sizeof(header), MSG_NOSIGNAL);
+ s->header_sent = 1;
+ return ret < 0 ? ff_neterrno() : ret;
+ }
+ if (size > 0) {
+ ret = send(s->fd, buf, size, MSG_NOSIGNAL);
+ return ret < 0 ? ff_neterrno() : ret;
+ } else {
+ ret = -1;
+ }
+ return ret;
}
- return size;
}
static int http_shutdown(URLContext *h, int flags)
@@ -1143,20 +1193,23 @@ static int http_close(URLContext *h)
{
int ret = 0;
HTTPContext *s = h->priv_data;
-
+ if (!s->listen) {
#if CONFIG_ZLIB
- inflateEnd(&s->inflate_stream);
- av_freep(&s->inflate_buffer);
+ inflateEnd(&s->inflate_stream);
+ av_freep(&s->inflate_buffer);
#endif /* CONFIG_ZLIB */
- if (!s->end_chunked_post)
- /* Close the write direction by sending the end of chunked encoding. */
- ret = http_shutdown(h, h->flags);
+ if (!s->end_chunked_post)
+ /* Close the write direction by sending the end of chunked encoding. */
+ ret = http_shutdown(h, h->flags);
- if (s->hd)
- ffurl_closep(&s->hd);
- av_dict_free(&s->chained_options);
- return ret;
+ if (s->hd)
+ ffurl_closep(&s->hd);
+ av_dict_free(&s->chained_options);
+ return ret;
+ } else {
+ return shutdown(s->fd, SHUT_RDWR);
+ }
}
static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
_______________________________________________
ffmpeg-devel mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel