[FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader
Stephan Holljes
klaxa1337 at googlemail.com
Sun May 20 21:53:58 EEST 2018
Signed-off-by: Stephan Holljes <klaxa1337 at googlemail.com>
---
configreader.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
configreader.h | 46 +++++++++++++
2 files changed, 257 insertions(+)
create mode 100644 configreader.c
create mode 100644 configreader.h
diff --git a/configreader.c b/configreader.c
new file mode 100644
index 0000000..84b27fa
--- /dev/null
+++ b/configreader.c
@@ -0,0 +1,211 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "configreader.h"
+#include "httpd.h"
+#include <stdio.h>
+#include <string.h>
+#include <lua5.3/lua.h>
+#include <lua5.3/lauxlib.h>
+#include <lua5.3/lualib.h>
+
+#include <libavutil/mem.h>
+
+const char *stream_format_names[] = { "mkv" };
+
+void stream_free(struct StreamConfig *stream)
+{
+ if (stream->stream_name)
+ av_free(stream->stream_name);
+ if (stream->input_uri)
+ av_free(stream->input_uri);
+ if (stream->formats)
+ av_free(stream->formats);
+}
+
+void config_free(struct HTTPDConfig *config)
+{
+ int i;
+ if (config->server_name)
+ av_free(config->server_name);
+ if (config->bind_address)
+ av_free(config->bind_address);
+ if (config->streams) {
+ for (i = 0; i < config->nb_streams; i++)
+ stream_free(&config->streams[i]);
+ av_free(config->streams);
+ }
+}
+
+void config_dump(struct HTTPDConfig *config) {
+ int i, j;
+ printf("======\nserver name: %s\nbind_address: %s\nport: %d\nnb_streams: %d\n",
+ config->server_name, config->bind_address, config->port, config->nb_streams);
+ for (i = 0; i < config->nb_streams; i++) {
+ printf("------\nstream_name: %s\ninput: %s\nformats: ",
+ config->streams[i].stream_name, config->streams[i].input_uri);
+ for (j = 0; j < config->streams[i].nb_formats; j++) {
+ printf("%s ", stream_format_names[config->streams[i].formats[j]]);
+ }
+ printf("\n");
+ }
+}
+
+int configs_read(struct HTTPDConfig **configs, const char *filename)
+{
+ int ret = 0;
+ int nb_configs = 0;
+ int nb_streams = 0;
+ int nb_formats = 0;
+ int i;
+ int index = 0;
+ const char *key, *error;
+ struct HTTPDConfig *parsed_configs = NULL;
+ struct HTTPDConfig *config;
+ struct StreamConfig *stream;
+ lua_State *L = luaL_newstate();
+ ret = luaL_loadfile(L, filename);
+ if (ret != 0) {
+ fprintf(stderr, "Unable to open config file: %s\n", lua_tostring(L, -1));
+ lua_close(L);
+ return -1;
+ }
+
+ ret = lua_pcall(L, 0, 0, 0);
+
+ if (ret != 0) {
+ fprintf(stderr, "Unable to read config file: %s\n", lua_tostring(L, -1));
+ lua_close(L);
+ return -1;
+ }
+ lua_getglobal(L, "settings");
+ if (lua_type(L, -1) != LUA_TTABLE) {
+ lua_pushstring(L, "Error \"settings\" is not a table");
+ goto fail;
+ }
+ lua_pushnil(L);
+
+ // iterate servers
+ while (lua_next(L, -2) != 0) {
+ nb_configs++;
+ parsed_configs = av_realloc(parsed_configs, nb_configs * sizeof(struct HTTPDConfig));
+ config = &parsed_configs[nb_configs - 1];
+ config->server_name = NULL;
+ config->bind_address = NULL;
+ config->port = 0;
+ config->accept_timeout = 1000;
+ config->streams = NULL;
+ config->nb_streams = 0;
+ if (lua_type(L, -2) != LUA_TSTRING) {
+ lua_pushstring(L, "Error server name is not a string.");
+ goto fail;
+ }
+ if (lua_type(L, -1) != LUA_TTABLE) {
+ lua_pushstring(L, "Error server settings is not a table.");
+ goto fail;
+ }
+ config->server_name = av_strdup(lua_tostring(L, -2));
+ lua_pushnil(L);
+ // iterate server properties
+ nb_streams = 0;
+ while(lua_next(L, -2) != 0) {
+ if (lua_type(L, -2) != LUA_TSTRING) {
+ lua_pushstring(L, "Error server property is not a string.");
+ goto fail;
+ }
+ key = lua_tostring(L, -2);
+ if (!strncmp("bind_address", key, 12)) {
+ config->bind_address = av_strdup(lua_tostring(L, -1));
+ } else if (!strncmp("port", key, 4)) {
+ config->port = (int) lua_tonumber(L, -1);
+ } else {
+ // keys that are not "bind_address" or "port" are streams
+ if (lua_type(L, -1) != LUA_TTABLE) {
+ lua_pushstring(L, "Error Stream configuration is not a table.");
+ goto fail;
+ }
+
+ nb_streams++;
+ config->streams = av_realloc(config->streams, nb_streams * sizeof(struct StreamConfig));
+ stream = &config->streams[nb_streams - 1];
+ stream->input_uri = NULL;
+ stream->formats = NULL;
+ stream->stream_name = av_strdup(lua_tostring(L, -2));
+ lua_pushnil(L);
+ while(lua_next(L, -2) != 0) {
+ if (lua_type(L, -2) != LUA_TSTRING) {
+ lua_pushstring(L, "Error stream property is not a string.");
+ goto fail;
+ }
+ key = lua_tostring(L, -2);
+ if (!strncmp("input", key, 5)) {
+ stream->input_uri = av_strdup(lua_tostring(L, -1));
+ } else if (!strncmp("formats", key, 7)) {
+ index = 1;
+ nb_formats = 0;
+ lua_pushnumber(L, index);
+ while(1) {
+ lua_gettable(L, -2);
+ if (lua_isnil(L, -1))
+ break;
+ if (lua_type(L, -1) != LUA_TSTRING) {
+ lua_pushstring(L, "Error format name is not a string.");
+ goto fail;
+ }
+ stream->formats = av_realloc(stream->formats,
+ (nb_formats + 1) * sizeof(enum StreamFormat));
+ key = lua_tostring(L, -1);
+ if (!strncmp("mkv", key, 3)) {
+ stream->formats[nb_formats++] = FMT_MATROSKA;
+ } else {
+ fprintf(stderr, "Warning unknown format (%s) in stream format configuration.\n",
+ key);
+ av_realloc(stream->formats, nb_formats * sizeof(enum StreamFormat));
+ }
+ stream->nb_formats = nb_formats;
+ lua_pop(L, 1);
+ lua_pushnumber(L, ++index);
+ }
+ lua_pop(L, 1);
+
+ } else {
+ fprintf(stderr, "Warning unknown key (%s) in stream configuration.\n", key);
+ }
+ lua_pop(L, 1);
+ }
+ }
+ lua_pop(L, 1);
+ }
+ config->nb_streams = nb_streams;
+ lua_pop(L, 1);
+ }
+
+ lua_close(L);
+ *configs = parsed_configs;
+ return nb_configs;
+
+fail:
+ error = lua_tostring(L, -1);
+ fprintf(stderr, "%s\n", error);
+ lua_close(L);
+ for (i = 0; i < nb_configs; i++)
+ config_free(&parsed_configs[i]);
+ av_free(parsed_configs);
+ return -1;
+}
+
diff --git a/configreader.h b/configreader.h
new file mode 100644
index 0000000..788ff60
--- /dev/null
+++ b/configreader.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef CONFIGREADER_H
+#define CONFIGREADER_H
+
+#include "httpd.h"
+
+/**
+ * Read configurations from a file using the json format. The configurations
+ * are allocated as an array at *configs. This has to be freed by the user.
+ *
+ * @param configs pointer to a pointer where configurations will be allocated.
+ * @param filename filename of the configuration to use.
+ * @return number of configurations read, -1 on error.
+ */
+int configs_read(struct HTTPDConfig **configs, const char *filename);
+
+/**
+ * Dump a configuration to stdout.
+ * @param config pointer to a configuration
+ */
+void config_dump(struct HTTPDConfig *config);
+
+/**
+ * Free a configuration.
+ * @param config pointer to a configuration
+ */
+void config_free(struct HTTPDConfig *config);
+
+#endif
--
2.16.2
More information about the ffmpeg-devel
mailing list