[FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader

2018-05-31 Thread Stephan Holljes
Signed-off-by: Stephan Holljes 
---
 configreader.c | 230 +
 configreader.h |  47 
 2 files changed, 277 insertions(+)
 create mode 100644 configreader.c
 create mode 100644 configreader.h

diff --git a/configreader.c b/configreader.c
new file mode 100644
index 000..88bba26
--- /dev/null
+++ b/configreader.c
@@ -0,0 +1,230 @@
+/*
+ * 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 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+const char *stream_format_names[] = { "mkv" };
+
+static struct HTTPDConfig *parsed_configs = NULL;
+
+void stream_free(struct StreamConfig *stream)
+{
+av_freep(>stream_name);
+av_freep(>input_uri);
+av_freep(>formats);
+}
+
+void config_free(struct HTTPDConfig *config)
+{
+int i;
+av_freep(>server_name);
+av_freep(>bind_address);
+if (config->streams) {
+for (i = 0; i < config->nb_streams; i++)
+stream_free(>streams[i]);
+av_freep(>streams);
+}
+}
+
+void config_dump(struct HTTPDConfig *config, FILE *stream) {
+int i, j;
+fprintf(stream, "==\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++) {
+fprintf(stream, "--\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++) {
+fprintf(stream, "%s ", 
stream_format_names[config->streams[i].formats[j]]);
+}
+fprintf(stream, "\n");
+}
+}
+
+int configs_parse(lua_State *L)
+{
+int nb_configs = 0;
+int nb_streams = 0;
+int nb_formats = 0;
+int index = 0;
+const char *key;
+struct HTTPDConfig *config;
+struct StreamConfig *stream;
+
+luaL_checktype(L, -1, LUA_TTABLE);
+lua_pushnil(L);
+
+// iterate servers
+while (lua_next(L, -2) != 0) {
+nb_configs++;
+parsed_configs = av_realloc(parsed_configs, nb_configs * sizeof(struct 
HTTPDConfig));
+if (!parsed_configs) {
+return luaL_error(L, "Error could not allocate memory for 
configs");
+}
+luaL_checktype(L, -2, LUA_TSTRING);
+luaL_checktype(L, -1, LUA_TTABLE);
+config = _configs[nb_configs - 1];
+config->server_name = NULL;
+config->bind_address = NULL;
+config->port = -1;
+config->accept_timeout = 1000;
+config->streams = NULL;
+config->nb_streams = 0;
+
+config->server_name = av_strdup(lua_tostring(L, -2));
+if (!config->server_name) {
+return luaL_error(L, "Error could not allocate server name 
string");
+}
+lua_pushnil(L);
+// iterate server properties
+nb_streams = 0;
+while(lua_next(L, -2) != 0) {
+luaL_checktype(L, -2, LUA_TSTRING);
+key = lua_tostring(L, -2);
+if (!strncmp("bind_address", key, 12)) {
+config->bind_address = av_strdup(lua_tostring(L, -1));
+if (!config->bind_address) {
+return luaL_error(L, "Error could not allocate bind 
address string");
+}
+} else if (!strncmp("port", key, 4)) {
+config->port = (int) lua_tonumber(L, -1);
+} else {
+// keys that are not "bind_address" or "port" are streams
+luaL_checktype(L, -1, LUA_TTABLE);
+
+nb_streams++;
+config->streams = av_realloc(config->streams, nb_streams * 
sizeof(struct StreamConfig));
+if (!config->streams) {
+return luaL_error(L, "Error could not allocate memory for 
streams");
+}
+stream = >streams[nb_streams - 1];
+stream->input_uri = NULL;
+stream->formats = NULL;
+stream->nb_formats = 0;
+stream->stream_name = av_strdup(lua_tostring(L, -2));
+if (!stream->stream_name) {
+

Re: [FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader

2018-05-28 Thread Michael Niedermayer
On Mon, May 28, 2018 at 08:18:53PM +0200, Stephan Holljes wrote:
> Signed-off-by: Stephan Holljes 
> ---
>  configreader.c | 235 
> +
>  configreader.h |  47 
>  2 files changed, 282 insertions(+)
>  create mode 100644 configreader.c
>  create mode 100644 configreader.h
> 
> diff --git a/configreader.c b/configreader.c
> new file mode 100644
> index 000..3580fc5
> --- /dev/null
> +++ b/configreader.c
> @@ -0,0 +1,235 @@
> +/*
> + * 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 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +const char *stream_format_names[] = { "mkv" };
> +
> +static struct HTTPDConfig *parsed_configs = NULL;
> +
> +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);

the null checks arent needed
also av_freep() may be better as it does not leave the freed pointer but
replaces with with NULL


[...]

-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

I do not agree with what you have to say, but I'll defend to the death your
right to say it. -- Voltaire


signature.asc
Description: PGP signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader

2018-05-28 Thread Stephan Holljes
Signed-off-by: Stephan Holljes 
---
 configreader.c | 235 +
 configreader.h |  47 
 2 files changed, 282 insertions(+)
 create mode 100644 configreader.c
 create mode 100644 configreader.h

diff --git a/configreader.c b/configreader.c
new file mode 100644
index 000..3580fc5
--- /dev/null
+++ b/configreader.c
@@ -0,0 +1,235 @@
+/*
+ * 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 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+const char *stream_format_names[] = { "mkv" };
+
+static struct HTTPDConfig *parsed_configs = NULL;
+
+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(>streams[i]);
+av_free(config->streams);
+}
+}
+
+void config_dump(struct HTTPDConfig *config, FILE *stream) {
+int i, j;
+fprintf(stream, "==\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++) {
+fprintf(stream, "--\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++) {
+fprintf(stream, "%s ", 
stream_format_names[config->streams[i].formats[j]]);
+}
+fprintf(stream, "\n");
+}
+}
+
+int configs_parse(lua_State *L)
+{
+int nb_configs = 0;
+int nb_streams = 0;
+int nb_formats = 0;
+int index = 0;
+const char *key;
+struct HTTPDConfig *config;
+struct StreamConfig *stream;
+
+luaL_checktype(L, -1, LUA_TTABLE);
+lua_pushnil(L);
+
+// iterate servers
+while (lua_next(L, -2) != 0) {
+nb_configs++;
+parsed_configs = av_realloc(parsed_configs, nb_configs * sizeof(struct 
HTTPDConfig));
+if (!parsed_configs) {
+return luaL_error(L, "Error could not allocate memory for 
configs");
+}
+luaL_checktype(L, -2, LUA_TSTRING);
+luaL_checktype(L, -1, LUA_TTABLE);
+config = _configs[nb_configs - 1];
+config->server_name = NULL;
+config->bind_address = NULL;
+config->port = -1;
+config->accept_timeout = 1000;
+config->streams = NULL;
+config->nb_streams = 0;
+
+config->server_name = av_strdup(lua_tostring(L, -2));
+if (!config->server_name) {
+return luaL_error(L, "Error could not allocate server name 
string");
+}
+lua_pushnil(L);
+// iterate server properties
+nb_streams = 0;
+while(lua_next(L, -2) != 0) {
+luaL_checktype(L, -2, LUA_TSTRING);
+key = lua_tostring(L, -2);
+if (!strncmp("bind_address", key, 12)) {
+config->bind_address = av_strdup(lua_tostring(L, -1));
+if (!config->bind_address) {
+return luaL_error(L, "Error could not allocate bind 
address string");
+}
+} else if (!strncmp("port", key, 4)) {
+config->port = (int) lua_tonumber(L, -1);
+} else {
+// keys that are not "bind_address" or "port" are streams
+luaL_checktype(L, -1, LUA_TTABLE);
+
+nb_streams++;
+config->streams = av_realloc(config->streams, nb_streams * 
sizeof(struct StreamConfig));
+if (!config->streams) {
+return luaL_error(L, "Error could not allocate memory for 
streams");
+}
+stream = >streams[nb_streams - 1];
+stream->input_uri = NULL;
+

Re: [FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader

2018-05-21 Thread Stephan Holljes
On Mon, May 21, 2018 at 3:04 PM, James Darnley  wrote:
> On 2018-05-20 20:53, Stephan Holljes wrote:
>> +#include 
>> +#include 
>> +#include 
>
> That's not portable.  Lua headers are not in a subdirectory.

Yes, artifact from early testing, changed and tested, pkg-config adds
the appropriate include directories.

>
>> +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 = _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 = >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 

Re: [FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader

2018-05-21 Thread James Darnley
On 2018-05-20 20:53, Stephan Holljes wrote:
> +#include 
> +#include 
> +#include 

That's not portable.  Lua headers are not in a subdirectory.

> +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 = _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 = >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",
> +   

Re: [FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader

2018-05-20 Thread Michael Niedermayer
On Sun, May 20, 2018 at 08:53:58PM +0200, Stephan Holljes wrote:
> Signed-off-by: Stephan Holljes 
> ---
>  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 000..84b27fa
> --- /dev/null
> +++ b/configreader.c
> @@ -0,0 +1,211 @@
[...]
> +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 = _configs[nb_configs - 1];

Missing realloc failure handling


> +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));

Missing alloc failure check, same with other similar allocation

[...]
> +fail:
> +error = lua_tostring(L, -1);
> +fprintf(stderr, "%s\n", error);
> +lua_close(L);
> +for (i = 0; i < nb_configs; i++)
> +config_free(_configs[i]);
> +av_free(parsed_configs);

> +return -1;
> +}

We probably should use error codes (AVERROR*) from the begin.
Otherwise it would need a "2nd" pass one day to cleanup


> +
> diff --git a/configreader.h b/configreader.h
> new file mode 100644
> index 000..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);

it may be more flexible to add a argument that can point to stdout/stderr/file

[...]

-- 
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If you drop bombs on a foreign country and kill a hundred thousand
innocent people, expect your government to call the consequence
"unprovoked inhuman terrorist attacks" and use it to justify dropping
more bombs and killing more people. The technology changed, the idea is old.



[FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader

2018-05-20 Thread Stephan Holljes
Signed-off-by: Stephan Holljes 
---
 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 000..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 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+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(>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 = _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 {
+//