From eedbafe05e4947b0030399597c4aeb4d898b390c Mon Sep 17 00:00:00 2001
From: Stefano Sabatini <[email protected]>
Date: Sat, 1 Jun 2013 16:43:31 +0200
Subject: [PATCH] lavfi: add lua filter
---
configure | 4 +
libavfilter/Makefile | 1 +
libavfilter/allfilters.c | 1 +
libavfilter/vf_lua.c | 261 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 267 insertions(+)
create mode 100644 libavfilter/vf_lua.c
diff --git a/configure b/configure
index 93970a1..35f3d79 100755
--- a/configure
+++ b/configure
@@ -205,6 +205,7 @@ External library support:
--enable-libgsm enable GSM de/encoding via libgsm [no]
--enable-libiec61883 enable iec61883 via libiec61883 [no]
--enable-libilbc enable iLBC de/encoding via libilbc [no]
+ --enable-liblua enable Lua scripting [no]
--enable-libmodplug enable ModPlug via libmodplug [no]
--enable-libmp3lame enable MP3 encoding via libmp3lame [no]
--enable-libnut enable NUT (de)muxing via libnut,
@@ -1169,6 +1170,7 @@ EXTERNAL_LIBRARY_LIST="
libgsm
libiec61883
libilbc
+ liblua
libmodplug
libmp3lame
libnut
@@ -2154,6 +2156,7 @@ histeq_filter_deps="gpl"
hqdn3d_filter_deps="gpl"
hue_filter_deps="gpl"
interlace_filter_deps="gpl"
+lua_filter_deps="liblua"
kerndeint_filter_deps="gpl"
mcdeint_filter_deps="avcodec gpl"
movie_filter_deps="avcodec avformat"
@@ -4116,6 +4119,7 @@ enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do
check_lib "${gsm_hdr}" gsm_create -lgsm && break;
done || die "ERROR: libgsm not found"; }
enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc
+enabled liblua && require_pkg_config lua5.1 lua.h lua_newstate
enabled libmodplug && require libmodplug libmodplug/modplug.h ModPlug_Load -lmodplug
enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
enabled libnut && require libnut libnut.h nut_demuxer_init -lnut
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 2d2ea45..fdb5ce8 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -148,6 +148,7 @@ OBJS-$(CONFIG_IL_FILTER) += vf_il.o
OBJS-$(CONFIG_INTERLACE_FILTER) += vf_interlace.o
OBJS-$(CONFIG_INTERLEAVE_FILTER) += f_interleave.o
OBJS-$(CONFIG_KERNDEINT_FILTER) += vf_kerndeint.o
+OBJS-$(CONFIG_LUA_FILTER) += vf_lua.o
OBJS-$(CONFIG_LUT3D_FILTER) += vf_lut3d.o
OBJS-$(CONFIG_LUT_FILTER) += vf_lut.o
OBJS-$(CONFIG_LUTRGB_FILTER) += vf_lut.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index f9d9391..10a1fb0 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -144,6 +144,7 @@ void avfilter_register_all(void)
REGISTER_FILTER(INTERLACE, interlace, vf);
REGISTER_FILTER(INTERLEAVE, interleave, vf);
REGISTER_FILTER(KERNDEINT, kerndeint, vf);
+ REGISTER_FILTER(LUA, lua, vf);
REGISTER_FILTER(LUT3D, lut3d, vf);
REGISTER_FILTER(LUT, lut, vf);
REGISTER_FILTER(LUTRGB, lutrgb, vf);
diff --git a/libavfilter/vf_lua.c b/libavfilter/vf_lua.c
new file mode 100644
index 0000000..e9106d4
--- /dev/null
+++ b/libavfilter/vf_lua.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2013 Stefano Sabatini
+ *
+ * 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
+ */
+
+/**
+ * @file
+ * lua scripting filter
+ */
+
+#include "libavutil/opt.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+
+typedef struct {
+ const AVClass *class;
+ lua_State *state;
+ char *filename;
+} LuaContext;
+
+#define OFFSET(x) offsetof(LuaContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+
+static const AVOption lua_options[] = {
+ { "file", "set lua script file", OFFSET(filename), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS },
+ { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(lua);
+
+static int l_sin(lua_State *l)
+{
+ double d = lua_tonumber(l, 1); /* get argument from stack */
+ lua_pushnumber(l, sin(d)); /* push result to the stack */
+ return 1; /* number of results */
+}
+
+static int l_cos(lua_State *l)
+{
+ double d = lua_tonumber(l, 1); /* get argument from stack */
+ lua_pushnumber(l, cos(d)); /* push result to the stack */
+ return 1; /* number of results */
+}
+
+/* static int l_send_command(lua_State *l) */
+/* { */
+/* char buf[128]; */
+/* char *target = lua_tostring(l, 1); */
+/* char *command = lua_tostring(l, 2); */
+/* char *arg = lua_tostring(l, 3); */
+/* int ret; */
+
+/* ret = avfilter_graph_send_command(inlink->graph, */
+/* target, command, arg, buf, sizeof(buf), */
+/* AVFILTER_CMD_FLAG_ONE); */
+/* lua_pushnumber(l, ret); */
+/* return 1; */
+/* } */
+
+static const struct luaL_reg lavfi[] = {
+ { "sin", l_sin},
+ { "cos", l_cos},
+// { "send_command", l_send_command },
+ { NULL, NULL }
+};
+
+static int l_open_lavfi(lua_State *l)
+{
+ luaL_openlib(l, "lavfi", lavfi, 0);
+ return 1;
+}
+
+static av_cold int init(AVFilterContext *ctx)
+{
+ LuaContext *lua = ctx->priv;
+
+ lua->state = luaL_newstate();
+ luaL_openlibs(lua->state);
+
+ /* register l_sin function */
+ /* lua_pushcfunction(lua->state, l_sin); */
+ /* lua_setglobal(lua->state, "l_sin"); */
+ /* lua_pushcfunction(lua->state, l_send_command); */
+ /* lua_setglobal(lua->state, "l_send_command"); */
+
+ if (!lua->filename) {
+ av_log(ctx, AV_LOG_ERROR, "No script specified, aborting\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (luaL_loadfile(lua->state, lua->filename) != 0) {
+ av_log(ctx, AV_LOG_ERROR, "Could not load lua script '%s': %s\n",
+ lua->filename, lua_tostring(lua->state, -1));
+ return AVERROR_EXTERNAL;
+ }
+
+ if (lua_pcall(lua->state, 0, 0, 0) != 0) {
+ av_log(ctx, AV_LOG_ERROR, "Could not call function: %s\n",
+ lua_tostring(lua->state, -1));
+ return AVERROR_EXTERNAL;
+ }
+
+ /* call a function `f' defined in Lua */
+ /* double f (double x, double y) { */
+
+ /* load function and push it on the stack */
+ lua_getglobal(lua->state, "init");
+
+ /* pass arguments to init */
+ /* lua_pushnumber(L, x); /\* push 1st argument *\/ */
+ /* lua_pushnumber(L, y); /\* push 2nd argument *\/ */
+
+ /* call init function, 0 arguments, 1 result */
+ if (lua_pcall(lua->state, 0, 1, 0) != 0)
+ av_log(ctx, AV_LOG_ERROR, "Error running init function: %s",
+ lua_tostring(lua->state, -1));
+
+ /* retrieve result */
+ /* if (!lua_isnumber(L, -1)) */
+ /* error(L, "function `f' must return a number"); */
+ /* z = lua_tonumber(L, -1); */
+ /* lua_pop(L, 1); /\* pop returned value *\/ */
+ /* return z; */
+ /* } */
+
+ /* lua_getglobal(lua->state, "result"); */
+ /* av_log(ctx, AV_LOG_INFO, "result is: %f\n", lua_tonumber(lua->state, -1)); */
+ return 0;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+ LuaContext *lua = ctx->priv;
+
+ if (lua->state)
+ lua_close(lua->state);
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
+{
+ AVFilterContext *ctx = inlink->dst;
+ LuaContext *lua = ctx->priv;
+ AVFilterLink *outlink = ctx->outputs[0];
+ int ret;
+
+ /* load function and push it on the stack */
+ lua_getglobal(lua->state, "filter_frame");
+
+ /* TODO: pass arguments to function, in particular inlink and frame */
+ if (lua_pcall(lua->state, 0, 1, 0) != 0)
+ av_log(ctx, AV_LOG_ERROR, "Error running filter_frame function: %s",
+ lua_tostring(lua->state, -1));
+ ret = lua_tointeger(lua->state, -1);
+ if (ret < 0)
+ return ret;
+
+ return ff_filter_frame(outlink, frame);
+}
+
+static const AVFilterPad lua_inputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .filter_frame = filter_frame,
+ },
+ { NULL }
+};
+
+static const AVFilterPad lua_outputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ },
+ { NULL }
+};
+
+AVFilter avfilter_vf_lua = {
+ .name = "lua",
+ .descripti lua script."),
+ .priv_size = sizeof(LuaContext),
+ .priv_class = &lua;_class,
+ .init = init,
+ .uninit = uninit,
+ .inputs = lua_inputs,
+ .outputs = lua_outputs,
+};
+
+
+/* /\* Variable arg function callable from a Lua script as: */
+/* * say_something('A', 'gaggle', 'of', 5, 'args') */
+/* *\/ */
+/* static int */
+/* say_something(lua_State* luaVM) { */
+/* int n = lua_gettop(luaVM); */
+/* int i; */
+
+/* if (n == 0) { */
+/* printf("no arguments"); */
+/* return 0; */
+/* } */
+
+/* for (i = 1; i <= n; i++) { */
+/* if (!lua_isstring(luaVM, i)) { */
+/* lua_pushstring(luaVM, "[ERROR] argument must be a string or a number"); */
+/* lua_error(luaVM); */
+/* } */
+/* printf("%s\n", lua_tostring(luaVM, i)); */
+/* } */
+
+/* return 0; */
+/* } */
+
+/* int */
+/* main(int argc, char** argv) { */
+/* if (!check_args(argc, argv)) return(EXIT_FAILURE); */
+
+/* /\* Initialize Lua *\/ */
+/* lua_State* luaVM = luaL_newstate(); */
+/* if (luaVM == NULL) { */
+/* err_message("Cannot initialize Lua; exiting..."); */
+/* return EXIT_FAILURE; */
+/* } */
+
+/* /\* Stop the GC during Lua library (all std) initialization and function */
+/* * registrations. C functions that are callable from a Lua script must be */
+/* * registered with Lua. */
+/* *\/ */
+/* lua_gc(luaVM, LUA_GCSTOP, 0); */
+/* luaL_openlibs(luaVM); */
+/* lua_register(luaVM, "say_something", say_something); */
+/* lua_gc(luaVM, LUA_GCRESTART, 0); */
+
+/* /\* Execute the Lua script *\/ */
+/* if (luaL_dofile(luaVM, argv[1])) err_message("Problem running script."); */
+
+/* /\* Lua cleanup *\/ */
+/* lua_close(luaVM); */
+
+/* return EXIT_SUCCESS; */
+/* } */
--
1.8.1.2
Add a code snippet to your website: www.paste.org