| Index: patched-ffmpeg-mt/ffserver.c
|
| ===================================================================
|
| --- patched-ffmpeg-mt/ffserver.c (revision 41250)
|
| +++ patched-ffmpeg-mt/ffserver.c (working copy)
|
| @@ -28,7 +28,6 @@
|
| #include <string.h>
|
| #include <strings.h>
|
| #include <stdlib.h>
|
| -/* avformat.h defines LIBAVFORMAT_BUILD, include it before all the other libav* headers which use it */
|
| #include "libavformat/avformat.h"
|
| #include "libavformat/network.h"
|
| #include "libavformat/os_support.h"
|
| @@ -37,7 +36,6 @@
|
| #include "libavutil/avstring.h"
|
| #include "libavutil/lfg.h"
|
| #include "libavutil/random_seed.h"
|
| -#include "libavutil/intreadwrite.h"
|
| #include "libavcodec/opt.h"
|
| #include <stdarg.h>
|
| #include <unistd.h>
|
| @@ -48,7 +46,6 @@
|
| #endif
|
| #include <errno.h>
|
| #include <sys/time.h>
|
| -#undef time //needed because HAVE_AV_CONFIG_H is defined on top
|
| #include <time.h>
|
| #include <sys/wait.h>
|
| #include <signal.h>
|
| @@ -58,8 +55,6 @@
|
|
|
| #include "cmdutils.h"
|
|
|
| -#undef exit
|
| -
|
| const char program_name[] = "FFserver";
|
| const int program_birth_year = 2000;
|
|
|
| @@ -124,6 +119,8 @@
|
| uint8_t *buffer_ptr, *buffer_end;
|
| int http_error;
|
| int post;
|
| + int chunked_encoding;
|
| + int chunk_size; /* 0 if it needs to be read */
|
| struct HTTPContext *next;
|
| int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
|
| int64_t data_count;
|
| @@ -315,6 +312,42 @@
|
|
|
| static FILE *logfile = NULL;
|
|
|
| +/* FIXME: make ffserver work with IPv6 */
|
| +/* resolve host with also IP address parsing */
|
| +static int resolve_host(struct in_addr *sin_addr, const char *hostname)
|
| +{
|
| +
|
| + if (!ff_inet_aton(hostname, sin_addr)) {
|
| +#if HAVE_GETADDRINFO
|
| + struct addrinfo *ai, *cur;
|
| + struct addrinfo hints;
|
| + memset(&hints, 0, sizeof(hints));
|
| + hints.ai_family = AF_INET;
|
| + if (getaddrinfo(hostname, NULL, &hints, &ai))
|
| + return -1;
|
| + /* getaddrinfo returns a linked list of addrinfo structs.
|
| + * Even if we set ai_family = AF_INET above, make sure
|
| + * that the returned one actually is of the correct type. */
|
| + for (cur = ai; cur; cur = cur->ai_next) {
|
| + if (cur->ai_family == AF_INET) {
|
| + *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
|
| + freeaddrinfo(ai);
|
| + return 0;
|
| + }
|
| + }
|
| + freeaddrinfo(ai);
|
| + return -1;
|
| +#else
|
| + struct hostent *hp;
|
| + hp = gethostbyname(hostname);
|
| + if (!hp)
|
| + return -1;
|
| + memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
|
| +#endif
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| static char *ctime1(char *buf2)
|
| {
|
| time_t ti;
|
| @@ -2440,26 +2473,56 @@
|
| c->buffer_ptr = c->buffer;
|
| c->buffer_end = c->buffer + FFM_PACKET_SIZE;
|
| c->stream->feed_opened = 1;
|
| + c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
|
| return 0;
|
| }
|
|
|
| static int http_receive_data(HTTPContext *c)
|
| {
|
| HTTPContext *c1;
|
| + int len, loop_run = 0;
|
|
|
| - if (c->buffer_end > c->buffer_ptr) {
|
| - int len;
|
| + while (c->chunked_encoding && !c->chunk_size &&
|
| + c->buffer_end > c->buffer_ptr) {
|
| + /* read chunk header, if present */
|
| + len = recv(c->fd, c->buffer_ptr, 1, 0);
|
|
|
| - len = recv(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
|
| if (len < 0) {
|
| if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
|
| ff_neterrno() != FF_NETERROR(EINTR))
|
| /* error : close connection */
|
| goto fail;
|
| + } else if (len == 0) {
|
| + /* end of connection : close it */
|
| + goto fail;
|
| + } else if (c->buffer_ptr - c->buffer >= 2 &&
|
| + !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
|
| + c->chunk_size = strtol(c->buffer, 0, 16);
|
| + if (c->chunk_size == 0) // end of stream
|
| + goto fail;
|
| + c->buffer_ptr = c->buffer;
|
| + break;
|
| + } else if (++loop_run > 10) {
|
| + /* no chunk header, abort */
|
| + goto fail;
|
| + } else {
|
| + c->buffer_ptr++;
|
| + }
|
| + }
|
| +
|
| + if (c->buffer_end > c->buffer_ptr) {
|
| + len = recv(c->fd, c->buffer_ptr,
|
| + FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
|
| + if (len < 0) {
|
| + if (ff_neterrno() != FF_NETERROR(EAGAIN) &&
|
| + ff_neterrno() != FF_NETERROR(EINTR))
|
| + /* error : close connection */
|
| + goto fail;
|
| } else if (len == 0)
|
| /* end of connection : close it */
|
| goto fail;
|
| else {
|
| + c->chunk_size -= len;
|
| c->buffer_ptr += len;
|
| c->data_count += len;
|
| update_datarate(&c->datarate, c->data_count);
|
| @@ -2693,7 +2756,7 @@
|
| len = sizeof(line) - 1;
|
| memcpy(line, p, len);
|
| line[len] = '\0';
|
| - rtsp_parse_line(header, line);
|
| + ff_rtsp_parse_line(header, line);
|
| p = p1 + 1;
|
| }
|
|
|
| @@ -2778,7 +2841,7 @@
|
| struct sockaddr_in my_addr;
|
|
|
| /* find which url is asked */
|
| - url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
|
| + ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
|
| path = path1;
|
| if (*path == '/')
|
| path++;
|
| @@ -2853,7 +2916,7 @@
|
| RTSPActionServerSetup setup;
|
|
|
| /* find which url is asked */
|
| - url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
|
| + ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
|
| path = path1;
|
| if (*path == '/')
|
| path++;
|
| @@ -2995,7 +3058,7 @@
|
| return NULL;
|
|
|
| /* find which url is asked */
|
| - url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
|
| + ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
|
| path = path1;
|
| if (*path == '/')
|
| path++;
|
| @@ -4223,7 +4286,7 @@
|
| } else if (!strcasecmp(cmd, "VideoTag")) {
|
| get_arg(arg, sizeof(arg), &p);
|
| if ((strlen(arg) == 4) && stream)
|
| - video_enc.codec_tag = AV_RL32(arg);
|
| + video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
|
| } else if (!strcasecmp(cmd, "BitExact")) {
|
| if (stream)
|
| video_enc.flags |= CODEC_FLAG_BITEXACT;
|
|
|