Robert Winder wrote:
> Well i believe dischi made some progress on this and xine can be used
> for audio and video with cvs version.
>
> But it doesn't work for me that well. If i remove video.mplayer and
> activate video.xine xine is used but there is no LIRC event control. Is
> this the correct way to enable xine?
xine should be started with --no-lirc and --stdctrl. With that, Freevo
uses lirc and sends commands to xine.
> Also A/V sync is way off with xine when used for video. I know there
> is a option for mplayer to work around the audio delay from
> MMpython. Maybe we need this for xine as well.
That's why I prefer mplayer. You can set many options on the command
line, like -delay. Since xine doesn't support this, Freevo can't work
around it.
> xine for DVD is working great after installing all the freevo
> dependencies because of the segfaulting with dvdinfo in the runtime.
> That's something what imho needs to be fixed it's taking all the fun
> away :-)
Yes.
> Also checked out CVS and the blending of the images is very cool, nice
> work. ;-) But still got some questions left about the new features in
> cvs.
>
> * Got xine-lib xine-ui cvs installed but the new enhance interlacing
> stuff doesn't seem to work. Does i have to enable this somewhere ?
If you use X, it should work. If you use fbxine, I made a patch
yesterday and send it to the xine people. It's not in cvs, I expect it
there in about 3 days. I attached the patch in this mail in case you
want to try it.
> * When xine is configured as dvd player and i select DVD title list
> mplayer is used and as i prefer xine i didn't expected this.
Beacuse the rating for dvd tracks in xine is low. I had some problems
playing only track x without displaying the menu afterwards. Maybe I'm
missing something. I also failed to only play CVS track x with the new
xine cvs plugin.
> * and something i don't understand for quite a while is the configure
> directory option. When used is this saved somewhere or is this for
> future use ?
It should be saved to folder.fxd and should remember the settings.
> * Why doesn't recursive/random play work for images or must this be
> done manually with playlists ?
It should work in current cvs -- maybe too good. If I read the code
correctly, it will always add all media. So it may happen that the
audio playlist conatins an image. I will fix that.
Dischi
*** ../fb.orig/actions.c Sun Nov 16 15:08:01 2003
--- actions.c Sun Nov 30 20:07:41 2003
***************
*** 33,39 ****
#include "main.h"
#include "actions.h"
#include "osd.h"
!
#define GUI_NEXT 1
#define GUI_PREV 2
--- 33,39 ----
#include "main.h"
#include "actions.h"
#include "osd.h"
! #include "post.h"
#define GUI_NEXT 1
#define GUI_PREV 2
***************
*** 441,445 ****
--- 441,451 ----
case ACTID_QUIT:
fbxine_exit();
break;
+ case ACTID_TOGGLE_INTERLEAVE:
+ fbxine.deinterlace_enable = !fbxine.deinterlace_enable;
+ osd_display_info("Deinterlace: %s", (fbxine.deinterlace_enable) ?
+ "enabled" : "disabled");
+ post_deinterlace();
+ break;
}
}
*** ../fb.orig/keys.c Mon Jul 28 20:55:10 2003
--- keys.c Sun Nov 30 19:34:01 2003
***************
*** 75,80 ****
--- 75,81 ----
case 'L': return ACTID_EVENT_RIGHT;
case 'M': return ACTID_EVENT_MENU1;
case 'S': return ACTID_EVENT_SELECT;
+ case 'i': return ACTID_TOGGLE_INTERLEAVE;
}
return 0;
*** ../fb.orig/main.c Sun Nov 9 11:58:48 2003
--- main.c Sun Nov 30 20:10:49 2003
***************
*** 44,49 ****
--- 44,58 ----
tty_fd: -1,
video_port_id: "fb",
+ post_elements: NULL,
+ post_elements_num: 0,
+ post_enable: 1,
+
+ deinterlace_plugin: NULL,
+ deinterlace_elements: NULL,
+ deinterlace_elements_num: 0,
+ deinterlace_enable: 0,
+
exit_cond: PTHREAD_COND_INITIALIZER
};
***************
*** 275,280 ****
--- 284,294 ----
pplugin_rewire_posts();
}
+ post_deinterlace_init(NULL);
+
+ if (fbxine.deinterlace_enable)
+ post_deinterlace();
+
osd_init();
fbxine.osd.enabled = 1;
return 1;
*** ../fb.orig/main.h Sun Nov 16 15:08:01 2003
--- main.h Sun Nov 30 20:06:32 2003
***************
*** 81,88 ****
int debug;
int ignore_next;
! post_element_t **post_elements;
! int post_elements_num;
#ifdef HAVE_LIRC
struct
--- 81,96 ----
int debug;
int ignore_next;
!
! post_element_t **post_elements;
! int post_elements_num;
! int post_enable;
!
! char *deinterlace_plugin;
! post_element_t **deinterlace_elements;
! int deinterlace_elements_num;
! int deinterlace_enable;
!
#ifdef HAVE_LIRC
struct
***************
*** 123,125 ****
--- 131,140 ----
extern struct fbxine fbxine;
void fbxine_exit(void);
+
+ #define SAFE_FREE(x) do { \
+ if((x)) { \
+ free((x)); \
+ x = NULL; \
+ } \
+ } while(0)
*** ../fb.orig/options.c Mon Jul 28 20:55:15 2003
--- options.c Sun Nov 30 20:14:25 2003
***************
*** 103,109 ****
#ifdef HAVE_LIRC
printf(" -L, --no-lirc Turn off LIRC support.\n");
#endif
! printf(" --stdctl Turn on controlling xine over STDIN.\n"
" --post <plugin>[:parameter=value][,...]\n"
" Load a post plugin.\n"
" Parameters are comma separated.\n"
--- 103,112 ----
#ifdef HAVE_LIRC
printf(" -L, --no-lirc Turn off LIRC support.\n");
#endif
! printf(" -D, --deinterlace Deinterlace video output. One or more post plugin\n"
! " can be specified, with optional parameters.\n"
! " Syntax is the same as --post option.\n"
! " --stdctl Turn on controlling xine over STDIN.\n"
" --post <plugin>[:parameter=value][,...]\n"
" Load a post plugin.\n"
" Parameters are comma separated.\n"
***************
*** 136,144 ****
{ "no-lirc", no_argument, 0, 'L' },
{ "stdctl", optional_argument, 0, OPTION_STDCTL },
{"post", required_argument, 0, OPTION_POST },
{ 0, no_argument, 0, 0 }
};
! const char *short_options = "?hda:qA:V:R::v";
int c = '?', option_index = 0;
opterr = 0;
--- 139,148 ----
{ "no-lirc", no_argument, 0, 'L' },
{ "stdctl", optional_argument, 0, OPTION_STDCTL },
{"post", required_argument, 0, OPTION_POST },
+ {"deinterlace", no_argument, 0, 'D' },
{ 0, no_argument, 0, 0 }
};
! const char *short_options = "?hda:qA:V:R::vD";
int c = '?', option_index = 0;
opterr = 0;
***************
*** 146,152 ****
long_options, &option_index)) != EOF)
{
switch(c) {
!
case 'a':
sscanf(optarg, "%i", &fbxine.audio_channel);
break;
--- 150,159 ----
long_options, &option_index)) != EOF)
{
switch(c) {
! case 'D':
! fbxine.deinterlace_enable = 1;
! break;
!
case 'a':
sscanf(optarg, "%i", &fbxine.audio_channel);
break;
*** ../fb.orig/osd.c Sun Nov 16 15:08:01 2003
--- osd.c Sun Nov 30 20:05:35 2003
***************
*** 109,121 ****
{ NULL , 0 }
};
- #define SAFE_FREE(x) do { \
- if((x)) { \
- free((x)); \
- x = NULL; \
- } \
- } while(0)
-
static uint32_t color[OVL_PALETTE_SIZE];
static uint8_t trans[OVL_PALETTE_SIZE];
--- 109,114 ----
*** ../fb.orig/post.c Sun Aug 17 17:32:57 2003
--- post.c Sun Nov 30 20:06:20 2003
***************
*** 87,263 ****
pobj->api->get_parameters(pobj->post, pobj->param_data);
}
- void pplugin_parse_and_store_post(const char *post) {
! /* -post <name>:option1=value1,option2=value2... */
! if(post && strlen(post)) {
! char *p = (char *) post;
! char *plugin, *args = NULL;
! xine_post_t *post;
!
! while(*p == ' ')
! p++;
!
! xine_strdupa(plugin, p);
! if((p = strchr(plugin, ':')))
! *p++ = '\0';
! if(p && (strlen(p) > 1))
! args = p;
!
! post = xine_post_init(fbxine.xine, plugin, 0, &fbxine.audio_port,
! &fbxine.video_port);
!
! if(post) {
! post_object_t pobj;
!
! if(!fbxine.post_elements_num)
! fbxine.post_elements = (post_element_t **) xine_xmalloc(sizeof(post_element_t *) * 2);
! else
! fbxine.post_elements = (post_element_t **)
! realloc(fbxine.post_elements, sizeof(post_element_t *) * (fbxine.post_elements_num + 2));
!
! fbxine.post_elements[fbxine.post_elements_num] = (post_element_t *)
! xine_xmalloc(sizeof(post_element_t));
! fbxine.post_elements[fbxine.post_elements_num]->post = post;
! fbxine.post_elements[fbxine.post_elements_num]->name = strdup(plugin);
! fbxine.post_elements_num++;
! fbxine.post_elements[fbxine.post_elements_num] = NULL;
! memset(&pobj, 0, sizeof(post_object_t));
! pobj.post = post;
!
! if(__pplugin_retrieve_parameters(&pobj)) {
! int i;
!
! if(pobj.properties_names && args) {
! char *param;
! while((param = xine_strsep(&args, ",")) != NULL) {
!
! p = param;
!
! while((*p != '\0') && (*p != '='))
! p++;
! if(p && strlen(p)) {
! int param_num = 0;
! *p++ = '\0';
!
! while(pobj.properties_names[param_num]
! && strcmp(pobj.properties_names[param_num], param))
! param_num++;
!
! if(pobj.properties_names[param_num]) {
! pobj.param = pobj.descr->parameter;
! pobj.param += param_num;
! pobj.readonly = pobj.param->readonly;
!
! switch(pobj.param->type) {
! case POST_PARAM_TYPE_INT:
! if(!pobj.readonly) {
! *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10);
! _pplugin_update_parameter(&pobj);
! }
! break;
!
! case POST_PARAM_TYPE_DOUBLE:
! if(!pobj.readonly) {
! *(double *)(pobj.param_data + pobj.param->offset) = strtod(p, &p);
! _pplugin_update_parameter(&pobj);
! }
! break;
!
! case POST_PARAM_TYPE_CHAR:
! case POST_PARAM_TYPE_STRING:
! if(!pobj.readonly) {
! if(pobj.param->type == POST_PARAM_TYPE_CHAR) {
! int maxlen = pobj.param->size / sizeof(char);
! snprintf((char *)(pobj.param_data + pobj.param->offset), maxlen, "%s", p);
! _pplugin_update_parameter(&pobj);
}
- else
- fprintf(stderr, "parameter type POST_PARAM_TYPE_STRING) not supported yet.\n");
- }
- break;
-
- case POST_PARAM_TYPE_STRINGLIST: // unsupported */
- if(!pobj.readonly)
- fprintf(stderr, "parameter type POST_PARAM_TYPE_STRINGLIST not supported yet.\n");
- break;
-
- case POST_PARAM_TYPE_BOOL:
- if(!pobj.readonly) {
- *(int *)(pobj.param_data + pobj.param->offset) = ((int) strtol(p, &p, 10)) ? 1 : 0;
- _pplugin_update_parameter(&pobj);
}
- break;
}
}
}
! }
!
! i = 0;
!
! while(pobj.properties_names[i]) {
! free(pobj.properties_names[i]);
! i++;
}
-
- free(pobj.properties_names);
}
! free(pobj.param_data);
}
}
}
}
static void _pplugin_unwire(void) {
xine_post_out_t *vo_source;
!
vo_source = xine_get_video_source(fbxine.stream);
(void) xine_post_wire_video_port(vo_source, fbxine.video_port);
/* Waiting a small chunk of time helps to avoid crashing */
xine_usec_sleep(500000);
! }
!
! void pplugin_rewire_posts(void) {
! _pplugin_unwire();
- if(fbxine.post_elements_num) {
! if(1) {
! xine_post_out_t *vo_source;
! int i = 0;
! for(i = (fbxine.post_elements_num - 1); i >= 0; i--) {
! const char *const *outs = xine_post_list_outputs(fbxine.post_elements[i]->post);
! const xine_post_out_t *vo_out = xine_post_output(fbxine.post_elements[i]->post, (char *) *outs);
! if(i == (fbxine.post_elements_num - 1)) {
! xine_post_wire_video_port((xine_post_out_t *) vo_out, fbxine.video_port);
! }
! else {
! const xine_post_in_t *vo_in = xine_post_input(fbxine.post_elements[i + 1]->post, "video");
! int err;
!
! err = xine_post_wire((xine_post_out_t *) vo_out, (xine_post_in_t *) vo_in);
! }
}
-
- vo_source = xine_get_video_source(fbxine.stream);
- xine_post_wire_video_port(vo_source, fbxine.post_elements[0]->post->video_input[0]);
}
}
}
/* end of post.c */
--- 87,444 ----
pobj->api->get_parameters(pobj->post, pobj->param_data);
}
! /* -post <name>:option1=value1,option2=value2... */
! static post_element_t **pplugin_parse_and_load(const char *pchain, int *post_elements_num) {
! post_element_t **post_elements = NULL;
! char *post_chain;
!
! *post_elements_num = 0;
!
! if(pchain && strlen(pchain)) {
! char *p;
! xine_strdupa(post_chain, pchain);
! while((p = xine_strsep(&post_chain, ";"))) {
! if(p && strlen(p)) {
! char *plugin, *args = NULL;
! xine_post_t *post;
!
! while(*p == ' ')
! p++;
!
! plugin = strdup(p);
!
! if((p = strchr(plugin, ':')))
! *p++ = '\0';
!
! if(p && (strlen(p) > 1))
! args = p;
!
! post = xine_post_init(fbxine.xine, plugin, 0, &fbxine.audio_port, &fbxine.video_port);
!
! if(post) {
! post_object_t pobj;
!
! if(!(*post_elements_num))
! post_elements = (post_element_t **) xine_xmalloc(sizeof(post_element_t *) * 2);
! else
! post_elements = (post_element_t **)
! realloc(post_elements, sizeof(post_element_t *) * ((*post_elements_num) + 2));
! post_elements[(*post_elements_num)] = (post_element_t *)
! xine_xmalloc(sizeof(post_element_t));
! post_elements[(*post_elements_num)]->post = post;
! post_elements[(*post_elements_num)]->name = strdup(plugin);
! (*post_elements_num)++;
! post_elements[(*post_elements_num)] = NULL;
!
! memset(&pobj, 0, sizeof(post_object_t));
! pobj.post = post;
!
! if(__pplugin_retrieve_parameters(&pobj)) {
! int i;
! if(pobj.properties_names && args) {
! char *param;
! while((param = xine_strsep(&args, ",")) != NULL) {
! p = param;
!
! while((*p != '\0') && (*p != '='))
! p++;
!
! if(p && strlen(p)) {
! int param_num = 0;
!
! *p++ = '\0';
!
! while(pobj.properties_names[param_num]
! && strcasecmp(pobj.properties_names[param_num], param))
! param_num++;
!
! if(pobj.properties_names[param_num]) {
!
! pobj.param = pobj.descr->parameter;
! pobj.param += param_num;
! pobj.readonly = pobj.param->readonly;
!
! switch(pobj.param->type) {
! case POST_PARAM_TYPE_INT:
! if(!pobj.readonly) {
! if(pobj.param->enum_values) {
! char **values = pobj.param->enum_values;
! int i = 0;
!
! while(values[i]) {
! if(!strcasecmp(values[i], p)) {
! *(int *)(pobj.param_data + pobj.param->offset) = i;
! break;
! }
! i++;
! }
!
! if( !values[i] )
! *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10);
! } else {
! *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10);
! }
! _pplugin_update_parameter(&pobj);
! }
! break;
!
! case POST_PARAM_TYPE_DOUBLE:
! if(!pobj.readonly) {
! *(double *)(pobj.param_data + pobj.param->offset) = strtod(p, &p);
! _pplugin_update_parameter(&pobj);
! }
! break;
!
! case POST_PARAM_TYPE_CHAR:
! case POST_PARAM_TYPE_STRING:
! if(!pobj.readonly) {
! if(pobj.param->type == POST_PARAM_TYPE_CHAR) {
! int maxlen = pobj.param->size / sizeof(char);
!
! snprintf((char *)(pobj.param_data + pobj.param->offset), maxlen, "%s", p);
! _pplugin_update_parameter(&pobj);
! }
! else
! fprintf(stderr, "parameter type POST_PARAM_TYPE_STRING not supported yet.\n");
! }
! break;
! case POST_PARAM_TYPE_STRINGLIST: /* unsupported */
! if(!pobj.readonly)
! fprintf(stderr, "parameter type POST_PARAM_TYPE_STRINGLIST not supported yet.\n");
! break;
!
! case POST_PARAM_TYPE_BOOL:
! if(!pobj.readonly) {
! *(int *)(pobj.param_data + pobj.param->offset) = ((int) strtol(p, &p, 10)) ? 1 : 0;
! _pplugin_update_parameter(&pobj);
! }
! break;
}
}
}
+ }
+
+ i = 0;
+
+ while(pobj.properties_names[i]) {
+ free(pobj.properties_names[i]);
+ i++;
}
+
+ free(pobj.properties_names);
}
!
! free(pobj.param_data);
}
}
! free(plugin);
}
}
}
+
+ return post_elements;
+ }
+
+
+ void pplugin_parse_and_store_post(const char *post_chain) {
+ post_element_t **posts = NULL;
+ int num;
+
+ if((posts = pplugin_parse_and_load(post_chain, &num))) {
+ if(fbxine.post_elements_num) {
+ int i;
+ int ptot = fbxine.post_elements_num + num;
+
+ fbxine.post_elements = (post_element_t **) realloc(fbxine.post_elements,
+ sizeof(post_element_t *) * (ptot + 1));
+ for(i = fbxine.post_elements_num; i < ptot; i++)
+ fbxine.post_elements[i] = posts[i - fbxine.post_elements_num];
+
+ fbxine.post_elements[i] = NULL;
+ fbxine.post_elements_num += num;
+
+ }
+ else {
+ fbxine.post_elements = posts;
+ fbxine.post_elements_num = num;;
+ }
+ }
+
}
static void _pplugin_unwire(void) {
xine_post_out_t *vo_source;
! int paused = 0;
!
vo_source = xine_get_video_source(fbxine.stream);
+
+ if((paused = (xine_get_param(fbxine.stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE)))
+ xine_set_param(fbxine.stream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_4);
+
(void) xine_post_wire_video_port(vo_source, fbxine.video_port);
+
+ if(paused)
+ xine_set_param(fbxine.stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
+
/* Waiting a small chunk of time helps to avoid crashing */
xine_usec_sleep(500000);
!
! }
! void _pplugin_rewire_from_post_elements(post_element_t **post_elements, int post_elements_num) {
!
! if(post_elements_num) {
! xine_post_out_t *vo_source;
! int i = 0;
! int paused = 0;
!
! if((paused = (xine_get_param(fbxine.stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE)))
! xine_set_param(fbxine.stream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_4);
!
! for(i = (post_elements_num - 1); i >= 0; i--) {
! const char *const *outs = xine_post_list_outputs(post_elements[i]->post);
! const xine_post_out_t *vo_out = xine_post_output(post_elements[i]->post, (char *) *outs);
! if(i == (post_elements_num - 1)) {
! xine_post_wire_video_port((xine_post_out_t *) vo_out, fbxine.video_port);
! }
! else {
! const xine_post_in_t *vo_in = xine_post_input(post_elements[i + 1]->post, "video");
! int err;
!
! err = xine_post_wire((xine_post_out_t *) vo_out, (xine_post_in_t *) vo_in);
}
}
+
+ vo_source = xine_get_video_source(fbxine.stream);
+ xine_post_wire_video_port(vo_source, post_elements[0]->post->video_input[0]);
+
+ if(paused)
+ xine_set_param(fbxine.stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
+
}
}
+ static post_element_t **_pplugin_join_deinterlace_and_post_elements(int *post_elements_num) {
+ post_element_t **post_elements;
+ int i, j;
+
+ *post_elements_num = 0;
+ if( fbxine.post_enable )
+ *post_elements_num += fbxine.post_elements_num;
+ if( fbxine.deinterlace_enable )
+ *post_elements_num += fbxine.deinterlace_elements_num;
+
+ if( *post_elements_num == 0 )
+ return NULL;
+
+ post_elements = (post_element_t **)
+ xine_xmalloc(sizeof(post_element_t *) * (*post_elements_num));
+
+ for( i = 0; fbxine.deinterlace_enable && i < fbxine.deinterlace_elements_num; i++ ) {
+ post_elements[i] = fbxine.deinterlace_elements[i];
+ }
+
+ for( j = 0; fbxine.post_enable && j < fbxine.post_elements_num; j++ ) {
+ post_elements[i+j] = fbxine.post_elements[j];
+ }
+
+ return post_elements;
+ }
+
+ static void _pplugin_rewire(void) {
+
+ static post_element_t **post_elements;
+ int post_elements_num;
+
+ post_elements = _pplugin_join_deinterlace_and_post_elements(&post_elements_num);
+
+ if( post_elements ) {
+ _pplugin_rewire_from_post_elements(post_elements, post_elements_num);
+
+ free(post_elements);
+ }
+ }
+
+
+
+ #define DEFAULT_DEINTERLACER "tvtime:method=Linear,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1"
+
+ static void post_deinterlace_plugin_cb(void *data, xine_cfg_entry_t *cfg) {
+ post_element_t **posts = NULL;
+ int num, i;
+
+ fbxine.deinterlace_plugin = cfg->str_value;
+
+ if(fbxine.deinterlace_enable)
+ _pplugin_unwire();
+
+ for(i = 0; i < fbxine.deinterlace_elements_num; i++) {
+ xine_post_dispose(fbxine.xine, fbxine.deinterlace_elements[i]->post);
+ free(fbxine.deinterlace_elements[i]->name);
+ free(fbxine.deinterlace_elements[i]);
+ }
+
+ SAFE_FREE(fbxine.deinterlace_elements);
+ fbxine.deinterlace_elements_num = 0;
+
+ if((posts = pplugin_parse_and_load(fbxine.deinterlace_plugin, &num))) {
+ fbxine.deinterlace_elements = posts;
+ fbxine.deinterlace_elements_num = num;
+ }
+
+ if(fbxine.deinterlace_enable)
+ _pplugin_rewire();
+ }
+
+
+
+ void post_deinterlace_init(const char *deinterlace_post) {
+ post_element_t **posts = NULL;
+ int num;
+
+ fbxine.deinterlace_plugin = DEFAULT_DEINTERLACER;
+
+ if((posts = pplugin_parse_and_load((deinterlace_post && strlen(deinterlace_post)) ?
+ deinterlace_post : fbxine.deinterlace_plugin, &num))) {
+ fbxine.deinterlace_elements = posts;
+ fbxine.deinterlace_elements_num = num;
+ }
+ }
+
+
+ void post_deinterlace(void) {
+
+ if( !fbxine.deinterlace_elements_num ) {
+ /* fallback to the old method */
+ xine_set_param(fbxine.stream, XINE_PARAM_VO_DEINTERLACE,
+ fbxine.deinterlace_enable);
+ }
+ else {
+ _pplugin_unwire();
+ _pplugin_rewire();
+ }
+ }
+
+ void pplugin_rewire_posts(void) {
+
+ _pplugin_unwire();
+ _pplugin_rewire();
+ }
/* end of post.c */
*** ../fb.orig/post.h Sun Jul 27 19:40:36 2003
--- post.h Sun Nov 30 20:07:09 2003
***************
*** 24,29 ****
--- 24,31 ----
void pplugin_rewire_posts(void);
void pplugin_parse_and_store_post(const char *post);
+ void post_deinterlace(void);
+ void post_deinterlace_init(const char *deinterlace_post);
#endif
--
I feel like a genocidal maniac when emacs asks me if I want to kill
10789 characters.