X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=ffserver.c;h=e5c4ac23d8a60295e3bcb6bf79d84fcba09ad206;hb=e51975392d85e72801193123945a35fb5221248f;hp=14141f7ab2135caea9ac74db8a956d8da4d77e89;hpb=5634f30c4a25c17c1de26703948efeafb733413d;p=ffmpeg diff --git a/ffserver.c b/ffserver.c index 14141f7ab21..e5c4ac23d8a 100644 --- a/ffserver.c +++ b/ffserver.c @@ -36,6 +36,7 @@ #include "libavutil/avstring.h" #include "libavutil/lfg.h" #include "libavutil/random_seed.h" +#include "libavutil/parseutils.h" #include "libavcodec/opt.h" #include #include @@ -91,6 +92,10 @@ static const char *http_state[] = { "RTSP_SEND_PACKET", }; +#if !FF_API_MAX_STREAMS +#define MAX_STREAMS 20 +#endif + #define IOBUFFER_INIT_SIZE 8192 /* timeouts are in ms */ @@ -158,7 +163,7 @@ typedef struct HTTPContext { /* RTSP state specific */ uint8_t *pb_buffer; /* XXX: use that in all the code */ - ByteIOContext *pb; + AVIOContext *pb; int seq; /* RTSP sequence number */ /* RTP state specific */ @@ -379,7 +384,10 @@ static void http_vlog(const char *fmt, va_list vargs) } } -static void __attribute__ ((format (printf, 1, 2))) http_log(const char *fmt, ...) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +static void http_log(const char *fmt, ...) { va_list vargs; va_start(vargs, fmt); @@ -684,8 +692,8 @@ static int http_server(void) second to handle timeouts */ do { ret = poll(poll_table, poll_entry - poll_table, delay); - if (ret < 0 && ff_neterrno() != FF_NETERROR(EAGAIN) && - ff_neterrno() != FF_NETERROR(EINTR)) + if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) return -1; } while (ret < 0); @@ -740,7 +748,7 @@ static void http_send_too_busy_reply(int fd) { char buffer[300]; int len = snprintf(buffer, sizeof(buffer), - "HTTP/1.0 200 Server too busy\r\n" + "HTTP/1.0 503 Server too busy\r\n" "Content-type: text/html\r\n" "\r\n" "Too busy\r\n" @@ -908,8 +916,8 @@ static int handle_connection(HTTPContext *c) read_loop: len = recv(c->fd, c->buffer_ptr, 1, 0); if (len < 0) { - if (ff_neterrno() != FF_NETERROR(EAGAIN) && - ff_neterrno() != FF_NETERROR(EINTR)) + if (ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) return -1; } else if (len == 0) { return -1; @@ -944,8 +952,8 @@ static int handle_connection(HTTPContext *c) return 0; len = send(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)) { + if (ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) { /* error : close connection */ av_freep(&c->pb_buffer); return -1; @@ -1014,8 +1022,8 @@ static int handle_connection(HTTPContext *c) return 0; len = send(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)) { + if (ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) { /* error : close connection */ av_freep(&c->pb_buffer); return -1; @@ -1041,8 +1049,8 @@ static int handle_connection(HTTPContext *c) len = send(c->fd, c->packet_buffer_ptr, c->packet_buffer_end - c->packet_buffer_ptr, 0); if (len < 0) { - if (ff_neterrno() != FF_NETERROR(EAGAIN) && - ff_neterrno() != FF_NETERROR(EINTR)) { + if (ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) { /* error : close connection */ av_freep(&c->packet_buffer); return -1; @@ -1187,19 +1195,6 @@ static int modify_current_stream(HTTPContext *c, char *rates) return action_required; } - -static void do_switch_stream(HTTPContext *c, int i) -{ - if (c->switch_feed_streams[i] >= 0) { -#ifdef PHILIP - c->feed_streams[i] = c->switch_feed_streams[i]; -#endif - - /* Now update the stream */ - } - c->switch_feed_streams[i] = -1; -} - /* XXX: factorize in utils.c ? */ /* XXX: take care with different space meaning */ static void skip_spaces(const char **pp) @@ -1573,7 +1568,7 @@ static int http_parse_request(HTTPContext *c) if (modify_current_stream(c, ratebuf)) { for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) { if (c->switch_feed_streams[i] >= 0) - do_switch_stream(c, i); + c->switch_feed_streams[i] = -1; } } } @@ -1589,10 +1584,10 @@ static int http_parse_request(HTTPContext *c) } if (c->post == 0 && max_bandwidth < current_bandwidth) { - c->http_error = 200; + c->http_error = 503; q = c->buffer; q += snprintf(q, c->buffer_size, - "HTTP/1.0 200 Server too busy\r\n" + "HTTP/1.0 503 Server too busy\r\n" "Content-type: text/html\r\n" "\r\n" "Too busy\r\n" @@ -1859,7 +1854,7 @@ static int http_parse_request(HTTPContext *c) return 0; } -static void fmt_bytecount(ByteIOContext *pb, int64_t count) +static void fmt_bytecount(AVIOContext *pb, int64_t count) { static const char *suffix = " kMGTP"; const char *s; @@ -1876,7 +1871,7 @@ static void compute_status(HTTPContext *c) char *p; time_t ti; int i, len; - ByteIOContext *pb; + AVIOContext *pb; if (url_open_dyn_buf(&pb) < 0) { /* XXX: return an error ? */ @@ -2140,11 +2135,10 @@ static int open_input_stream(HTTPContext *c, const char *info) strcpy(input_filename, c->stream->feed->feed_filename); buf_size = FFM_PACKET_SIZE; /* compute position (absolute time) */ - if (find_info_tag(buf, sizeof(buf), "date", info)) { - stream_pos = parse_date(buf, 0); - if (stream_pos == INT64_MIN) - return -1; - } else if (find_info_tag(buf, sizeof(buf), "buffer", info)) { + if (av_find_info_tag(buf, sizeof(buf), "date", info)) { + if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0) + return ret; + } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) { int prebuffer = strtol(buf, 0, 10); stream_pos = av_gettime() - prebuffer * (int64_t)1000000; } else @@ -2153,10 +2147,9 @@ static int open_input_stream(HTTPContext *c, const char *info) strcpy(input_filename, c->stream->feed_filename); buf_size = 0; /* compute position (relative time) */ - if (find_info_tag(buf, sizeof(buf), "date", info)) { - stream_pos = parse_date(buf, 1); - if (stream_pos == INT64_MIN) - return -1; + if (av_find_info_tag(buf, sizeof(buf), "date", info)) { + if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0) + return ret; } else stream_pos = 0; } @@ -2344,7 +2337,7 @@ static int http_prepare_data(HTTPContext *c) for(i=0;istream->nb_streams;i++) { if (c->switch_feed_streams[i] == pkt.stream_index) if (pkt.flags & AV_PKT_FLAG_KEY) - do_switch_stream(c, i); + c->switch_feed_streams[i] = -1; if (c->switch_feed_streams[i] >= 0) c->switch_pending = 1; } @@ -2498,7 +2491,7 @@ static int http_send_data(HTTPContext *c) if (c->rtp_protocol == RTSP_LOWER_TRANSPORT_TCP) { /* RTP packets are sent inside the RTSP TCP connection */ - ByteIOContext *pb; + AVIOContext *pb; int interleaved_index, size; uint8_t header[4]; HTTPContext *rtsp_c; @@ -2521,10 +2514,10 @@ static int http_send_data(HTTPContext *c) header[1] = interleaved_index; header[2] = len >> 8; header[3] = len; - put_buffer(pb, header, 4); + avio_write(pb, header, 4); /* write RTP packet data */ c->buffer_ptr += 4; - put_buffer(pb, c->buffer_ptr, len); + avio_write(pb, c->buffer_ptr, len); size = url_close_dyn_buf(pb, &c->packet_buffer); /* prepare asynchronous TCP sending */ rtsp_c->packet_buffer_ptr = c->packet_buffer; @@ -2557,8 +2550,8 @@ static int http_send_data(HTTPContext *c) /* TCP data output */ len = send(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)) + if (ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) /* error : close connection */ return -1; else @@ -2631,8 +2624,8 @@ static int http_receive_data(HTTPContext *c) len = recv(c->fd, c->buffer_ptr, 1, 0); if (len < 0) { - if (ff_neterrno() != FF_NETERROR(EAGAIN) && - ff_neterrno() != FF_NETERROR(EINTR)) + if (ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) /* error : close connection */ goto fail; return 0; @@ -2658,8 +2651,8 @@ static int http_receive_data(HTTPContext *c) 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)) + if (ff_neterrno() != AVERROR(EAGAIN) && + ff_neterrno() != AVERROR(EINTR)) /* error : close connection */ goto fail; } else if (len == 0) @@ -2719,7 +2712,7 @@ static int http_receive_data(HTTPContext *c) } else { /* We have a header in our hands that contains useful data */ AVFormatContext *s = NULL; - ByteIOContext *pb; + AVIOContext *pb; AVInputFormat *fmt_in; int i; @@ -2890,7 +2883,7 @@ static int rtsp_parse_request(HTTPContext *c) len = sizeof(line) - 1; memcpy(line, p, len); line[len] = '\0'; - ff_rtsp_parse_line(header, line, NULL); + ff_rtsp_parse_line(header, line, NULL, NULL); p = p1 + 1; } @@ -2929,7 +2922,7 @@ static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer, struct in_addr my_ip) { AVFormatContext *avc; - AVStream avs[MAX_STREAMS]; + AVStream *avs = NULL; int i; avc = avformat_alloc_context(); @@ -2947,14 +2940,29 @@ static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer, snprintf(avc->filename, 1024, "rtp://0.0.0.0"); } +#if !FF_API_MAX_STREAMS + if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) || + !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams)))) + goto sdp_done; +#endif + if (avc->nb_streams >= INT_MAX/sizeof(*avs) || + !(avs = av_malloc(avc->nb_streams * sizeof(*avs)))) + goto sdp_done; + for(i = 0; i < stream->nb_streams; i++) { avc->streams[i] = &avs[i]; avc->streams[i]->codec = stream->streams[i]->codec; } *pbuffer = av_mallocz(2048); avf_sdp_create(&avc, 1, *pbuffer, 2048); + + sdp_done: +#if !FF_API_MAX_STREAMS + av_free(avc->streams); +#endif av_metadata_free(&avc->metadata); av_free(avc); + av_free(avs); return strlen(*pbuffer); } @@ -2978,7 +2986,7 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url) struct sockaddr_in my_addr; /* find which url is asked */ - ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); + av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') path++; @@ -3010,7 +3018,7 @@ static void rtsp_cmd_describe(HTTPContext *c, const char *url) url_fprintf(c->pb, "Content-Type: application/sdp\r\n"); url_fprintf(c->pb, "Content-Length: %d\r\n", content_length); url_fprintf(c->pb, "\r\n"); - put_buffer(c->pb, content, content_length); + avio_write(c->pb, content, content_length); av_free(content); } @@ -3055,7 +3063,7 @@ static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPActionServerSetup setup; /* find which url is asked */ - ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); + av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') path++; @@ -3191,14 +3199,14 @@ static HTTPContext *find_rtp_session_with_url(const char *url, char path1[1024]; const char *path; char buf[1024]; - int s; + int s, len; rtp_c = find_rtp_session(session_id); if (!rtp_c) return NULL; /* find which url is asked */ - ff_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); + av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url); path = path1; if (*path == '/') path++; @@ -3211,6 +3219,10 @@ static HTTPContext *find_rtp_session_with_url(const char *url, return rtp_c; } } + len = strlen(path); + if (len > 0 && path[len - 1] == '/' && + !strncmp(path, rtp_c->stream->filename, len - 1)) + return rtp_c; return NULL; } @@ -3477,6 +3489,7 @@ static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int cop fst->priv_data = av_mallocz(sizeof(FeedData)); fst->index = stream->nb_streams; av_set_pts_info(fst, 33, 1, 90000); + fst->sample_aspect_ratio = codec->sample_aspect_ratio; stream->streams[stream->nb_streams++] = fst; return fst; } @@ -3751,7 +3764,7 @@ static void build_feed_streams(void) } /* only write the header of the ffm file */ - if (url_fopen(&s->pb, feed->feed_filename, URL_WRONLY) < 0) { + if (avio_open(&s->pb, feed->feed_filename, URL_WRONLY) < 0) { http_log("Could not open output feed file '%s'\n", feed->feed_filename); exit(1); @@ -3770,7 +3783,7 @@ static void build_feed_streams(void) } /* XXX: need better api */ av_freep(&s->priv_data); - url_fclose(s->pb); + avio_close(s->pb); } /* get feed size and write index */ fd = open(feed->feed_filename, O_RDONLY); @@ -3952,27 +3965,11 @@ static int ffserver_opt_preset(const char *arg, { FILE *f=NULL; char filename[1000], tmp[1000], tmp2[1000], line[1000]; - int i, ret = 0; - const char *base[3]= { getenv("FFMPEG_DATADIR"), - getenv("HOME"), - FFMPEG_DATADIR, - }; - - for(i=0; i<3 && !f; i++){ - if(!base[i]) - continue; - snprintf(filename, sizeof(filename), "%s%s/%s.ffpreset", base[i], i != 1 ? "" : "/.ffmpeg", arg); - f= fopen(filename, "r"); - if(!f){ - AVCodec *codec = avcodec_find_encoder(avctx->codec_id); - if (codec) { - snprintf(filename, sizeof(filename), "%s%s/%s-%s.ffpreset", base[i], i != 1 ? "" : "/.ffmpeg", codec->name, arg); - f= fopen(filename, "r"); - } - } - } + int ret = 0; + AVCodec *codec = avcodec_find_encoder(avctx->codec_id); - if(!f){ + if (!(f = get_preset_file(filename, sizeof(filename), arg, 0, + codec ? codec->name : NULL))) { fprintf(stderr, "File for preset '%s' not found\n", arg); return 1; } @@ -4410,7 +4407,7 @@ static int parse_ffconfig(const char *filename) } else if (!strcasecmp(cmd, "VideoSize")) { get_arg(arg, sizeof(arg), &p); if (stream) { - av_parse_video_frame_size(&video_enc.width, &video_enc.height, arg); + av_parse_video_size(&video_enc.width, &video_enc.height, arg); if ((video_enc.width % 16) != 0 || (video_enc.height % 16) != 0) { ERROR("Image size must be a multiple of 16\n"); @@ -4420,7 +4417,7 @@ static int parse_ffconfig(const char *filename) get_arg(arg, sizeof(arg), &p); if (stream) { AVRational frame_rate; - if (av_parse_video_frame_rate(&frame_rate, arg) < 0) { + if (av_parse_video_rate(&frame_rate, arg) < 0) { ERROR("Incorrect frame rate: %s\n", arg); } else { video_enc.time_base.num = frame_rate.den;