From patchwork Mon May 28 18:18:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephan Holljes X-Patchwork-Id: 9124 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:11c:0:0:0:0:0 with SMTP id c28-v6csp2230259jad; Mon, 28 May 2018 11:26:41 -0700 (PDT) X-Google-Smtp-Source: AB8JxZo6VScyxFvy4GYKInD3lUJdRZmLyQHygriyiXpE+Mw8aeBTQb3tL1quNLatNmuDsnNblaFT X-Received: by 2002:adf:c32b:: with SMTP id n40-v6mr11961908wrf.91.1527532001228; Mon, 28 May 2018 11:26:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527532001; cv=none; d=google.com; s=arc-20160816; b=gxlEd32eGURrzEj4SY45aiPMWYRxPtmZXGYtFyP5p5rXQdiKRONTaL0pe+5haMZR7q 4KgTH1psAYcQ2A9XlRQcNb7IMR+3gFdcj0T+rahGdYiUMwTV8+fHWWOM6A5g8SURVBw4 ysbW1cyobGsh376dAMfi134y6NeYF/+8kILOXJ4ji3AyzQloG3gfVRuOBu5rKxq2JL1/ YTKAScTAHy8J/tSZw4xAK6TbYcF89CXkoljuRyEfd8/aultXxuyJG0BoY5bEkF+DlYoG mE+VfDnTmtQDIS48pXbTbvoveCcMqeRK4Cek2suGacMcYoBitl7hrP7xvAXurivJHuCJ dZIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=7YqRAkbQi4QPV3DVzufkSzX1GXYUR5oBbTOJLiGaERo=; b=adHy3rWJ4Lz9bf7wr6bIRKM0kt2vz/WA5WCah0gbzZzWJf3Vj7rHFKhowUZxJDdlyG A50bF+ZJC8WSUup2nVdrIhMh0MN8pY567QL5pGlIPrwAdStja3DTGakMqcEG3xP54/aj /hkqteep1siDbcsInIn+xi7uK2UwRNO+U2PdKRZMCUXrWXCnHeM6CrCyCP3xrT/Zk8fB S/AfkHkPFQpWgVMoBJl6J1tGsPLhKBXH+u13ZXiEPFvA+3hudDNdnG3UUbl30pDiCuJu xrt+d5IQrJ9eUygLUlN2FZeOKsli1LsDWTJWDwQigrczFcPl1e6UM5+7Nz8XJ9YDyyeN wqQA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@googlemail.com header.s=20161025 header.b=J/CZy64k; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id n86-v6si10373531wmi.174.2018.05.28.11.26.40; Mon, 28 May 2018 11:26:41 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@googlemail.com header.s=20161025 header.b=J/CZy64k; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1714368A331; Mon, 28 May 2018 21:25:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f196.google.com (mail-wr0-f196.google.com [209.85.128.196]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4B33C68A08D for ; Mon, 28 May 2018 21:25:54 +0300 (EEST) Received: by mail-wr0-f196.google.com with SMTP id v13-v6so9869825wrp.13 for ; Mon, 28 May 2018 11:26:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=HCYhWB9MPn5knGeWR/NE6tQeCPXLqFuY9LJ2lAfbaxI=; b=J/CZy64kOXeulpfguHGqnD13AIzrnRxJQwG25p/YNPhnDmhvlGPFK9v0NpwC7aFeO2 v4sc5r61zx78WOqUx8V63b7oGyaqpBufly21oFlmLOi7127OjKNhNkMupAQYl9b///P0 1GxXDVnWYD4W6kTJBaJPm94nK9q4oEkT20r5+jgfEZ28DADU9rZ8UlVs4A7HV1zbJExO kifKTQPSSyzk38bF8cKq0NHhMLvnlTtR/hblOKydrcSqJnLvwSRpZ53aycRIUXdhPJ5/ x/kQt+EiVk2EwKcSmJrLfjGoiobyewZSGB7cItK8tEyxP9c8vRQ0DRW3re7HQhvZXdpG aHbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HCYhWB9MPn5knGeWR/NE6tQeCPXLqFuY9LJ2lAfbaxI=; b=CC4rYHB/YDi/eKcsAQkGmbCwxfbgizXBRtBX9gl1NxqGnH6+LA9cL/Abl0AOwykQIF nlnqWE4UsbbXqKqwVQypwE9GR7Whfk0jCbrxE6GZub5HAE2X0fI61ZDhFTkUtLhZgw4i K8NPzy36n3oKFWm1m4hVtLONcVfx8odNcgz5zwq8tKL7RLJcgo/lEDJeH8sd5EUi8Vir ZV+ArKkNiONUdMdtbnxr2TiLWi3Szqba2bZ7c5bL0SrphP6P3DGjT9vRvQO7SfvMW+dI W9UYBG1+rA0Qlp1ZcX7XGVW5UkJwQvSA3hWkzjnVspULA03OHsca25TFSuwMscU+bz7G O7xw== X-Gm-Message-State: ALKqPwfrtUkpNgxkj87wkWIk/RK2sEu6XayWZScA6le4AVp1Q1RsmhkS EteqjXLsrpvzXTpJBn85YxwyMg== X-Received: by 2002:adf:eace:: with SMTP id o14-v6mr9881857wrn.150.1527531566865; Mon, 28 May 2018 11:19:26 -0700 (PDT) Received: from localhost.localdomain ([46.5.2.0]) by smtp.gmail.com with ESMTPSA id p5-v6sm14649465wre.83.2018.05.28.11.19.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 May 2018 11:19:26 -0700 (PDT) From: Stephan Holljes To: ffmpeg-devel@ffmpeg.org Date: Mon, 28 May 2018 20:18:53 +0200 Message-Id: <20180528181859.12182-3-klaxa1337@googlemail.com> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180528181859.12182-1-klaxa1337@googlemail.com> References: <20180520185404.29836-1-klaxa1337@googlemail.com> <20180528181859.12182-1-klaxa1337@googlemail.com> Subject: [FFmpeg-devel] [PATCH 2/8] ffserver: Implement lua config file reader X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Stephan Holljes MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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 0000000..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(&config->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 = &parsed_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 = &config->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) { + return luaL_error(L, "Error could not allocate stream name string"); + } + lua_pushnil(L); + while(lua_next(L, -2) != 0) { + luaL_checktype(L, -2, LUA_TSTRING); + key = lua_tostring(L, -2); + if (!strncmp("input", key, 5)) { + stream->input_uri = av_strdup(lua_tostring(L, -1)); + if (!stream->input_uri) { + return luaL_error(L, "Error could not allocate input_uri"); + } + } 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; + luaL_checktype(L, -1, LUA_TSTRING); + stream->formats = av_realloc(stream->formats, + (nb_formats + 1) * sizeof(enum StreamFormat)); + if (!stream->formats) { + return luaL_error(L, "Error could not allocate stream formats"); + } + 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)); + if (!stream->formats) { + return luaL_error(L, "Error could not shrink stream formats"); + } + } + 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); + } + if (stream->nb_formats == 0) + luaL_error(L, "No format specified for stream %s on server %s", stream->stream_name, config->server_name); + } + lua_pop(L, 1); + } + if (config->port == -1) + return luaL_error(L, "No port set for server: %s", config->server_name); + if (!config->bind_address) + return luaL_error(L, "No bind address set for server: %s", config->server_name); + config->nb_streams = nb_streams; + lua_pop(L, 1); + } + lua_pushnumber(L, nb_configs); + return 1; +} + + +int configs_read(struct HTTPDConfig **configs, const char *filename) +{ + int ret = 0; + int nb_configs = 0; + 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 AVERROR_INVALIDDATA; + } + + 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 AVERROR_INVALIDDATA; + } + + lua_pushcfunction(L, configs_parse); + lua_getglobal(L, "settings"); + + ret = lua_pcall(L, 1, 1, 0); + + if (ret != 0) { + fprintf(stderr, "Unable to parse config file: %s\n", lua_tostring(L, -1)); + lua_close(L); + return AVERROR_INVALIDDATA; + } + + nb_configs = lua_tonumber(L, -1); + + lua_close(L); + *configs = parsed_configs; + return nb_configs; +} + diff --git a/configreader.h b/configreader.h new file mode 100644 index 0000000..7842a45 --- /dev/null +++ b/configreader.h @@ -0,0 +1,47 @@ +/* + * 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, a negative AVERROR code on error. + */ +int configs_read(struct HTTPDConfig **configs, const char *filename); + +/** + * Dump a configuration to a stream specified by the user. + * @param config pointer to a configuration + * @param stream output stream to be used to dump the config + */ +void config_dump(struct HTTPDConfig *config, FILE *stream); + +/** + * Free a configuration. + * @param config pointer to a configuration + */ +void config_free(struct HTTPDConfig *config); + +#endif