[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