2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "img_format.h"
33 #include "libvo/fastmemcpy.h"
34 #include "libavutil/avutil.h"
37 #include "libvo/sub.h"
38 #include "libvo/osd.h"
44 static struct vf_priv_s
{
45 // These four values are a backup of the values parsed from the command line.
46 // This is necessary so that we do not get a mess upon filter reinit due to
47 // e.g. aspect changes and with only aspect specified on the command line,
48 // where we would otherwise use the values calculated for a different aspect
49 // instead of recalculating them again.
50 int cfg_exp_w
, cfg_exp_h
;
51 int cfg_exp_x
, cfg_exp_y
;
57 unsigned char* fb_ptr
;
60 } const vf_priv_dflt
= {
73 extern int opt_screen_size_x
;
74 extern int opt_screen_size_y
;
76 //===========================================================================//
79 static struct vf_instance_s
* vf
=NULL
; // fixme (needs sub.c changes)
80 static int orig_w
,orig_h
;
82 static void remove_func_2(int x0
,int y0
, int w
,int h
){
83 // TODO: let's cleanup the place
84 //printf("OSD clear: %d;%d %dx%d \n",x0,y0,w,h);
85 vf_mpi_clear(vf
->dmpi
,x0
,y0
,w
,h
);
88 static void remove_func(int x0
,int y0
, int w
,int h
){
89 if(!vo_osd_changed_flag
) return;
90 // split it to 4 parts:
91 if(y0
<vf
->priv
->exp_y
){
92 // it has parts above the image:
94 if(y
>vf
->priv
->exp_y
) y
=vf
->priv
->exp_y
;
95 remove_func_2(x0
,y0
,w
,y
-y0
);
96 if(y0
+h
<=vf
->priv
->exp_y
) return;
99 if(y0
+h
>vf
->priv
->exp_y
+orig_h
){
100 // it has parts under the image:
102 if(y
<vf
->priv
->exp_y
+orig_h
) y
=vf
->priv
->exp_y
+orig_h
;
103 remove_func_2(x0
,y
,w
,y0
+h
-y
);
104 if(y0
>=vf
->priv
->exp_y
+orig_h
) return;
107 if(x0
<vf
->priv
->exp_x
){
108 // it has parts on the left side of the image:
110 if(x
>vf
->priv
->exp_x
) x
=vf
->priv
->exp_x
;
111 remove_func_2(x0
,y0
,x
-x0
,h
);
112 if(x0
+w
<=vf
->priv
->exp_x
) return;
115 if(x0
+w
>vf
->priv
->exp_x
+orig_w
){
116 // it has parts on the right side of the image:
118 if(x
<vf
->priv
->exp_x
+orig_w
) x
=vf
->priv
->exp_x
+orig_w
;
119 remove_func_2(x
,y0
,x0
+w
-x
,h
);
120 if(x0
>=vf
->priv
->exp_x
+orig_w
) return;
125 static void draw_func(int x0
,int y0
, int w
,int h
,unsigned char* src
, unsigned char *srca
, int stride
){
127 if(!vo_osd_changed_flag
&& vf
->dmpi
->planes
[0]==vf
->priv
->fb_ptr
){
128 // ok, enough to update the area inside the video, leave the black bands
130 if(x0
<vf
->priv
->exp_x
){
131 int tmp
=vf
->priv
->exp_x
-x0
;
132 w
-=tmp
; src
+=tmp
; srca
+=tmp
; x0
+=tmp
;
134 if(y0
<vf
->priv
->exp_y
){
135 int tmp
=vf
->priv
->exp_y
-y0
;
136 h
-=tmp
; src
+=tmp
*stride
; srca
+=tmp
*stride
; y0
+=tmp
;
138 if(x0
+w
>vf
->priv
->exp_x
+orig_w
){
139 w
=vf
->priv
->exp_x
+orig_w
-x0
;
141 if(y0
+h
>vf
->priv
->exp_y
+orig_h
){
142 h
=vf
->priv
->exp_y
+orig_h
-y0
;
145 if(w
<=0 || h
<=0) return; // nothing to do...
146 // printf("OSD redraw: %d;%d %dx%d \n",x0,y0,w,h);
147 dst
=vf
->dmpi
->planes
[0]+
148 vf
->dmpi
->stride
[0]*y0
+
149 (vf
->dmpi
->bpp
>>3)*x0
;
150 switch(vf
->dmpi
->imgfmt
){
153 vo_draw_alpha_rgb15(w
,h
,src
,srca
,stride
,dst
,vf
->dmpi
->stride
[0]);
157 vo_draw_alpha_rgb16(w
,h
,src
,srca
,stride
,dst
,vf
->dmpi
->stride
[0]);
161 vo_draw_alpha_rgb24(w
,h
,src
,srca
,stride
,dst
,vf
->dmpi
->stride
[0]);
165 vo_draw_alpha_rgb32(w
,h
,src
,srca
,stride
,dst
,vf
->dmpi
->stride
[0]);
174 vo_draw_alpha_yv12(w
,h
,src
,srca
,stride
,dst
,vf
->dmpi
->stride
[0]);
177 vo_draw_alpha_yuy2(w
,h
,src
,srca
,stride
,dst
,vf
->dmpi
->stride
[0]);
180 vo_draw_alpha_yuy2(w
,h
,src
,srca
,stride
,dst
+1,vf
->dmpi
->stride
[0]);
185 static void draw_osd(struct vf_instance_s
* vf_
,int w
,int h
){
186 vf
=vf_
;orig_w
=w
;orig_h
=h
;
187 // printf("======================================\n");
188 if(vf
->priv
->exp_w
!=w
|| vf
->priv
->exp_h
!=h
||
189 vf
->priv
->exp_x
|| vf
->priv
->exp_y
){
190 // yep, we're expanding image, not just copy.
191 if(vf
->dmpi
->planes
[0]!=vf
->priv
->fb_ptr
){
192 // double buffering, so we need full clear :(
193 if (vf
->priv
->exp_y
> 0)
194 remove_func_2(0,0,vf
->priv
->exp_w
,vf
->priv
->exp_y
);
195 if (vf
->priv
->exp_y
+h
< vf
->priv
->exp_h
)
196 remove_func_2(0,vf
->priv
->exp_y
+h
,vf
->priv
->exp_w
,vf
->priv
->exp_h
-h
-vf
->priv
->exp_y
);
197 if (vf
->priv
->exp_x
> 0)
198 remove_func_2(0,vf
->priv
->exp_y
,vf
->priv
->exp_x
,h
);
199 if (vf
->priv
->exp_x
+w
< vf
->priv
->exp_w
)
200 remove_func_2(vf
->priv
->exp_x
+w
,vf
->priv
->exp_y
,vf
->priv
->exp_w
-w
-vf
->priv
->exp_x
,h
);
203 vo_remove_text(vf
->priv
->exp_w
,vf
->priv
->exp_h
,remove_func
);
206 vo_draw_text(vf
->priv
->exp_w
,vf
->priv
->exp_h
,draw_func
);
207 // save buffer pointer for double buffering detection - yes, i know it's
208 // ugly method, but note that codecs with DR support does the same...
210 vf
->priv
->fb_ptr
=vf
->dmpi
->planes
[0];
214 //===========================================================================//
216 static int config(struct vf_instance_s
* vf
,
217 int width
, int height
, int d_width
, int d_height
,
218 unsigned int flags
, unsigned int outfmt
){
219 if(outfmt
== IMGFMT_MPEGPES
) {
220 vf
->priv
->passthrough
= 1;
221 return vf_next_config(vf
,width
,height
,d_width
,d_height
,flags
,outfmt
);
223 if (outfmt
== IMGFMT_IF09
) return 0;
224 vf
->priv
->exp_x
= vf
->priv
->cfg_exp_x
;
225 vf
->priv
->exp_y
= vf
->priv
->cfg_exp_y
;
226 vf
->priv
->exp_w
= vf
->priv
->cfg_exp_w
;
227 vf
->priv
->exp_h
= vf
->priv
->cfg_exp_h
;
228 // calculate the missing parameters:
230 if(vf
->priv
->exp_w
<width
) vf
->priv
->exp_w
=width
;
231 if(vf
->priv
->exp_h
<height
) vf
->priv
->exp_h
=height
;
233 if ( vf
->priv
->exp_w
== -1 ) vf
->priv
->exp_w
=width
;
234 else if (vf
->priv
->exp_w
< -1 ) vf
->priv
->exp_w
=width
- vf
->priv
->exp_w
;
235 else if ( vf
->priv
->exp_w
<width
) vf
->priv
->exp_w
=width
;
236 if ( vf
->priv
->exp_h
== -1 ) vf
->priv
->exp_h
=height
;
237 else if ( vf
->priv
->exp_h
< -1 ) vf
->priv
->exp_h
=height
- vf
->priv
->exp_h
;
238 else if( vf
->priv
->exp_h
<height
) vf
->priv
->exp_h
=height
;
240 if (vf
->priv
->aspect
) {
241 float adjusted_aspect
= vf
->priv
->aspect
;
242 adjusted_aspect
*= ((double)width
/height
) / ((double)d_width
/d_height
);
243 if (vf
->priv
->exp_h
< vf
->priv
->exp_w
/ adjusted_aspect
) {
244 vf
->priv
->exp_h
= vf
->priv
->exp_w
/ adjusted_aspect
+ 0.5;
246 vf
->priv
->exp_w
= vf
->priv
->exp_h
* adjusted_aspect
+ 0.5;
249 if (vf
->priv
->round
> 1) { // round up.
250 vf
->priv
->exp_w
= (1 + (vf
->priv
->exp_w
- 1) / vf
->priv
->round
) * vf
->priv
->round
;
251 vf
->priv
->exp_h
= (1 + (vf
->priv
->exp_h
- 1) / vf
->priv
->round
) * vf
->priv
->round
;
254 if(vf
->priv
->exp_x
<0 || vf
->priv
->exp_x
+width
>vf
->priv
->exp_w
) vf
->priv
->exp_x
=(vf
->priv
->exp_w
-width
)/2;
255 if(vf
->priv
->exp_y
<0 || vf
->priv
->exp_y
+height
>vf
->priv
->exp_h
) vf
->priv
->exp_y
=(vf
->priv
->exp_h
-height
)/2;
256 vf
->priv
->fb_ptr
=NULL
;
258 if(!opt_screen_size_x
&& !opt_screen_size_y
){
259 d_width
=d_width
*vf
->priv
->exp_w
/width
;
260 d_height
=d_height
*vf
->priv
->exp_h
/height
;
262 return vf_next_config(vf
,vf
->priv
->exp_w
,vf
->priv
->exp_h
,d_width
,d_height
,flags
,outfmt
);
265 // there are 4 cases:
266 // codec --DR--> expand --DR--> vo
267 // codec --DR--> expand -copy-> vo
268 // codec -copy-> expand --DR--> vo
269 // codec -copy-> expand -copy-> vo (worst case)
271 static void get_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
){
272 // if(mpi->type==MP_IMGTYPE_IPB) return; // not yet working
274 if(vf
->priv
->osd
&& (mpi
->flags
&MP_IMGFLAG_PRESERVE
)){
275 // check if we have to render osd!
276 vo_update_osd(vf
->priv
->exp_w
, vf
->priv
->exp_h
);
277 if(vo_osd_check_range_update(vf
->priv
->exp_x
,vf
->priv
->exp_y
,
278 vf
->priv
->exp_x
+mpi
->w
,vf
->priv
->exp_y
+mpi
->h
)) return;
281 if(vf
->priv
->exp_w
==mpi
->width
||
282 (mpi
->flags
&(MP_IMGFLAG_ACCEPT_STRIDE
|MP_IMGFLAG_ACCEPT_WIDTH
)) ){
284 mpi
->priv
=vf
->dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
285 mpi
->type
, mpi
->flags
,
286 FFMAX(vf
->priv
->exp_w
, mpi
->width
+vf
->priv
->exp_x
),
287 FFMAX(vf
->priv
->exp_h
, mpi
->height
+vf
->priv
->exp_y
));
288 if((vf
->dmpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
) &&
289 !(vf
->dmpi
->flags
& MP_IMGFLAG_DIRECT
)){
290 mp_msg(MSGT_VFILTER
, MSGL_INFO
, MSGTR_MPCODECS_FullDRNotPossible
);
293 // set up mpi as a cropped-down image of dmpi:
294 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
295 mpi
->planes
[0]=vf
->dmpi
->planes
[0]+
296 vf
->priv
->exp_y
*vf
->dmpi
->stride
[0]+vf
->priv
->exp_x
;
297 mpi
->planes
[1]=vf
->dmpi
->planes
[1]+
298 (vf
->priv
->exp_y
>>mpi
->chroma_y_shift
)*vf
->dmpi
->stride
[1]+(vf
->priv
->exp_x
>>mpi
->chroma_x_shift
);
299 mpi
->planes
[2]=vf
->dmpi
->planes
[2]+
300 (vf
->priv
->exp_y
>>mpi
->chroma_y_shift
)*vf
->dmpi
->stride
[2]+(vf
->priv
->exp_x
>>mpi
->chroma_x_shift
);
301 mpi
->stride
[1]=vf
->dmpi
->stride
[1];
302 mpi
->stride
[2]=vf
->dmpi
->stride
[2];
304 mpi
->planes
[0]=vf
->dmpi
->planes
[0]+
305 vf
->priv
->exp_y
*vf
->dmpi
->stride
[0]+
306 vf
->priv
->exp_x
*(vf
->dmpi
->bpp
/8);
308 mpi
->stride
[0]=vf
->dmpi
->stride
[0];
309 mpi
->width
=vf
->dmpi
->width
;
310 mpi
->flags
|=MP_IMGFLAG_DIRECT
;
311 mpi
->flags
&=~MP_IMGFLAG_DRAW_CALLBACK
;
312 // vf->dmpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK;
316 static void start_slice(struct vf_instance_s
* vf
, mp_image_t
*mpi
){
317 // printf("start_slice called! flag=%d\n",mpi->flags&MP_IMGFLAG_DRAW_CALLBACK);
318 if(!vf
->next
->draw_slice
){
319 mpi
->flags
&=~MP_IMGFLAG_DRAW_CALLBACK
;
322 // they want slices!!! allocate the buffer.
324 mpi
->priv
=vf
->dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
325 // MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
326 MP_IMGTYPE_TEMP
, mpi
->flags
,
327 FFMAX(vf
->priv
->exp_w
, mpi
->width
+vf
->priv
->exp_x
),
328 FFMAX(vf
->priv
->exp_h
, mpi
->height
+vf
->priv
->exp_y
));
329 if(!(vf
->dmpi
->flags
&MP_IMGFLAG_DRAW_CALLBACK
))
330 mp_msg(MSGT_VFILTER
, MSGL_WARN
, MSGTR_MPCODECS_WarnNextFilterDoesntSupportSlices
); // shouldn't happen.
331 vf
->priv
->first_slice
= 1;
334 static void draw_top_blackbar_slice(struct vf_instance_s
* vf
,
335 unsigned char** src
, int* stride
, int w
,int h
, int x
, int y
){
336 if(vf
->priv
->exp_y
>0 && y
== 0) {
337 vf_next_draw_slice(vf
, vf
->dmpi
->planes
, vf
->dmpi
->stride
,
338 vf
->dmpi
->w
,vf
->priv
->exp_y
,0,0);
343 static void draw_bottom_blackbar_slice(struct vf_instance_s
* vf
,
344 unsigned char** src
, int* stride
, int w
,int h
, int x
, int y
){
345 if(vf
->priv
->exp_y
+vf
->h
<vf
->dmpi
->h
&& y
+h
== vf
->h
) {
346 unsigned char *src2
[MP_MAX_PLANES
];
347 src2
[0] = vf
->dmpi
->planes
[0]
348 + (vf
->priv
->exp_y
+vf
->h
)*vf
->dmpi
->stride
[0];
349 if(vf
->dmpi
->flags
&MP_IMGFLAG_PLANAR
){
350 src2
[1] = vf
->dmpi
->planes
[1]
351 + ((vf
->priv
->exp_y
+vf
->h
)>>vf
->dmpi
->chroma_y_shift
)*vf
->dmpi
->stride
[1];
352 src2
[2] = vf
->dmpi
->planes
[2]
353 + ((vf
->priv
->exp_y
+vf
->h
)>>vf
->dmpi
->chroma_y_shift
)*vf
->dmpi
->stride
[2];
355 src2
[1] = vf
->dmpi
->planes
[1]; // passthrough rgb8 palette
357 vf_next_draw_slice(vf
, src2
, vf
->dmpi
->stride
,
358 vf
->dmpi
->w
,vf
->dmpi
->h
-(vf
->priv
->exp_y
+vf
->h
),
359 0,vf
->priv
->exp_y
+vf
->h
);
363 static void draw_slice(struct vf_instance_s
* vf
,
364 unsigned char** src
, int* stride
, int w
,int h
, int x
, int y
){
365 // printf("draw_slice() called %d at %d\n",h,y);
367 if (y
== 0 && y
+h
== vf
->h
) {
368 // special case - only one slice
369 draw_top_blackbar_slice(vf
, src
, stride
, w
, h
, x
, y
);
370 vf_next_draw_slice(vf
,src
,stride
,w
,h
,x
+vf
->priv
->exp_x
,y
+vf
->priv
->exp_y
);
371 draw_bottom_blackbar_slice(vf
, src
, stride
, w
, h
, x
, y
);
374 if (vf
->priv
->first_slice
) {
375 draw_top_blackbar_slice(vf
, src
, stride
, w
, h
, x
, y
);
376 draw_bottom_blackbar_slice(vf
, src
, stride
, w
, h
, x
, y
);
378 vf_next_draw_slice(vf
,src
,stride
,w
,h
,x
+vf
->priv
->exp_x
,y
+vf
->priv
->exp_y
);
379 if (!vf
->priv
->first_slice
) {
380 draw_top_blackbar_slice(vf
, src
, stride
, w
, h
, x
, y
);
381 draw_bottom_blackbar_slice(vf
, src
, stride
, w
, h
, x
, y
);
383 vf
->priv
->first_slice
= 0;
386 static int put_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
, double pts
){
387 if (vf
->priv
->passthrough
) {
388 mp_image_t
*dmpi
= vf_get_image(vf
->next
, IMGFMT_MPEGPES
,
389 MP_IMGTYPE_EXPORT
, 0, mpi
->w
, mpi
->h
);
390 dmpi
->planes
[0]=mpi
->planes
[0];
391 return vf_next_put_image(vf
,dmpi
, pts
);
394 if(mpi
->flags
&MP_IMGFLAG_DIRECT
|| mpi
->flags
&MP_IMGFLAG_DRAW_CALLBACK
){
396 if(!vf
->dmpi
) { mp_msg(MSGT_VFILTER
, MSGL_WARN
, MSGTR_MPCODECS_FunWhydowegetNULL
); return 0; }
399 if(vf
->priv
->osd
) draw_osd(vf
,mpi
->w
,mpi
->h
);
401 // we've used DR, so we're ready...
402 if(!(mpi
->flags
&MP_IMGFLAG_PLANAR
))
403 vf
->dmpi
->planes
[1] = mpi
->planes
[1]; // passthrough rgb8 palette
404 return vf_next_put_image(vf
,vf
->dmpi
, pts
);
407 // hope we'll get DR buffer:
408 vf
->dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
409 MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
,
410 vf
->priv
->exp_w
, vf
->priv
->exp_h
);
413 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
414 memcpy_pic(vf
->dmpi
->planes
[0]+
415 vf
->priv
->exp_y
*vf
->dmpi
->stride
[0]+vf
->priv
->exp_x
,
416 mpi
->planes
[0], mpi
->w
, mpi
->h
,
417 vf
->dmpi
->stride
[0],mpi
->stride
[0]);
418 memcpy_pic(vf
->dmpi
->planes
[1]+
419 (vf
->priv
->exp_y
>>mpi
->chroma_y_shift
)*vf
->dmpi
->stride
[1]+(vf
->priv
->exp_x
>>mpi
->chroma_x_shift
),
420 mpi
->planes
[1], (mpi
->w
>>mpi
->chroma_x_shift
), (mpi
->h
>>mpi
->chroma_y_shift
),
421 vf
->dmpi
->stride
[1],mpi
->stride
[1]);
422 memcpy_pic(vf
->dmpi
->planes
[2]+
423 (vf
->priv
->exp_y
>>mpi
->chroma_y_shift
)*vf
->dmpi
->stride
[2]+(vf
->priv
->exp_x
>>mpi
->chroma_x_shift
),
424 mpi
->planes
[2], (mpi
->w
>>mpi
->chroma_x_shift
), (mpi
->h
>>mpi
->chroma_y_shift
),
425 vf
->dmpi
->stride
[2],mpi
->stride
[2]);
427 memcpy_pic(vf
->dmpi
->planes
[0]+
428 vf
->priv
->exp_y
*vf
->dmpi
->stride
[0]+vf
->priv
->exp_x
*(vf
->dmpi
->bpp
/8),
429 mpi
->planes
[0], mpi
->w
*(vf
->dmpi
->bpp
/8), mpi
->h
,
430 vf
->dmpi
->stride
[0],mpi
->stride
[0]);
431 vf
->dmpi
->planes
[1] = mpi
->planes
[1]; // passthrough rgb8 palette
434 if(vf
->priv
->osd
) draw_osd(vf
,mpi
->w
,mpi
->h
);
436 return vf_next_put_image(vf
,vf
->dmpi
, pts
);
439 //===========================================================================//
441 static int control(struct vf_instance_s
* vf
, int request
, void* data
){
444 case VFCTRL_DRAW_OSD
:
445 if(vf
->priv
->osd
) return CONTROL_TRUE
;
448 return vf_next_control(vf
,request
,data
);
451 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
){
452 return vf_next_query_format(vf
,fmt
);
455 static int open(vf_instance_t
*vf
, char* args
){
458 vf
->query_format
=query_format
;
459 vf
->start_slice
=start_slice
;
460 vf
->draw_slice
=draw_slice
;
461 vf
->get_image
=get_image
;
462 vf
->put_image
=put_image
;
463 mp_msg(MSGT_VFILTER
, MSGL_INFO
, "Expand: %d x %d, %d ; %d, osd: %d, aspect: %f, round: %d\n",
474 #define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
475 static m_option_t vf_opts_fields
[] = {
476 {"w", ST_OFF(cfg_exp_w
), CONF_TYPE_INT
, 0, 0 ,0, NULL
},
477 {"h", ST_OFF(cfg_exp_h
), CONF_TYPE_INT
, 0, 0 ,0, NULL
},
478 {"x", ST_OFF(cfg_exp_x
), CONF_TYPE_INT
, M_OPT_MIN
, -1, 0, NULL
},
479 {"y", ST_OFF(cfg_exp_y
), CONF_TYPE_INT
, M_OPT_MIN
, -1, 0, NULL
},
480 {"osd", ST_OFF(osd
), CONF_TYPE_FLAG
, 0 , 0, 1, NULL
},
481 {"aspect", ST_OFF(aspect
), CONF_TYPE_DOUBLE
, M_OPT_MIN
, 0, 0, NULL
},
482 {"round", ST_OFF(round
), CONF_TYPE_INT
, M_OPT_MIN
, 1, 0, NULL
},
483 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
486 static m_struct_t vf_opts
= {
488 sizeof(struct vf_priv_s
),
495 const vf_info_t vf_info_expand
= {
508 //===========================================================================//