Work in progress... Need support Signed-off-by: Lukasz Marek <lukasz.m.lu...@gmail.com> --- Makefile | 4 +- ffserver_config.c | 40 ++++++++++ ffserver_config.h | 7 ++ tools/ffserver_config_test.c | 178 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 tools/ffserver_config_test.c
diff --git a/Makefile b/Makefile index 1e1dbb3..41fd6c5 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ OBJS-ffserver += ffserver_config.o TESTTOOLS = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options -TOOLS = qt-faststart trasher uncoded_frame +TOOLS = qt-faststart trasher uncoded_frame ffserver_config_test TOOLS-$(CONFIG_ZLIB) += cws2fws # $(FFLIBS-yes) needs to be in linking order @@ -69,6 +69,8 @@ $(TOOLS): %$(EXESUF): %.o $(EXEOBJS) tools/cws2fws$(EXESUF): ELIBS = $(ZLIB) tools/uncoded_frame$(EXESUF): $(FF_DEP_LIBS) tools/uncoded_frame$(EXESUF): ELIBS = $(FF_EXTRALIBS) +tools/ffserver_config_test$(EXESUF): $(FF_DEP_LIBS) +tools/ffserver_config_test$(EXESUF): ELIBS = ffserver_config.o cmdutils.o $(FF_DEP_LIBS) -lm config.h: .config .config: $(wildcard $(FFLIBS:%=$(SRC_PATH)/lib%/all*.c)) diff --git a/ffserver_config.c b/ffserver_config.c index 355111c..511752b 100644 --- a/ffserver_config.c +++ b/ffserver_config.c @@ -1205,3 +1205,43 @@ int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config) #undef ERROR #undef WARNING + +static void ffserver_free_server_stream(FFServerStream *stream) +{ + int i; + + av_dict_free(&stream->in_opts); + av_dict_free(&stream->metadata); + while(stream->acl) { + FFServerIPAddressACL *acl = stream->acl; + stream->acl = acl->next; + av_free(acl); + } + for (i = 0; i < stream->nb_streams; i++) { + avcodec_free_context(&stream->streams[i]->codec); + av_free(stream->streams[i]); + } + av_free(stream); +} + +void ffserver_free_config(FFServerConfig *config) +{ + FFServerStream *st; + + if (!config) + return; + + config->first_feed = NULL; + while (config->first_stream) { + st = config->first_stream; + config->first_stream = st->next; + ffserver_free_server_stream(st); + } + av_freep(&config->filename); + + //make sure config parser state is also freed + av_dict_free(&config->video_opts); + av_dict_free(&config->audio_opts); + avcodec_free_context(&config->dummy_vctx); + avcodec_free_context(&config->dummy_actx); +} diff --git a/ffserver_config.h b/ffserver_config.h index 4e1e0e0..b62a6b7 100644 --- a/ffserver_config.h +++ b/ffserver_config.h @@ -128,4 +128,11 @@ void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream* feed, int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config); +/** + * Deallocate all memory used by the config + * + * @param config ffserver configuration + */ +void ffserver_free_config(FFServerConfig *config); + #endif /* FFSERVER_CONFIG_H */ diff --git a/tools/ffserver_config_test.c b/tools/ffserver_config_test.c new file mode 100644 index 0000000..0680d39 --- /dev/null +++ b/tools/ffserver_config_test.c @@ -0,0 +1,178 @@ + +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "../ffserver_config.h" + +const char *program_name=""; +const int program_birth_year=2014; +void show_help_default(const char *opt, const char *arg); +void show_help_default(const char *opt, const char *arg) +{ +} + +static int dummy_encode(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) +{ + return -1; +} + +AVCodec dummy_v_encoder = { + .name = "dummy_v_codec", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_NONE - 1, + .encode2 = dummy_encode, +}; + +AVCodec dummy_a_encoder = { + .name = "dummy_a_codec", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_NONE - 2, + .encode2 = dummy_encode, +}; + +static const char *config_file = "/tmp/__test_config.txt"; + +static struct { + const char *key; + const char *value; +} alias_stream_options[] = { + //common + {"Debug", "1"}, + {"Strict", "-2"}, + //audio + {"AudioBitRate", "192"}, + {"AudioChannels", "4"}, + {"AudioSampleRate", "22050"}, + //video + {"VideoBitRateRange", "1000-2000"}, + {"VideoBufferSize", "4"}, + {"VideoBitRateTolerance", "500"}, + {"VideoBitRate", "1500"}, + {"VideoSize", "1280x720"}, + {"VideoFrameRate", "25"}, + {"PixelFormat", "yuv420p"}, + {"VideoGopSize", "4"}, + {"VideoIntraOnly", ""}, + {"VideoHighQuality", ""}, + {"Video4MotionVector", ""}, + {"VideoTag", "XVID"}, + {"BitExact", ""}, + {"DctFastint", ""}, + {"IdctSimple", ""}, + {"Qscale", "4"}, + {"VideoQDiff", "4"}, + {"VideoQMax", "20"}, + {"VideoQMin", "5"}, + {"LumiMask", "0.5"}, + {"DarkMask", "0.5"}, + {NULL} +}; + +/* +static struct { + const char *key; + const char *value; + //(void)(*validator)(const char *opt, const char *arg, const FFServerConfig *config) +} stream[] = { + {"Format", ""}, + {"InputFormat", "0.5"}, + {"Metadata", "0.5"}, + {"Preroll", "0.5"}, + {"StartSendOnKey", "0.5"}, + {"NoVideo", ""}, + {"MaxTime", ""}, + {"NoAudio", ""}, + {"ACL", ""}, + {"DynamicACL", ""}, + {"RTSPOption", ""}, + {"MulticastAddress", ""}, + {"MulticastPort", ""}, + {"MulticastTTL", ""}, + {"NoLoop", ""}, + {"File", ""}, + {"ReadOnlyFile", ""}, + {NULL} +}; +*/ + +static int generate_config(int cnt, ...) +{ + FILE *f; + va_list vl; + int i; + const char *opt, *arg; + + f = fopen(config_file, "w"); + if (!f) + return -1; + + fprintf(f, "CustomLog -\n"); + fprintf(f, "<Feed test_feed1.ffm>\n"); + fprintf(f, " File /tmp/test_feed1.ffm\n"); + fprintf(f, " FileMaxSize 400K\n"); + fprintf(f, "</Feed>\n"); + fprintf(f, "<Stream test1.flv>\n"); + fprintf(f, " Feed test_feed1.ffm\n"); + fprintf(f, " VideoCodec dummy_v_codec\n"); + fprintf(f, " AudioCodec dummy_a_codec\n"); + va_start(vl, cnt); + for (i = 0; i < cnt; i++) { + opt = va_arg(vl, const char *); + arg = va_arg(vl, const char *); + fprintf(f, " %s %s\n", opt, arg); + } + va_end(vl); + fprintf(f, "</Stream>\n"); + + fclose(f); + return 0; +} + + +int main(void) +{ + FFServerConfig config = {0}; + int i, s, type; + AVCodecContext *ctx; + FFServerStream *st; + char *buf = NULL; + char t; + + av_register_all(); + avcodec_register(&dummy_v_encoder); + avcodec_register(&dummy_a_encoder); + config.use_defaults = 0; + + /* need to suppress error about missing defaults */ + av_log_set_level(AV_LOG_QUIET); + + printf("Testing aliased stream options\n"); + for (i = 0; alias_stream_options[i].key; i++) { + generate_config(1, alias_stream_options[i].key, alias_stream_options[i].value); + config.filename = av_strdup(config_file); + ffserver_parse_ffconfig(config_file, &config); + for (st = config.first_stream; st->is_feed; st = st->next) { + //just skip feed + } + printf("%s %s:\n", alias_stream_options[i].key, alias_stream_options[i].value); + for (s = 0; s < st->nb_streams; s++) { + if (st->streams[s]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + type = AV_OPT_FLAG_AUDIO_PARAM; + t = 'a'; + } else { + type = AV_OPT_FLAG_VIDEO_PARAM; + t = 'v'; + } + ctx = st->streams[s]->codec; + av_opt_serialize(ctx, 0, AV_OPT_SERIALIZE_SKIP_DEFAULTS | AV_OPT_SERIALIZE_OPT_FLAGS_EXACT, &buf, '=', ','); + printf("%c:%s,", t, buf); + av_freep(&buf); + av_opt_serialize(ctx, type | AV_OPT_FLAG_ENCODING_PARAM , AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ','); + printf("%s\n", buf); + av_freep(&buf); + } + ffserver_free_config(&config); + } + + + return 0; +} -- 1.9.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel