diff options
author | Reynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com> | 2015-12-16 18:14:25 -0800 |
---|---|---|
committer | Reynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com> | 2015-12-19 01:52:20 -0800 |
commit | ae2ed20b5912b00866631e78049f165deb9f2fb2 (patch) | |
tree | 2f88abea264ce6d6b5610d40c3e6e5d52328acf1 | |
parent | 4ba148a6ea2c3f2491f1dc60246dd62c665ce1cf (diff) | |
download | ffmpeg-ae2ed20b5912b00866631e78049f165deb9f2fb2.tar.gz |
ffserver: refactor build_feed_streams()
* Avoid excesive nesting that made it really hard to follow
* Drop unneeded vars
* Factor out codec compatibility check routine
* Ensure inputs are closed and contexts are freed as needed
before returning
Signed-off-by: Reynaldo H. Verdejo Pinochet <reynaldo@osg.samsung.com>
-rw-r--r-- | ffserver.c | 172 |
1 files changed, 98 insertions, 74 deletions
diff --git a/ffserver.c b/ffserver.c index 65044e6d15..c7dbb16f80 100644 --- a/ffserver.c +++ b/ffserver.c @@ -242,6 +242,9 @@ static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr, static int rtp_new_av_stream(HTTPContext *c, int stream_index, struct sockaddr_in *dest_addr, HTTPContext *rtsp_c); +/* utils */ +static inline int check_codec_match(AVCodecContext *ccf, AVCodecContext *ccs, + int stream); static const char *my_program_name; @@ -3624,11 +3627,46 @@ static void build_file_streams(void) } } +static inline +int check_codec_match(AVCodecContext *ccf, AVCodecContext *ccs, int stream) +{ + int matches = 1; + +#define CHECK_CODEC(x) (ccf->x != ccs->x) + if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) { + http_log("Codecs do not match for stream %d\n", stream); + matches = 0; + } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) { + http_log("Codec bitrates do not match for stream %d\n", stream); + matches = 0; + } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) { + if (CHECK_CODEC(time_base.den) || + CHECK_CODEC(time_base.num) || + CHECK_CODEC(width) || + CHECK_CODEC(height)) { + http_log("Codec width, height or framerate do not match for stream %d\n", stream); + matches = 0; + } + } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) { + if (CHECK_CODEC(sample_rate) || + CHECK_CODEC(channels) || + CHECK_CODEC(frame_size)) { + http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", stream); + matches = 0; + } + } else { + http_log("Unknown codec type for stream %d\n", stream); + matches = 0; + } + + return matches; +} + /* compute the needed AVStream for each feed */ static int build_feed_streams(void) { FFServerStream *stream, *feed; - int i; + int i, fd; /* gather all streams */ for(stream = config.first_stream; stream; stream = stream->next) { @@ -3639,98 +3677,77 @@ static int build_feed_streams(void) if (stream->is_feed) { for(i=0;i<stream->nb_streams;i++) stream->feed_streams[i] = i; - } else { - /* we handle a stream coming from a feed */ - for(i=0;i<stream->nb_streams;i++) - stream->feed_streams[i] = add_av_stream(feed, - stream->streams[i]); + continue; } + /* we handle a stream coming from a feed */ + for(i=0;i<stream->nb_streams;i++) + stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]); } /* create feed files if needed */ for(feed = config.first_feed; feed; feed = feed->next_feed) { - int fd; if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) { - /* See if it matches */ AVFormatContext *s = NULL; int matches = 0; - if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) { - /* set buffer size */ - int ret = ffio_set_buf_size(s->pb, FFM_PACKET_SIZE); - if (ret < 0) { - http_log("Failed to set buffer size\n"); - goto bail; - } + /* See if it matches */ - /* Now see if it matches */ - if (s->nb_streams == feed->nb_streams) { - matches = 1; - for(i=0;i<s->nb_streams;i++) { - AVStream *sf, *ss; - sf = feed->streams[i]; - ss = s->streams[i]; - - if (sf->index != ss->index || - sf->id != ss->id) { - http_log("Index & Id do not match for stream %d (%s)\n", - i, feed->feed_filename); - matches = 0; - } else { - AVCodecContext *ccf, *ccs; - - ccf = sf->codec; - ccs = ss->codec; -#define CHECK_CODEC(x) (ccf->x != ccs->x) + if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) < 0) { + http_log("Deleting feed file '%s' as it appears " + "to be corrupt\n", + feed->feed_filename); + goto drop; + } - if (CHECK_CODEC(codec_id) || CHECK_CODEC(codec_type)) { - http_log("Codecs do not match for stream %d\n", i); - matches = 0; - } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) { - http_log("Codec bitrates do not match for stream %d\n", i); - matches = 0; - } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) { - if (CHECK_CODEC(time_base.den) || - CHECK_CODEC(time_base.num) || - CHECK_CODEC(width) || - CHECK_CODEC(height)) { - http_log("Codec width, height and framerate do not match for stream %d\n", i); - matches = 0; - } - } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) { - if (CHECK_CODEC(sample_rate) || - CHECK_CODEC(channels) || - CHECK_CODEC(frame_size)) { - http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i); - matches = 0; - } - } else { - http_log("Unknown codec type\n"); - matches = 0; - } - } - if (!matches) - break; - } - } else - http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n", - feed->feed_filename, s->nb_streams, feed->nb_streams); + /* set buffer size */ + if (ffio_set_buf_size(s->pb, FFM_PACKET_SIZE) < 0) { + http_log("Failed to set buffer size\n"); + avformat_close_input(&s); + goto bail; + } + + /* Now see if it matches */ + if (s->nb_streams != feed->nb_streams) { + http_log("Deleting feed file '%s' as stream counts " + "differ (%d != %d)\n", + feed->feed_filename, s->nb_streams, feed->nb_streams); + goto drop; + } + + matches = 1; + for(i=0;i<s->nb_streams;i++) { + AVStream *sf, *ss; + + sf = feed->streams[i]; + ss = s->streams[i]; + if (sf->index != ss->index || sf->id != ss->id) { + http_log("Index & Id do not match for stream %d (%s)\n", + i, feed->feed_filename); + matches = 0; + break; + } + + matches = check_codec_match (sf->codec, ss->codec, i); + if (!matches) + break; + } + +drop: + if (s) avformat_close_input(&s); - } else - http_log("Deleting feed file '%s' as it appears to be corrupt\n", - feed->feed_filename); if (!matches) { if (feed->readonly) { - http_log("Unable to delete feed file '%s' as it is marked readonly\n", - feed->feed_filename); + http_log("Unable to delete read-only feed file '%s'\n", + feed->feed_filename); goto bail; } unlink(feed->feed_filename); } } + if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) { AVFormatContext *s = avformat_alloc_context(); @@ -3740,8 +3757,10 @@ static int build_feed_streams(void) } if (feed->readonly) { - http_log("Unable to create feed file '%s' as it is marked readonly\n", - feed->feed_filename); + http_log("Unable to create feed file '%s' as it is " + "marked readonly\n", + feed->feed_filename); + avformat_free_context(s); goto bail; } @@ -3749,6 +3768,7 @@ static int build_feed_streams(void) if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) { http_log("Could not open output feed file '%s'\n", feed->feed_filename); + avformat_free_context(s); goto bail; } s->oformat = feed->fmt; @@ -3756,6 +3776,8 @@ static int build_feed_streams(void) s->streams = feed->streams; if (avformat_write_header(s, NULL) < 0) { http_log("Container doesn't support the required parameters\n"); + avio_closep(&s->pb); + avformat_free_context(s); goto bail; } /* XXX: need better API */ @@ -3765,6 +3787,7 @@ static int build_feed_streams(void) s->nb_streams = 0; avformat_free_context(s); } + /* get feed size and write index */ fd = open(feed->feed_filename, O_RDONLY); if (fd < 0) { @@ -3773,7 +3796,8 @@ static int build_feed_streams(void) goto bail; } - feed->feed_write_index = FFMAX(ffm_read_write_index(fd), FFM_PACKET_SIZE); + feed->feed_write_index = FFMAX(ffm_read_write_index(fd), + FFM_PACKET_SIZE); feed->feed_size = lseek(fd, 0, SEEK_END); /* ensure that we do not wrap before the end of file */ if (feed->feed_max_size && feed->feed_max_size < feed->feed_size) |