• R/O
  • HTTP
  • SSH
  • HTTPS

libav_saccubus: コミット

さきゅばす/いんきゅばす用libav(実験的)


コミットメタ情報

リビジョンa3effb29d9ff2b8982335c895de74d4f91ce0f4d (tree)
日時2011-05-22 20:24:40
作者yukihane <yukihane.feather@gmai...>
コミッターyukihane

ログメッセージ

patch for saccubus

変更サマリ

差分

--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -48,6 +48,7 @@
4848 # include "libavfilter/avfilter.h"
4949 # include "libavfilter/avfiltergraph.h"
5050 # include "libavfilter/vsrc_buffer.h"
51+# include "libavfilter/avtool.h"
5152 #endif
5253
5354 #if HAVE_SYS_RESOURCE_H
@@ -2245,6 +2246,7 @@ static int transcode(AVFormatContext **output_files,
22452246 ist->decoding_needed = 1;
22462247
22472248 #if CONFIG_AVFILTER
2249+ tool_registerInfo(is, recording_time);
22482250 if (configure_video_filters(ist, ost)) {
22492251 fprintf(stderr, "Error opening filters!\n");
22502252 exit(1);
@@ -4346,7 +4348,8 @@ static const OptionDef options[] = {
43464348 { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
43474349 { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" },
43484350 #if CONFIG_AVFILTER
4349- { "vf", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
4351+// さきゅばすインタフェース互換性維持のため処置 引数を新しいvfでなく古いvfiltersのままとする
4352+ { "vfilters", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
43504353 #endif
43514354 { "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
43524355 { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" },
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -64,4 +64,7 @@ OBJS-$(CONFIG_NULLSINK_FILTER) += vsink_nullsink.o
6464
6565 DIRS = x86
6666
67+OBJS-$(CONFIG_VHEXT_FILTER) += avtool.o
68+OBJS-$(CONFIG_VHEXT_FILTER) += vf_vhext.o
69+
6770 include $(SUBDIR)../subdir.mak
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -78,4 +78,6 @@ void avfilter_register_all(void)
7878 REGISTER_FILTER (NULLSRC, nullsrc, vsrc);
7979
8080 REGISTER_FILTER (NULLSINK, nullsink, vsink);
81+
82+ REGISTER_FILTER (VHEXT, vhext, vf);
8183 }
--- /dev/null
+++ b/libavfilter/avtool.c
@@ -0,0 +1,32 @@
1+/*
2+ * avtool
3+ * copyright (c) 2008 ψ(プサイ)
4+ *
5+ * さきゅばす用に拡張されたVhookライブラリから
6+ * 使われるライブラリです。
7+ *
8+ * このファイルは「さきゅばす」の一部であり、
9+ * このソースコードはGPLライセンスで配布されますです。
10+ */
11+#include <stdio.h>
12+#include "common/framehook_ext.h"
13+#include "avtool.h"
14+
15+static toolbox Box = {
16+ .version = TOOLBOX_VERSION,
17+ .video_length = 0.0f
18+};
19+
20+/* こちらはffmpeg側から呼ばれる関数 */
21+
22+int tool_registerInfo(AVFormatContext *in_file,int64_t rec_time){
23+ if(in_file->duration > rec_time && rec_time > 0){
24+ Box.video_length = ((double)rec_time) / AV_TIME_BASE;
25+ }
26+ Box.video_length = ((double)in_file->duration)/AV_TIME_BASE;
27+ return 0;
28+}
29+
30+const toolbox* tool_getToolBox(){
31+ return &Box;
32+}
--- /dev/null
+++ b/libavfilter/avtool.h
@@ -0,0 +1,19 @@
1+/*
2+ * avtool
3+ * copyright (c) 2008 ψ(プサイ)
4+ *
5+ * さきゅばす用に拡張されたFFmpegから
6+ * 使われるライブラリです。
7+ *
8+ * このファイルは「さきゅばす」の一部であり、
9+ * このソースコードはGPLライセンスで配布されますです。
10+ */
11+#ifndef SACCUBUS_AVINFO_H
12+#define SACCUBUS_AVINFO_H
13+#include "common/framehook_ext.h"
14+#include <libavformat/avformat.h>
15+
16+int tool_registerInfo(AVFormatContext *in_file,int64_t rec_time);
17+const toolbox* tool_getToolBox(void);
18+
19+#endif /* SACCUBUS_AVINFO_H */
--- /dev/null
+++ b/libavfilter/common/framehook_ext.h
@@ -0,0 +1,57 @@
1+/*
2+ * 拡張Vhookフィルタ
3+ * copyright (c) 2008 ψ(プサイ)
4+ *
5+ * さきゅばす用に拡張されたVhookライブラリを
6+ * ビルドするためのヘッダです。
7+ *
8+ * このファイルは「さきゅばす」の一部であり、
9+ * このソースコードはGPLライセンスで配布されますです。
10+ */
11+#ifndef SACCUBUS_VF_VHEXT_H
12+#define SACCUBUS_VF_VHEXT_H
13+/*
14+ * ツールボックスのバージョン
15+ * DLLの中で確認しといた方がいい。
16+ */
17+#define TOOLBOX_VERSION 2
18+
19+/*
20+ * 呼ばれるときに一緒についてくるtoolbox.
21+ * ここから動画の情報なんかも取得できる。
22+ */
23+typedef struct toolbox{
24+ //バージョン
25+ int version;
26+ double video_length;
27+} toolbox;
28+
29+typedef struct vhext_frame{
30+ void *data;
31+ int linesize;
32+ int w;
33+ int h;
34+ double pts;
35+} vhext_frame;
36+
37+
38+/*
39+ * 拡張vhookライブラリ用関数群定義
40+ */
41+
42+//configure用
43+typedef int (FrameHookExtConfigure)(void **ctxp,const toolbox *tbox, int argc, char *argv[]);
44+typedef FrameHookExtConfigure *FrameHookExtConfigureFn;
45+extern FrameHookExtConfigure ExtConfigure;
46+
47+//フレーム用
48+typedef void (FrameHookExtProcess)(void *ctx,const toolbox *tbox,vhext_frame *pict);
49+typedef FrameHookExtProcess *FrameHookExtProcessFn;
50+extern FrameHookExtProcess ExtProcess;
51+
52+//終了時に呼ぶ
53+typedef void (FrameHookExtRelease)(void *ctx,const toolbox *tbox);
54+typedef FrameHookExtRelease *FrameHookExtReleaseFn;
55+extern FrameHookExtRelease ExtRelease;
56+
57+#endif /* SACCUBUS_VF_VHEXT_H */
--- /dev/null
+++ b/libavfilter/vf_expand.c
@@ -0,0 +1,372 @@
1+/*
2+ * video expand filter (alternative to pad syntax)
3+ * copyright (c) 2008 Ryo Hirafuji <http://ledyba.ddo.jp/>
4+ *
5+ * This file is part of FFmpeg.
6+ *
7+ * FFmpeg is free software; you can redistribute it and/or
8+ * modify it under the terms of the GNU Lesser General Public
9+ * License as published by the Free Software Foundation; either
10+ * version 2.1 of the License, or (at your option) any later version.
11+ *
12+ * FFmpeg is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+ * Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public
18+ * License along with FFmpeg; if not, write to the Free Software
19+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+ */
21+
22+#include <stdio.h>
23+
24+#include "avfilter.h"
25+#define INDEX_X 0
26+#define INDEX_Y 1
27+#define INDEX_MAX 2
28+
29+typedef struct{
30+ int size[INDEX_MAX];
31+ int offset[INDEX_MAX];
32+ int shift[INDEX_MAX];
33+
34+ int osd; ///< checked, but not used in this version.
35+ double aspect;
36+ int round;
37+
38+ int bpp; ///< bytes per pixel
39+ int is_yuv;
40+} ExpandContext;
41+
42+static int init(AVFilterContext *ctx, const char *args, void *opaque)
43+{
44+ ExpandContext *expand = ctx->priv;
45+ int i;
46+
47+ /* default parameters */
48+ for(i=0;i<INDEX_MAX;i++){
49+ expand->offset[i] = -1;
50+ expand->size[i] = -1;
51+ expand->shift[i] = 0;
52+ }
53+ expand->osd = 0;
54+ expand->aspect = 0.0f;
55+ expand->round = 0;
56+
57+ expand->bpp = 0;
58+ expand->is_yuv = 0;
59+
60+ if(args){
61+ int length = strlen(args);
62+ char* osd_tmp = av_malloc(length);
63+ char* aspect_tmp = av_malloc(length);
64+ if(!osd_tmp || !aspect_tmp){
65+ av_log(ctx, AV_LOG_ERROR, "Failed to malloc.\n");
66+ }
67+
68+ sscanf(args,"%d:%d:%d:%d:%255[^:]:%255[^:]:%d",
69+ &expand->size[INDEX_X],&expand->size[INDEX_Y],&expand->offset[INDEX_X],&expand->offset[INDEX_Y],
70+ osd_tmp,aspect_tmp,&expand->round
71+ );
72+
73+ if(osd_tmp && strlen(osd_tmp) > 0){ //checked, but not used in this version.
74+ if(!strncmp(osd_tmp,"true",4)){
75+ expand->osd = 1;
76+ }else{
77+ expand->osd = atoi(osd_tmp);
78+ }
79+ }
80+
81+ if(aspect_tmp && strlen(aspect_tmp) > 0){
82+ char* cp = strchr(aspect_tmp, '/');
83+ if(cp){ // rational
84+ AVRational rat;
85+ char* cpp;
86+ rat.num = strtol(aspect_tmp, &cpp, 10);
87+ if(cpp != aspect_tmp || cpp == cp){
88+ rat.den = strtol(cp+1, &cpp, 10);
89+ }else{
90+ rat.num = 0;
91+ }
92+ if(rat.num && rat.den){
93+ double eval = ((double)rat.num) / rat.den;
94+ if(eval > 0.0f){
95+ expand->aspect = eval;
96+ }
97+ }
98+ }else{ // double
99+ double eval = strtod(aspect_tmp, 0);
100+ if(eval > 0.0f){
101+ expand->aspect = eval;
102+ }
103+ }
104+ }
105+
106+ av_log(ctx, AV_LOG_INFO, "Expand: %dx%d , (%d,%d) , osd: %d, aspect: %lf, round: %d\n",
107+ expand->size[INDEX_X], expand->size[INDEX_Y], expand->offset[INDEX_X], expand->offset[INDEX_Y], expand->osd, expand->aspect, expand->round);
108+
109+ av_free(osd_tmp);
110+ av_free(aspect_tmp);
111+ }
112+
113+ return 0;
114+}
115+
116+static int query_formats(AVFilterContext *ctx){
117+ avfilter_set_common_formats(ctx,avfilter_make_format_list(30, // out of 38
118+ PIX_FMT_YUV420P,
119+ PIX_FMT_YUV422P,
120+ PIX_FMT_YUV444P,
121+ PIX_FMT_YUV410P,
122+ PIX_FMT_YUV411P,
123+ PIX_FMT_YUV440P,
124+ PIX_FMT_YUVJ420P,
125+ PIX_FMT_YUVJ422P,
126+ PIX_FMT_YUVJ444P,
127+ PIX_FMT_YUVJ440P,
128+ PIX_FMT_YUVA420P,
129+ PIX_FMT_NV12,
130+ PIX_FMT_NV21,
131+ PIX_FMT_RGB24,
132+ PIX_FMT_BGR24,
133+ PIX_FMT_RGB32,
134+ PIX_FMT_BGR32,
135+ PIX_FMT_RGB32_1,
136+ PIX_FMT_BGR32_1,
137+ PIX_FMT_GRAY16BE,
138+ PIX_FMT_GRAY16LE,
139+ PIX_FMT_BGR555,
140+ PIX_FMT_BGR565,
141+ PIX_FMT_RGB555,
142+ PIX_FMT_RGB565,
143+ //PIX_FMT_YUYV422, // not supported.
144+ //PIX_FMT_UYVY422, // not supported.
145+ //PIX_FMT_UYYVYY411, // not supported.
146+ PIX_FMT_RGB8,
147+ PIX_FMT_BGR8,
148+ PIX_FMT_RGB4_BYTE,
149+ PIX_FMT_BGR4_BYTE,
150+ PIX_FMT_GRAY8
151+ //PIX_FMT_RGB4, //not supported
152+ //PIX_FMT_BGR4, //not supported
153+ //PIX_FMT_MONOWHITE, // not supported
154+ //PIX_FMT_MONOBLACK, // not supported
155+ //PIX_FMT_PAL8, // not supported
156+ ));
157+ return 0;
158+}
159+
160+
161+static int config_input(AVFilterLink *link)
162+{
163+ ExpandContext *expand = link->dst->priv;
164+ int i;
165+ int size[INDEX_MAX];
166+
167+ size[INDEX_X] = link->w;
168+ size[INDEX_Y] = link->h;
169+
170+ for(i=0;i<INDEX_MAX;i++){
171+ if (expand->size[i] == -1){
172+ expand->size[i]=size[i];
173+ } else if (expand->size[i] < -1){
174+ expand->size[i]=size[i] - expand->size[i];
175+ } else if (expand->size[INDEX_X] < size[i]){
176+ expand->size[i]=size[i];
177+ }
178+ }
179+
180+ if (expand->aspect > 0.0f) {
181+ if (expand->size[INDEX_Y] < (expand->size[INDEX_X] / expand->aspect)) {
182+ expand->size[INDEX_Y] = (expand->size[INDEX_X] / expand->aspect) + 0.5;
183+ } else {
184+ expand->size[INDEX_X] = (expand->size[INDEX_Y] * expand->aspect) + 0.5;
185+ }
186+ }
187+
188+ for(i=0;i<INDEX_MAX;i++){
189+ if (expand->round > 1) {
190+ expand->size[i] = (1+(expand->size[i]-1)/expand->round)*expand->round;
191+ }
192+ if(expand->offset[i] < 0 || (expand->offset[i]+size[i]) > expand->size[i]){
193+ expand->offset[i] = (expand->size[INDEX_X] - size[i])>>1;
194+ }
195+ }
196+
197+ avcodec_get_chroma_sub_sample(link->format, &expand->shift[INDEX_X], &expand->shift[INDEX_Y]);
198+ for(i=0;i<INDEX_MAX;i++){
199+ expand->offset[i] &= ~((1 << expand->shift[i]) - 1);
200+ expand->size[i] &= ~((1 << expand->shift[i]) - 1);
201+ }
202+
203+ switch(link->format) {
204+ case PIX_FMT_YUV420P:
205+ case PIX_FMT_YUV422P:
206+ case PIX_FMT_YUV444P:
207+ case PIX_FMT_YUV410P:
208+ case PIX_FMT_YUV411P:
209+ case PIX_FMT_YUV440P:
210+ case PIX_FMT_YUVJ420P:
211+ case PIX_FMT_YUVJ422P:
212+ case PIX_FMT_YUVJ444P:
213+ case PIX_FMT_YUVJ440P:
214+ case PIX_FMT_YUVA420P:
215+ case PIX_FMT_NV12:
216+ case PIX_FMT_NV21:
217+ expand->is_yuv = 1;
218+ case PIX_FMT_RGB8:
219+ case PIX_FMT_BGR8:
220+ case PIX_FMT_RGB4_BYTE:
221+ case PIX_FMT_BGR4_BYTE:
222+ case PIX_FMT_GRAY8:
223+ expand->bpp = 1;
224+ break;
225+ case PIX_FMT_RGB24:
226+ case PIX_FMT_BGR24:
227+ expand->bpp = 3;
228+ break;
229+ case PIX_FMT_RGB32:
230+ case PIX_FMT_BGR32:
231+ case PIX_FMT_RGB32_1:
232+ case PIX_FMT_BGR32_1:
233+ expand->bpp = 4;
234+ break;
235+ case PIX_FMT_GRAY16BE:
236+ case PIX_FMT_GRAY16LE:
237+ case PIX_FMT_BGR555:
238+ case PIX_FMT_BGR565:
239+ case PIX_FMT_RGB555:
240+ case PIX_FMT_RGB565:
241+ expand->bpp = 2;
242+ break;
243+ // not supported.
244+ //case PIX_FMT_YUYV422:
245+ //case PIX_FMT_UYVY422:
246+ //case PIX_FMT_UYYVYY411:
247+ //case PIX_FMT_RGB4:
248+ //case PIX_FMT_BGR4:
249+ //case PIX_FMT_MONOWHITE:
250+ //case PIX_FMT_MONOBLACK:
251+ //case PIX_FMT_PAL8:
252+ default: // invalid or not supported format
253+ return -1;
254+ }
255+
256+ return 0;
257+}
258+
259+static int config_output(AVFilterLink *link)
260+{
261+ ExpandContext *expand = link->src->priv;
262+
263+ link->w = expand->size[INDEX_X];
264+ link->h = expand->size[INDEX_Y];
265+
266+ return 0;
267+}
268+
269+static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
270+{
271+ AVFilterLink *out = link->dst->outputs[0];
272+ out->outpic = avfilter_get_video_buffer(out, AV_PERM_WRITE);
273+ out->outpic->pts = picref->pts;
274+ avfilter_start_frame(out, avfilter_ref_pic(out->outpic, ~0));
275+}
276+
277+static void draw_slice(AVFilterLink *link, int y, int h)
278+{
279+ ExpandContext *expand = link->dst->priv;
280+ AVFilterPicRef *outpic = link->dst->outputs[0]->outpic;
281+ AVFilterPicRef *inpic = link->cur_pic;
282+ int i;
283+ int is_first = (y <= 0);
284+ int is_end = (y+h >= inpic->h);
285+
286+ for(i=0;i<4;i++) {
287+ if(outpic->data[i]) {
288+ int j;
289+ char* out_buff = outpic->data[i];
290+ const char* in_buff = inpic->data[i];
291+
292+ int copy_length;
293+ int y_add;
294+ int padcolor;
295+ int x_shift,y_shift;
296+
297+ if(!expand->is_yuv || i == 3){ // not YUV, or alpha channel of YUVA
298+ padcolor = 0;
299+ x_shift = y_shift = 0;
300+ }else{
301+ padcolor = (i == 0) ? 16 : 128;
302+ x_shift = (i == 0) ? 0 : expand->shift[INDEX_X];
303+ y_shift = (i == 0) ? 0 : expand->shift[INDEX_Y];
304+ }
305+
306+ copy_length = (inpic->w >> x_shift) * expand->bpp;
307+ y_add = 1<<y_shift;
308+
309+ if(is_first){
310+ int size = (expand->offset[INDEX_Y] >> y_shift) * outpic->linesize[i];
311+ memset(out_buff,padcolor,size);
312+ out_buff += size;
313+ }else{
314+ int y_skip = expand->offset[INDEX_Y] >> y_shift;
315+ out_buff += outpic->linesize[i] * y_skip;
316+ in_buff += inpic->linesize[i] * y_skip;
317+ }
318+
319+ for(j=0;j<h;j+=y_add){
320+ int size,total_size = 0;
321+ size = (expand->offset[INDEX_X] >> x_shift) * expand->bpp;
322+ memset(out_buff,padcolor,size);
323+ out_buff += size;
324+ total_size += size;
325+
326+ memcpy(out_buff,in_buff,copy_length);
327+ out_buff += copy_length;
328+ total_size += copy_length;
329+
330+ size = outpic->linesize[i]-total_size;
331+ memset(out_buff,padcolor,size);
332+ out_buff += size;
333+
334+ in_buff += inpic->linesize[i];
335+ }
336+
337+ if(is_end){
338+ memset(out_buff,padcolor,((outpic->h-expand->offset[INDEX_Y]-inpic->h) >> y_shift) * outpic->linesize[i]);
339+ }
340+
341+ }
342+ }
343+ if(is_first && is_end){
344+ avfilter_draw_slice(link->dst->outputs[0], 0, outpic->h);
345+ }else if(is_first){
346+ avfilter_draw_slice(link->dst->outputs[0], 0, expand->offset[INDEX_Y] + h);
347+ }else if(is_end){
348+ avfilter_draw_slice(link->dst->outputs[0], expand->offset[INDEX_Y] + y, outpic->h - expand->offset[INDEX_Y] - y);
349+ }else{
350+ avfilter_draw_slice(link->dst->outputs[0], expand->offset[INDEX_Y] + y, h);
351+ }
352+}
353+
354+AVFilter avfilter_vf_expand = {
355+ .name = "expand",
356+ .priv_size = sizeof(ExpandContext),
357+
358+ .init = init,
359+ .query_formats = query_formats,
360+
361+ .inputs = (AVFilterPad[]) {{ .name = "default",
362+ .type = CODEC_TYPE_VIDEO,
363+ .start_frame = start_frame,
364+ .draw_slice = draw_slice,
365+ .config_props = config_input, },
366+ { .name = NULL}},
367+ .outputs = (AVFilterPad[]) {{ .name = "default",
368+ .type = CODEC_TYPE_VIDEO,
369+ .config_props = config_output, },
370+ { .name = NULL}},
371+};
372+
--- /dev/null
+++ b/libavfilter/vf_vhext.c
@@ -0,0 +1,256 @@
1+/*
2+ * 拡張Vhookフィルタ
3+ * copyright (c) 2008 ψ(プサイ)
4+ *
5+ * さきゅばす用に拡張されたVhookライブラリを
6+ * 駆動させるためのフィルタです。
7+ *
8+ * このファイルは「さきゅばす」の一部であり、
9+ * このソースコードはGPLライセンスで配布されますです。
10+ */
11+#include "avfilter.h"
12+#include "common/framehook_ext.h"
13+#include "avtool.h"
14+#include <string.h>
15+#include <stdio.h>
16+#include <ctype.h>
17+
18+#ifdef HAVE_DLFCN_H
19+#include <dlfcn.h>
20+#else
21+//dlfcn.hの無いWindows Mingw環境用
22+#define dlopen(a) ((void*)LoadLibrary(a))
23+#define dlsym(a,b) ((void*)GetProcAddress((HMODULE)(a),(b)))
24+#define dlclose(a) FreeLibrary((HMODULE)(a));
25+#endif
26+
27+//デリミタ。MEncoder側とは同じにしといた方がよさそう。
28+#define VHEXT_DELIM '|'
29+
30+typedef struct{
31+ //引数はあとあと使うので確保。
32+ char* args;
33+ char** argv;
34+ int argc;
35+ //ツールボックス
36+ const toolbox* Box;
37+ //ダイナミックライブラリへのポインタ
38+ void* Dynamic;
39+ //関数へのポインタ
40+ FrameHookExtConfigureFn ExtConfigure;
41+ FrameHookExtProcessFn ExtProcess;
42+ FrameHookExtReleaseFn ExtRelease;
43+ //FrameHookの使うポインタ
44+ void* Context;
45+} Context;
46+
47+/*
48+ * この中でだけ使う関数定義
49+ */
50+
51+char** split(char* str,int str_len,int* argc,char delim);
52+int decode(char* s,int len);
53+
54+/*
55+ * AVFilter構造体に格納される関数群
56+ */
57+
58+static int init(AVFilterContext *ctx, const char *args, void *opaque){
59+ //Contextをとりあえず確保
60+ Context *context= ctx->priv;
61+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]called with args = %s.\n",args);
62+
63+ //引数がNULLなのはおかしい
64+ if(!args) {
65+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Invalid arguments.\n");
66+ return -1;
67+ }
68+ int arg_len = strlen(args);
69+ //引数のコピー
70+ context->args = (char*)av_malloc(arg_len+1);
71+ if(!context->args){
72+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to malloc memory for args.\n");
73+ return -1;
74+ }
75+ memcpy(context->args,args,arg_len);
76+ context->args[arg_len]='\0';//NULLで最後を埋める。
77+
78+ //デコード
79+ decode(context->args,arg_len);
80+ //引数の展開
81+ context->argv = split(context->args,arg_len,&context->argc,VHEXT_DELIM);
82+ if(!context->argv){
83+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to split args.\n");
84+ return -1;
85+ }
86+
87+ //ツールボックスを取得
88+ context->Box = tool_getToolBox();
89+ if(!context->Box){
90+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ToolBox.\n");
91+ return -1;
92+ }
93+
94+ //DLL読み込み
95+ context->Dynamic = dlopen(context->argv[0], RTLD_NOW);
96+ if (!context->Dynamic) {
97+ 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());
98+ return -1;
99+ }
100+ //各関数を取得
101+ context->ExtConfigure = dlsym(context->Dynamic, "ExtConfigure");
102+ context->ExtProcess = dlsym(context->Dynamic, "ExtProcess");
103+ context->ExtRelease = dlsym(context->Dynamic, "ExtRelease");
104+ if(!context->ExtConfigure){
105+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ExtConfigure.\n");
106+ return -1;
107+ }
108+ if(!context->ExtProcess){
109+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ExtProcess.\n");
110+ return -1;
111+ }
112+ if(!context->ExtRelease){
113+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to get ExtRelease.\n");
114+ return -1;
115+ }
116+
117+ //Configureを呼び出す
118+ int code;
119+ if((code = context->ExtConfigure(&context->Context,context->Box,context->argc,context->argv))){
120+ av_log(ctx, AV_LOG_ERROR, "[libavfilter/VhookExt Filter]Failed to configure.Code:%d\n",code);
121+ return -1;
122+ }
123+ return 0;
124+}
125+
126+static void uninit(AVFilterContext *ctx){
127+ //Contextをとりあえず確保
128+ Context *context= ctx->priv;
129+ //開放する。
130+ context->ExtRelease(context->Context,context->Box);
131+ //引数も開放する。
132+ if(!context->args){
133+ av_free(context->args);
134+ }
135+ if(!context->argv){
136+ av_free(context->argv);
137+ }
138+ //DLLも閉じる
139+ dlclose(context->Dynamic);
140+}
141+
142+static int query_formats(AVFilterContext *ctx){
143+ //SDLで使いやすくするためにRGB24フォーマットを要求する。
144+ enum PixelFormat pix_fmts[] = { PIX_FMT_RGB24, PIX_FMT_NONE };
145+ avfilter_set_common_formats(ctx,avfilter_make_format_list(pix_fmts));
146+ return 0;
147+}
148+
149+/*
150+ * AVFilterPadのInput側に呼ばれる関数
151+ */
152+
153+static void start_frame(AVFilterLink *link, AVFilterBufferRef *bufref){
154+ //おまじない
155+ avfilter_start_frame(link->dst->outputs[0], bufref);
156+}
157+
158+static void end_frame(AVFilterLink *link){
159+ //ポインタは基本
160+ Context *context = link->dst->priv;
161+ //よくわからないけどとりあえずおまじない(えー
162+ AVFilterLink* output = link->dst->outputs[0];
163+ AVFilterBufferRef *buf = link->cur_buf;
164+ //独自構造体に代入
165+ vhext_frame frame;
166+ frame.data = buf->data[0];
167+ frame.linesize = buf->linesize[0];
168+ frame.w = buf->video->w;
169+ frame.h = buf->video->h;
170+ frame.pts = ((double)buf->pts) / AV_TIME_BASE;
171+ //ライブラリを呼び出す。
172+ context->ExtProcess(context->Context,context->Box,&frame);
173+
174+ //おなじくおなじまい(えええ
175+ avfilter_draw_slice(output, 0, buf->video->h, 1);
176+ avfilter_end_frame(output);
177+}
178+
179+AVFilter avfilter_vf_vhext=
180+{
181+ .name = "vhext",
182+
183+ .priv_size = sizeof(Context),
184+
185+ .init = init,
186+ .uninit = uninit,
187+
188+ .query_formats = query_formats,
189+ .inputs = (AVFilterPad[]) {{ .name = "default",
190+ .type = AVMEDIA_TYPE_VIDEO,
191+ .start_frame = start_frame,
192+ .end_frame = end_frame,
193+ .min_perms = AV_PERM_WRITE |
194+ AV_PERM_READ,
195+ .rej_perms = AV_PERM_REUSE |
196+ AV_PERM_REUSE2},
197+ { .name = NULL}},
198+ .outputs = (AVFilterPad[]) {{ .name = "default",
199+ .type = AVMEDIA_TYPE_VIDEO, },
200+ { .name = NULL}},
201+};
202+
203+/*
204+ * この中でのみ使われる関数
205+ */
206+
207+//文字列を特定の文字によって分けます。
208+char** split(char* str,int str_len,int* argc,char delim){
209+ //チェック
210+ if(!str || delim=='\0' || str_len < 0){
211+ return 0;
212+ }
213+ //確保
214+ char** argv = av_malloc(sizeof(char*));
215+ if(!argv){
216+ return 0;
217+ }
218+ //ループ開始
219+ int last = 0;
220+ int i;
221+ int arg_cnt = 0;
222+ for(i=0;i<str_len;i++){
223+ if(str[i] == delim){//デリミタに達した
224+ str[i] = '\0';
225+ argv[arg_cnt] = &str[last];
226+ arg_cnt++;
227+ last = i+1;
228+ argv = av_realloc(argv,sizeof(char*) * (arg_cnt+1));
229+ }
230+ }
231+ argv[arg_cnt] = &str[last];
232+ *argc = arg_cnt + 1;
233+ return argv;
234+}
235+
236+//URエンコード記法が使えます。
237+int decode(char* s,int len){
238+ int i,j;
239+ char buf,*s1;
240+ if(len==0)return(-1);
241+ s1=(char*)av_malloc(len);
242+ for(i=0,j=0;i<len;i++,j++)
243+ {
244+ if(s[i]=='+'){s1[j]=' ';continue;}
245+ if(s[i]!='%') {s1[j]=s[i];continue;}
246+ buf=((s[++i]>='A') ? s[i]-'A'+10 : s[i]-'0');
247+ buf*=16;
248+ buf+=((s[++i]>='A') ? s[i]-'A'+10 : s[i]-'0');
249+ s1[j]=buf;
250+ }
251+ for(i=0;i<j;i++) s[i]=s1[i];
252+ s[i]='\0';
253+ av_free(s1);
254+ return(0);
255+}
256+
旧リポジトリブラウザで表示