[FFmpeg-devel] [PATCH 06/11] [WIP][RFC]tools: add ffserver_config_test

Lukasz Marek lukasz.m.luki2 at gmail.com
Mon Nov 17 02:46:53 CET 2014


Work in progress...
Need support

Signed-off-by: Lukasz Marek <lukasz.m.luki2 at 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



More information about the ffmpeg-devel mailing list