OSDN Git Service

Merge remote branch 'official/master'
authoryukihane <yukihane.feather@gmail.com>
Mon, 12 Sep 2011 10:44:41 +0000 (19:44 +0900)
committeryukihane <yukihane.feather@gmail.com>
Mon, 12 Sep 2011 10:44:41 +0000 (19:44 +0900)
Conflicts:
ffmpeg.c

ffmpeg.c
libavfilter/Makefile
libavfilter/allfilters.c
libavfilter/avtool.c [new file with mode: 0644]
libavfilter/avtool.h [new file with mode: 0644]
libavfilter/common/framehook_ext.h [new file with mode: 0644]
libavfilter/vf_expand.c [new file with mode: 0644]
libavfilter/vf_vhext.c [new file with mode: 0644]

index fa7a394..9e578ab 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -54,6 +54,7 @@
 # include "libavfilter/avfiltergraph.h"
 # include "libavfilter/buffersink.h"
 # include "libavfilter/vsrc_buffer.h"
+# include "libavfilter/avtool.h"
 #endif
 
 #if HAVE_SYS_RESOURCE_H
@@ -2193,6 +2194,7 @@ static int transcode_init(OutputFile *output_files,
                 }
 
 #if CONFIG_AVFILTER
+                tool_registerInfo(is, recording_time);
                 if (configure_video_filters(ist, ost)) {
                     fprintf(stderr, "Error opening filters!\n");
                     exit(1);
@@ -4268,7 +4270,8 @@ static const OptionDef options[] = {
     { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
     { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" },
 #if CONFIG_AVFILTER
-    { "vf", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_filters}, "video filters", "filter list" },
+// さきゅばすインタフェース互換性維持のため処置 引数を新しいvfでなく古いvfiltersのままとする
+    { "vfilters", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_filters}, "video filters", "filter list" },
 #endif
     { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(intra_matrices)}, "specify intra matrix coeffs", "matrix" },
     { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(inter_matrices)}, "specify inter matrix coeffs", "matrix" },
index 840d53c..7e6d25a 100644 (file)
@@ -141,6 +141,9 @@ OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_yuvcsp.o
 OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_yvu9.o
 OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/pullup.o
 
+OBJS-$(CONFIG_VHEXT_FILTER)                  += avtool.o
+OBJS-$(CONFIG_VHEXT_FILTER)                  += vf_vhext.o
+
 
 -include $(SRC_PATH)/$(SUBDIR)$(ARCH)/Makefile
 
index bff2371..c148eda 100644 (file)
@@ -98,4 +98,6 @@ void avfilter_register_all(void)
 
     REGISTER_FILTER (BUFFERSINK,  buffersink,  vsink);
     REGISTER_FILTER (NULLSINK,    nullsink,    vsink);
+
+    REGISTER_FILTER (VHEXT,       vhext,       vf);
 }
diff --git a/libavfilter/avtool.c b/libavfilter/avtool.c
new file mode 100644 (file)
index 0000000..b4be0b7
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * avtool
+ * copyright (c) 2008 ψ(プサイ)
+ *
+ * さきゅばす用に拡張されたVhookライブラリから
+ * 使われるライブラリです。
+ *
+ * このファイルは「さきゅばす」の一部であり、
+ * このソースコードはGPLライセンスで配布されますです。
+ */
+#include <stdio.h>
+#include "common/framehook_ext.h"
+#include "avtool.h"
+
+static toolbox Box = {
+       .version = TOOLBOX_VERSION,
+       .video_length = 0.0f
+};
+
+/* こちらはffmpeg側から呼ばれる関数 */
+
+int tool_registerInfo(AVFormatContext *in_file,int64_t rec_time){
+       if(in_file->duration > rec_time && rec_time > 0){
+               Box.video_length = ((double)rec_time) / AV_TIME_BASE;
+       }
+       Box.video_length = ((double)in_file->duration)/AV_TIME_BASE;
+       return 0;
+}
+
+const toolbox* tool_getToolBox(){
+       return &Box;
+}
diff --git a/libavfilter/avtool.h b/libavfilter/avtool.h
new file mode 100644 (file)
index 0000000..b54a620
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * avtool
+ * copyright (c) 2008 ψ(プサイ)
+ *
+ * さきゅばす用に拡張されたFFmpegから
+ * 使われるライブラリです。
+ *
+ * このファイルは「さきゅばす」の一部であり、
+ * このソースコードはGPLライセンスで配布されますです。
+ */
+#ifndef SACCUBUS_AVINFO_H
+#define SACCUBUS_AVINFO_H
+#include "common/framehook_ext.h"
+#include <libavformat/avformat.h>
+
+int tool_registerInfo(AVFormatContext *in_file,int64_t rec_time);
+const toolbox* tool_getToolBox(void);
+
+#endif /* SACCUBUS_AVINFO_H */
diff --git a/libavfilter/common/framehook_ext.h b/libavfilter/common/framehook_ext.h
new file mode 100644 (file)
index 0000000..e1ea56d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 拡張Vhookフィルタ
+ * copyright (c) 2008 ψ(プサイ)
+ *
+ * さきゅばす用に拡張されたVhookライブラリを
+ * ビルドするためのヘッダです。
+ *
+ * このファイルは「さきゅばす」の一部であり、
+ * このソースコードはGPLライセンスで配布されますです。
+ */
+#ifndef SACCUBUS_VF_VHEXT_H
+#define SACCUBUS_VF_VHEXT_H
+/*
+ * ツールボックスのバージョン
+ * DLLの中で確認しといた方がいい。
+ */
+#define TOOLBOX_VERSION 2
+
+/*
+ * 呼ばれるときに一緒についてくるtoolbox.
+ * ここから動画の情報なんかも取得できる。
+ */
+typedef struct toolbox{
+       //バージョン
+       int version;
+       double video_length;
+} toolbox;
+
+typedef struct vhext_frame{
+       void *data;
+       int linesize;
+       int w;
+       int h;
+       double pts;
+} vhext_frame;
+
+
+/*
+ * 拡張vhookライブラリ用関数群定義
+ */
+
+//configure用
+typedef int (FrameHookExtConfigure)(void **ctxp,const toolbox *tbox, int argc, char *argv[]);
+typedef FrameHookExtConfigure *FrameHookExtConfigureFn;
+extern FrameHookExtConfigure ExtConfigure;
+
+//フレーム用
+typedef void (FrameHookExtProcess)(void *ctx,const toolbox *tbox,vhext_frame *pict);
+typedef FrameHookExtProcess *FrameHookExtProcessFn;
+extern FrameHookExtProcess ExtProcess;
+
+//終了時に呼ぶ
+typedef void (FrameHookExtRelease)(void *ctx,const toolbox *tbox);
+typedef FrameHookExtRelease *FrameHookExtReleaseFn;
+extern FrameHookExtRelease ExtRelease;
+
+#endif /* SACCUBUS_VF_VHEXT_H */
diff --git a/libavfilter/vf_expand.c b/libavfilter/vf_expand.c
new file mode 100644 (file)
index 0000000..5026a8c
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * video expand filter (alternative to pad syntax)
+ * copyright (c) 2008 Ryo Hirafuji <http://ledyba.ddo.jp/>
+ *
+ * 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 <stdio.h>
+
+#include "avfilter.h"
+#define INDEX_X 0
+#define INDEX_Y 1
+#define INDEX_MAX 2
+
+typedef struct{
+       int size[INDEX_MAX];
+       int offset[INDEX_MAX];
+    int shift[INDEX_MAX];
+
+    int osd; ///< checked, but not used in this version.
+    double aspect;
+    int round;
+
+    int bpp;                ///< bytes per pixel
+    int is_yuv;
+} ExpandContext;
+
+static int init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+    ExpandContext *expand = ctx->priv;
+    int i;
+
+    /* default parameters */
+       for(i=0;i<INDEX_MAX;i++){
+           expand->offset[i] =  -1;
+           expand->size[i] = -1;
+           expand->shift[i] = 0;
+       }
+    expand->osd = 0;
+    expand->aspect = 0.0f;
+    expand->round = 0;
+
+    expand->bpp = 0;
+    expand->is_yuv = 0;
+
+    if(args){
+        int length = strlen(args);
+        char* osd_tmp = av_malloc(length);
+        char* aspect_tmp = av_malloc(length);
+        if(!osd_tmp || !aspect_tmp){
+               av_log(ctx, AV_LOG_ERROR, "Failed to malloc.\n");
+        }
+
+        sscanf(args,"%d:%d:%d:%d:%255[^:]:%255[^:]:%d",
+            &expand->size[INDEX_X],&expand->size[INDEX_Y],&expand->offset[INDEX_X],&expand->offset[INDEX_Y],
+            osd_tmp,aspect_tmp,&expand->round
+        );
+
+        if(osd_tmp && strlen(osd_tmp) > 0){ //checked, but not used in this version.
+            if(!strncmp(osd_tmp,"true",4)){
+                expand->osd = 1;
+            }else{
+                expand->osd = atoi(osd_tmp);
+            }
+        }
+
+        if(aspect_tmp && strlen(aspect_tmp) > 0){
+            char* cp = strchr(aspect_tmp, '/');
+            if(cp){ // rational
+                AVRational rat;
+                char* cpp;
+                rat.num = strtol(aspect_tmp, &cpp, 10);
+                if(cpp != aspect_tmp || cpp == cp){
+                    rat.den = strtol(cp+1, &cpp, 10);
+                }else{
+                    rat.num = 0;
+                }
+                if(rat.num && rat.den){
+                    double eval = ((double)rat.num) / rat.den;
+                    if(eval > 0.0f){
+                        expand->aspect = eval;
+                    }
+                }
+            }else{ // double
+                double eval = strtod(aspect_tmp, 0);
+                if(eval > 0.0f){
+                    expand->aspect = eval;
+                }
+            }
+        }
+
+        av_log(ctx, AV_LOG_INFO, "Expand: %dx%d , (%d,%d) , osd: %d, aspect: %lf, round: %d\n",
+        expand->size[INDEX_X], expand->size[INDEX_Y], expand->offset[INDEX_X], expand->offset[INDEX_Y], expand->osd, expand->aspect, expand->round);
+
+        av_free(osd_tmp);
+        av_free(aspect_tmp);
+    }
+
+    return 0;
+}
+
+static int query_formats(AVFilterContext *ctx){
+    avfilter_set_common_formats(ctx,avfilter_make_format_list(30, // out of 38
+         PIX_FMT_YUV420P,
+         PIX_FMT_YUV422P,
+         PIX_FMT_YUV444P,
+         PIX_FMT_YUV410P,
+         PIX_FMT_YUV411P,
+         PIX_FMT_YUV440P,
+         PIX_FMT_YUVJ420P,
+         PIX_FMT_YUVJ422P,
+         PIX_FMT_YUVJ444P,
+         PIX_FMT_YUVJ440P,
+         PIX_FMT_YUVA420P,
+         PIX_FMT_NV12,
+         PIX_FMT_NV21,
+         PIX_FMT_RGB24,
+         PIX_FMT_BGR24,
+         PIX_FMT_RGB32,
+         PIX_FMT_BGR32,
+         PIX_FMT_RGB32_1,
+         PIX_FMT_BGR32_1,
+         PIX_FMT_GRAY16BE,
+         PIX_FMT_GRAY16LE,
+         PIX_FMT_BGR555,
+         PIX_FMT_BGR565,
+         PIX_FMT_RGB555,
+         PIX_FMT_RGB565,
+         //PIX_FMT_YUYV422, // not supported.
+         //PIX_FMT_UYVY422, // not supported.
+         //PIX_FMT_UYYVYY411, // not supported.
+         PIX_FMT_RGB8,
+         PIX_FMT_BGR8,
+         PIX_FMT_RGB4_BYTE,
+         PIX_FMT_BGR4_BYTE,
+         PIX_FMT_GRAY8
+         //PIX_FMT_RGB4, //not supported
+         //PIX_FMT_BGR4, //not supported
+         //PIX_FMT_MONOWHITE, // not supported
+         //PIX_FMT_MONOBLACK, // not supported
+         //PIX_FMT_PAL8, // not supported
+    ));
+    return 0;
+}
+
+
+static int config_input(AVFilterLink *link)
+{
+    ExpandContext *expand = link->dst->priv;
+    int i;
+    int size[INDEX_MAX];
+
+    size[INDEX_X] = link->w;
+    size[INDEX_Y] = link->h;
+
+       for(i=0;i<INDEX_MAX;i++){
+           if (expand->size[i] == -1){
+               expand->size[i]=size[i];
+           } else if (expand->size[i] < -1){
+               expand->size[i]=size[i] - expand->size[i];
+           } else if (expand->size[INDEX_X] < size[i]){
+               expand->size[i]=size[i];
+           }
+       }
+
+    if (expand->aspect > 0.0f) {
+        if (expand->size[INDEX_Y] < (expand->size[INDEX_X] / expand->aspect)) {
+            expand->size[INDEX_Y] = (expand->size[INDEX_X] / expand->aspect) + 0.5;
+        } else {
+            expand->size[INDEX_X] = (expand->size[INDEX_Y] * expand->aspect) + 0.5;
+        }
+    }
+
+       for(i=0;i<INDEX_MAX;i++){
+           if (expand->round > 1) {
+               expand->size[i] = (1+(expand->size[i]-1)/expand->round)*expand->round;
+           }
+           if(expand->offset[i] < 0 || (expand->offset[i]+size[i]) > expand->size[i]){
+               expand->offset[i] = (expand->size[INDEX_X] - size[i])>>1;
+           }
+       }
+
+    avcodec_get_chroma_sub_sample(link->format, &expand->shift[INDEX_X], &expand->shift[INDEX_Y]);
+    for(i=0;i<INDEX_MAX;i++){
+           expand->offset[i] &= ~((1 << expand->shift[i]) - 1);
+           expand->size[i] &= ~((1 << expand->shift[i]) - 1);
+    }
+
+    switch(link->format) {
+        case PIX_FMT_YUV420P:
+        case PIX_FMT_YUV422P:
+        case PIX_FMT_YUV444P:
+        case PIX_FMT_YUV410P:
+        case PIX_FMT_YUV411P:
+        case PIX_FMT_YUV440P:
+        case PIX_FMT_YUVJ420P:
+        case PIX_FMT_YUVJ422P:
+        case PIX_FMT_YUVJ444P:
+        case PIX_FMT_YUVJ440P:
+        case PIX_FMT_YUVA420P:
+        case PIX_FMT_NV12:
+        case PIX_FMT_NV21:
+            expand->is_yuv = 1;
+        case PIX_FMT_RGB8:
+        case PIX_FMT_BGR8:
+        case PIX_FMT_RGB4_BYTE:
+        case PIX_FMT_BGR4_BYTE:
+        case PIX_FMT_GRAY8:
+            expand->bpp = 1;
+            break;
+        case PIX_FMT_RGB24:
+        case PIX_FMT_BGR24:
+            expand->bpp = 3;
+            break;
+        case PIX_FMT_RGB32:
+        case PIX_FMT_BGR32:
+        case PIX_FMT_RGB32_1:
+        case PIX_FMT_BGR32_1:
+            expand->bpp = 4;
+            break;
+        case PIX_FMT_GRAY16BE:
+        case PIX_FMT_GRAY16LE:
+        case PIX_FMT_BGR555:
+        case PIX_FMT_BGR565:
+        case PIX_FMT_RGB555:
+        case PIX_FMT_RGB565:
+            expand->bpp = 2;
+            break;
+        // not supported.
+        //case PIX_FMT_YUYV422:
+        //case PIX_FMT_UYVY422:
+        //case PIX_FMT_UYYVYY411:
+        //case PIX_FMT_RGB4:
+        //case PIX_FMT_BGR4:
+        //case PIX_FMT_MONOWHITE:
+        //case PIX_FMT_MONOBLACK:
+        //case PIX_FMT_PAL8:
+        default: // invalid or not supported format
+            return -1;
+    }
+
+    return 0;
+}
+
+static int config_output(AVFilterLink *link)
+{
+    ExpandContext *expand = link->src->priv;
+
+    link->w = expand->size[INDEX_X];
+    link->h = expand->size[INDEX_Y];
+
+    return 0;
+}
+
+static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
+{
+    AVFilterLink *out = link->dst->outputs[0];
+    out->outpic       = avfilter_get_video_buffer(out, AV_PERM_WRITE);
+    out->outpic->pts  = picref->pts;
+    avfilter_start_frame(out, avfilter_ref_pic(out->outpic, ~0));
+}
+
+static void draw_slice(AVFilterLink *link, int y, int h)
+{
+    ExpandContext *expand = link->dst->priv;
+    AVFilterPicRef *outpic = link->dst->outputs[0]->outpic;
+    AVFilterPicRef *inpic = link->cur_pic;
+    int i;
+    int is_first = (y <= 0);
+    int is_end = (y+h >= inpic->h);
+
+    for(i=0;i<4;i++) {
+        if(outpic->data[i]) {
+            int j;
+            char* out_buff = outpic->data[i];
+            const char* in_buff  = inpic->data[i];
+
+            int copy_length;
+            int y_add;
+            int padcolor;
+            int x_shift,y_shift;
+
+            if(!expand->is_yuv || i == 3){ // not YUV, or alpha channel of YUVA
+                padcolor = 0;
+                x_shift = y_shift = 0;
+            }else{
+                padcolor = (i == 0) ? 16 : 128;
+                x_shift = (i == 0) ? 0 : expand->shift[INDEX_X];
+                y_shift = (i == 0) ? 0 : expand->shift[INDEX_Y];
+            }
+
+            copy_length = (inpic->w >> x_shift) * expand->bpp;
+            y_add = 1<<y_shift;
+
+            if(is_first){
+                int size = (expand->offset[INDEX_Y] >> y_shift) * outpic->linesize[i];
+                memset(out_buff,padcolor,size);
+                out_buff += size;
+            }else{
+                int y_skip = expand->offset[INDEX_Y] >> y_shift;
+                out_buff += outpic->linesize[i] * y_skip;
+                in_buff += inpic->linesize[i] * y_skip;
+            }
+
+            for(j=0;j<h;j+=y_add){
+                int size,total_size = 0;
+                size = (expand->offset[INDEX_X] >> x_shift) * expand->bpp;
+                memset(out_buff,padcolor,size);
+                out_buff += size;
+                total_size += size;
+
+                memcpy(out_buff,in_buff,copy_length);
+                out_buff += copy_length;
+                total_size += copy_length;
+
+                size = outpic->linesize[i]-total_size;
+                memset(out_buff,padcolor,size);
+                out_buff += size;
+
+                in_buff += inpic->linesize[i];
+            }
+
+            if(is_end){
+                memset(out_buff,padcolor,((outpic->h-expand->offset[INDEX_Y]-inpic->h) >> y_shift) * outpic->linesize[i]);
+            }
+
+        }
+    }
+    if(is_first && is_end){
+        avfilter_draw_slice(link->dst->outputs[0], 0, outpic->h);
+    }else if(is_first){
+        avfilter_draw_slice(link->dst->outputs[0], 0, expand->offset[INDEX_Y] + h);
+    }else if(is_end){
+        avfilter_draw_slice(link->dst->outputs[0], expand->offset[INDEX_Y] + y, outpic->h - expand->offset[INDEX_Y] - y);
+    }else{
+        avfilter_draw_slice(link->dst->outputs[0], expand->offset[INDEX_Y] + y, h);
+    }
+}
+
+AVFilter avfilter_vf_expand = {
+    .name      = "expand",
+    .priv_size = sizeof(ExpandContext),
+
+    .init      = init,
+    .query_formats   = query_formats,
+
+    .inputs    = (AVFilterPad[]) {{ .name            = "default",
+                                    .type            = CODEC_TYPE_VIDEO,
+                                    .start_frame     = start_frame,
+                                    .draw_slice      = draw_slice,
+                                    .config_props    = config_input, },
+                                  { .name = NULL}},
+    .outputs   = (AVFilterPad[]) {{ .name            = "default",
+                                    .type            = CODEC_TYPE_VIDEO,
+                                    .config_props    = config_output, },
+                                  { .name = NULL}},
+};
+
diff --git a/libavfilter/vf_vhext.c b/libavfilter/vf_vhext.c
new file mode 100644 (file)
index 0000000..bf7aa2d
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * 拡張Vhookフィルタ
+ * copyright (c) 2008 ψ(プサイ)
+ *
+ * さきゅばす用に拡張されたVhookライブラリを
+ * 駆動させるためのフィルタです。
+ *
+ * このファイルは「さきゅばす」の一部であり、
+ * このソースコードはGPLライセンスで配布されますです。
+ */
+#include "avfilter.h"
+#include "common/framehook_ext.h"
+#include "avtool.h"
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#else
+//dlfcn.hの無いWindows Mingw環境用
+#define dlopen(a) ((void*)LoadLibrary(a))
+#define dlsym(a,b) ((void*)GetProcAddress((HMODULE)(a),(b)))
+#define dlclose(a) FreeLibrary((HMODULE)(a));
+#endif
+
+//デリミタ。MEncoder側とは同じにしといた方がよさそう。
+#define VHEXT_DELIM '|'
+
+typedef struct{
+       //引数はあとあと使うので確保。
+       char* args;
+       char** argv;
+       int argc;
+       //ツールボックス
+       const toolbox* Box;
+       //ダイナミックライブラリへのポインタ
+       void* Dynamic;
+       //関数へのポインタ
+       FrameHookExtConfigureFn ExtConfigure;
+       FrameHookExtProcessFn ExtProcess;
+       FrameHookExtReleaseFn ExtRelease;
+       //FrameHookの使うポインタ
+       void* Context;
+} Context;
+
+/*
+ * この中でだけ使う関数定義
+ */
+
+char** split(char* str,int str_len,int* argc,char delim);
+int decode(char* s,int len);
+
+/*
+ *  AVFilter構造体に格納される関数群
+ */
+
+static int init(AVFilterContext *ctx, const char *args, void *opaque){
+       //Contextをとりあえず確保
+    Context *context= ctx->priv;
+    av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]called with args = %s.\n",args);
+
+       //引数がNULLなのはおかしい
+    if(!args) {
+        av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Invalid arguments.\n");
+        return -1;
+    }
+    int arg_len = strlen(args);
+    //引数のコピー
+    context->args = (char*)av_malloc(arg_len+1);
+    if(!context->args){
+        av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to malloc memory for args.\n");
+        return -1;
+    }
+    memcpy(context->args,args,arg_len);
+    context->args[arg_len]='\0';//NULLで最後を埋める。
+
+       //デコード
+       decode(context->args,arg_len);
+       //引数の展開
+       context->argv = split(context->args,arg_len,&context->argc,VHEXT_DELIM);
+       if(!context->argv){
+            av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to split args.\n");
+            return -1;
+       }
+
+       //ツールボックスを取得
+       context->Box = tool_getToolBox();
+       if(!context->Box){
+            av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ToolBox.\n");
+            return -1;
+       }
+
+       //DLL読み込み
+    context->Dynamic = dlopen(context->argv[0], RTLD_NOW);
+    if (!context->Dynamic) {
+        av_log(NULL, AV_LOG_ERROR, "[libavfilter/VhookExt Filter][Lib:%s]Failed to open lib: %s\nMSG:%s\n",context->argv[0],context->argv[0], dlerror());
+        return -1;
+    }
+       //各関数を取得
+       context->ExtConfigure = dlsym(context->Dynamic, "ExtConfigure");
+       context->ExtProcess = dlsym(context->Dynamic, "ExtProcess");
+       context->ExtRelease = dlsym(context->Dynamic, "ExtRelease");
+       if(!context->ExtConfigure){
+        av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ExtConfigure.\n");
+        return -1;
+       }
+       if(!context->ExtProcess){
+        av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ExtProcess.\n");
+        return -1;
+       }
+       if(!context->ExtRelease){
+        av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ExtRelease.\n");
+        return -1;
+       }
+
+       //Configureを呼び出す
+       int code;
+       if((code = context->ExtConfigure(&context->Context,context->Box,context->argc,context->argv))){
+        av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to configure.Code:%d\n",code);
+        return -1;
+       }
+    return 0;
+}
+
+static void uninit(AVFilterContext *ctx){
+    //Contextをとりあえず確保
+    Context *context= ctx->priv;
+    //開放する。
+    context->ExtRelease(context->Context,context->Box);
+    //引数も開放する。
+    if(!context->args){
+        av_free(context->args);
+    }
+    if(!context->argv){
+        av_free(context->argv);
+    }
+    //DLLも閉じる
+    dlclose(context->Dynamic);
+}
+
+static int query_formats(AVFilterContext *ctx){
+       //SDLで使いやすくするためにRGB24フォーマットを要求する。
+    enum PixelFormat pix_fmts[] = { PIX_FMT_RGB24, PIX_FMT_NONE };
+    avfilter_set_common_pixel_formats(ctx,avfilter_make_format_list(pix_fmts));
+    return 0;
+}
+
+/*
+ * AVFilterPadのInput側に呼ばれる関数
+ */
+
+static void start_frame(AVFilterLink *link, AVFilterBufferRef *bufref){
+       //おまじない
+    avfilter_start_frame(link->dst->outputs[0], bufref);
+}
+
+static void end_frame(AVFilterLink *link){
+       //ポインタは基本
+    Context *context = link->dst->priv;
+    //よくわからないけどとりあえずおまじない(えー
+    AVFilterLink* output = link->dst->outputs[0];
+    AVFilterBufferRef *buf = link->cur_buf;
+    //独自構造体に代入
+    vhext_frame frame;
+    frame.data = buf->data[0];
+    frame.linesize = buf->linesize[0];
+    frame.w = buf->video->w;
+    frame.h = buf->video->h;
+    frame.pts = ((double)buf->pts) / AV_TIME_BASE;
+       //ライブラリを呼び出す。
+       context->ExtProcess(context->Context,context->Box,&frame);
+
+    //おなじくおなじまい(えええ
+    avfilter_draw_slice(output, 0, buf->video->h, 1);
+    avfilter_end_frame(output);
+}
+
+AVFilter avfilter_vf_vhext=
+{
+    .name      = "vhext",
+
+    .priv_size = sizeof(Context),
+
+    .init      = init,
+    .uninit    = uninit,
+
+    .query_formats   = query_formats,
+    .inputs    = (AVFilterPad[]) {{ .name            = "default",
+                                    .type            = AVMEDIA_TYPE_VIDEO,
+                                    .start_frame     = start_frame,
+                                    .end_frame       = end_frame,
+                                    .min_perms       = AV_PERM_WRITE |
+                                                       AV_PERM_READ,
+                                    .rej_perms       = AV_PERM_REUSE |
+                                                       AV_PERM_REUSE2},
+                                  { .name = NULL}},
+    .outputs   = (AVFilterPad[]) {{ .name            = "default",
+                                    .type            = AVMEDIA_TYPE_VIDEO, },
+                                  { .name = NULL}},
+};
+
+/*
+ * この中でのみ使われる関数
+ */
+
+//文字列を特定の文字によって分けます。
+char** split(char* str,int str_len,int* argc,char delim){
+       //チェック
+       if(!str || delim=='\0' || str_len < 0){
+               return 0;
+       }
+       //確保
+       char** argv = av_malloc(sizeof(char*));
+       if(!argv){
+               return 0;
+       }
+       //ループ開始
+       int last = 0;
+       int i;
+       int arg_cnt = 0;
+       for(i=0;i<str_len;i++){
+               if(str[i] == delim){//デリミタに達した
+                       str[i] = '\0';
+                       argv[arg_cnt] = &str[last];
+                       arg_cnt++;
+                       last = i+1;
+                       argv = av_realloc(argv,sizeof(char*) * (arg_cnt+1));
+               }
+       }
+       argv[arg_cnt] = &str[last];
+       *argc = arg_cnt + 1;
+       return argv;
+}
+
+//URエンコード記法が使えます。
+int decode(char* s,int len){
+        int i,j;
+        char buf,*s1;
+        if(len==0)return(-1);
+        s1=(char*)av_malloc(len);
+        for(i=0,j=0;i<len;i++,j++)
+        {
+                if(s[i]=='+'){s1[j]=' ';continue;}
+                if(s[i]!='%') {s1[j]=s[i];continue;}
+                buf=((s[++i]>='A') ? s[i]-'A'+10 : s[i]-'0');
+                buf*=16;
+                buf+=((s[++i]>='A') ? s[i]-'A'+10 : s[i]-'0');
+                s1[j]=buf;
+        }
+        for(i=0;i<j;i++) s[i]=s1[i];
+        s[i]='\0';
+        av_free(s1);
+        return(0);
+}
+