Index: libmpcodecs/vf_shmemin.c
===================================================================
--- libmpcodecs/vf_shmemin.c	(revision 0)
+++ libmpcodecs/vf_shmemin.c	(revision 0)
@@ -0,0 +1,595 @@
+/*
+ *  Import video frame from shared memory
+ *
+ *  Based on vf_bmovl.c
+ *
+ *  Copyright (C) 2007 Attila Ötvös <attila@onebithq.com>
+ *
+ *  MPlayer is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  MPlayer 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with MPlayer; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include "config.h"
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "img_format.h"
+#include "vf_scale.h"
+
+#include "mp_msg.h"
+#include "libavutil/common.h"
+
+#include "libvo/fastmemcpy.h"
+
+#include "m_option.h"
+#include "m_struct.h"
+
+#include "stream/stream.h"
+#include "libmpdemux/demuxer.h"
+
+typedef struct vf_cmd_s {
+    double spts; // start pts
+    double epts; // end pts
+    int on;	// on/off
+    int sa;	// start alpha
+    int sx;	// start x
+    int sy;	// start y
+    int sw;	// start width
+    int sh;	// start height
+    double sz;	// start zoom
+    int ea;	// end alpha
+    int ex;	// end x
+    int ey;	// end y
+    int ew;	// end width
+    int eh;	// end height
+    double ez;	// end zoom
+    void *next;
+} vf_cmd_t;
+
+static struct vf_priv_s {
+    int on, x, y, w, h, a;
+    int ow, oh;
+    double z, pts;
+    int sw, sh, dw, dh;
+    int fmt, sfmt;
+
+    mp_image_t *src;
+    mp_image_t *dst;
+    int shmemid;
+    stream_t* shmem_stream;
+    struct SwsContext *ctx;
+    uint8_t *rbuffer;
+    int total;
+    char *cmdfile;
+    vf_cmd_t *cmd;
+    vf_cmd_t *lastcmd;
+} const vf_priv_dflt = {
+    1, 0, 0, 0, 0, -1,
+    0, 0,
+    -1.0, MP_NOPTS_VALUE,
+    0, 0, 0, 0,
+    0, 0,
+    NULL,
+    NULL,
+    0,
+    NULL,
+    NULL,
+    NULL,
+    0,
+    NULL,
+    NULL,
+    NULL
+};
+
+#define BUFFER_SIZE	8192
+
+static void setcmd(vf_cmd_t *cmd, int n, char *value) {
+    int i;
+
+    while (isspace(*value))
+	++value;
+    if(*value=='\0') return;
+    for(i=strlen(value);i>0;i--)
+        if(isspace(*value)) *value=0; else break;
+    switch (n) {
+    case 0: cmd->spts=atof(value); break;
+    case 1: cmd->epts=atof(value); break;
+    case 2: cmd->on=atoi(value); break;
+    case 3: cmd->sa=atoi(value); break;
+    case 4: cmd->sx=atoi(value); break;
+    case 5: cmd->sy=atoi(value); break;
+    case 6: cmd->sw=atoi(value); break;
+    case 7: cmd->sh=atoi(value); break;
+    case 8: cmd->sz=atof(value); break;
+    case 9: cmd->ea=atoi(value); break;
+    case 10: cmd->ex=atoi(value); break;
+    case 11: cmd->ey=atoi(value); break;
+    case 12: cmd->ew=atoi(value); break;
+    case 13: cmd->eh=atoi(value); break;
+    case 14: cmd->ez=atof(value); break;
+    }
+}
+
+static int cmd_parser(char *fname, struct vf_instance_s *vf) {
+    FILE *fh;
+    char *line, *buffer, *p;
+    int n;
+    vf_cmd_t *tmpcmd;
+    vf_cmd_t *lastcmd = NULL;
+    
+    if(NULL==(fh=fopen(fname,"rb"))) return 0;
+    buffer=malloc(BUFFER_SIZE+1);
+    while (!feof(fh)) {
+	memset(buffer,0,BUFFER_SIZE+1);
+	fgets(buffer,BUFFER_SIZE,fh);
+	line = buffer;
+	while (isspace(*line))
+	    ++line;
+	if (*line == '\0' || *line == '#')
+	    continue;
+	if ((p=strchr(line,'\n'))) *p=0;
+	tmpcmd=malloc(sizeof(vf_cmd_t));
+	tmpcmd->spts=tmpcmd->epts=tmpcmd->sz=tmpcmd->ez=-1.0;
+	tmpcmd->on=-1;
+	tmpcmd->sa=tmpcmd->sx=tmpcmd->sy=tmpcmd->sh=tmpcmd->sw=-1;
+	tmpcmd->ea=tmpcmd->ex=tmpcmd->ey=tmpcmd->eh=tmpcmd->ew=-1;
+	n=0;
+	while ((p=strchr(line,','))) {
+	    *p++=0;
+	    setcmd(tmpcmd,n,line);
+	    n++;
+	    line=p;
+	}
+	setcmd(tmpcmd,n,line);
+
+mp_msg(MSGT_VFILTER, MSGL_V, "spts: %8.3f epts: %8.3f on: %d sa: %d  sx: %d  sy: %d  sw: %d  sh: %d  sz: %8.3f ea: %d  ex: %d  ey: %d  ew: %d  eh: %d  ez: %8.3f \n",
+	tmpcmd->spts, tmpcmd->epts, tmpcmd->on,
+	tmpcmd->sa,tmpcmd->sx,tmpcmd->sy,tmpcmd->sw,tmpcmd->sh,tmpcmd->sz,
+	tmpcmd->ea,tmpcmd->ex,tmpcmd->ey,tmpcmd->ew,tmpcmd->eh,tmpcmd->ez);
+
+	if(!vf->priv->cmd) 
+	    vf->priv->cmd=tmpcmd;
+	else
+	    lastcmd->next=tmpcmd;
+	lastcmd=tmpcmd;	
+    }
+    free(buffer);
+    fclose(fh);
+    return 1;
+}
+
+static void cmd_free(struct vf_instance_s *vf) {
+    vf_cmd_t *tmpcmd;
+    vf_cmd_t *nextcmd;
+    
+    tmpcmd=vf->priv->cmd;
+    while (tmpcmd) {
+    	nextcmd=tmpcmd->next;
+	free(tmpcmd);
+	tmpcmd=nextcmd;
+    }
+    vf->priv->cmd=NULL;
+}
+
+static vf_cmd_t* cmd_seek(double pts, struct vf_instance_s *vf) {
+    vf_cmd_t *tmpcmd = vf->priv->cmd;
+    vf_cmd_t *retcmd = NULL;
+    
+    while (tmpcmd) {
+    	if(tmpcmd->spts<=pts)
+	    if(!retcmd || retcmd->spts<tmpcmd->spts)
+	    	retcmd=tmpcmd;
+    	tmpcmd=tmpcmd->next;
+    }
+    return retcmd;
+}
+
+#define CMD_RATE_FLAG_NONE	0
+#define CMD_RATE_FLAG_MIN_HALF	1
+#define CMD_RATE_FLAG_MAX_HALF	2
+
+static int cmd_set_rate_i(int s, int e, double rate, int flag) {
+    double ds=s, de=e, dr;
+    int ret;
+    
+    if(s==e) return s;
+    dr=(de-ds)*rate+ds;
+    ret=round(dr);
+    switch (flag) {
+    case CMD_RATE_FLAG_MIN_HALF: ret &= ~1; break;
+    case CMD_RATE_FLAG_MAX_HALF: ret = (ret+1)&~1; break;
+    }
+    return ret;
+}
+static void cmd_set(double pts, struct vf_instance_s *vf, vf_cmd_t *forcecmd) {
+    vf_cmd_t *cmd = NULL;
+    vf_cmd_t tmpcmd;
+    double rate;
+    
+    if (pts==MP_NOPTS_VALUE) pts=vf->priv->pts;
+    if (pts==MP_NOPTS_VALUE) return;
+    if (forcecmd)
+    	cmd = forcecmd;
+    else
+    	cmd = cmd_seek(pts,vf);
+    if (!cmd) return;
+    if (vf->priv->lastcmd && vf->priv->lastcmd!=cmd && !forcecmd)
+    	cmd_set(pts,vf,vf->priv->lastcmd);
+    tmpcmd=*cmd;
+    vf->priv->lastcmd=cmd;
+    if (tmpcmd.on!=-1) vf->priv->on=tmpcmd.on;
+    if (tmpcmd.sa==-1) tmpcmd.sa=vf->priv->a;
+    if (tmpcmd.sx==-1) tmpcmd.sx=vf->priv->x;
+    if (tmpcmd.sy==-1) tmpcmd.sy=vf->priv->y;
+    if (tmpcmd.sw==-1) tmpcmd.sw=vf->priv->w;
+    if (tmpcmd.sh==-1) tmpcmd.sh=vf->priv->h;
+    if (tmpcmd.sz==-1.0) tmpcmd.sz=vf->priv->z;
+    if (tmpcmd.ea==-1) tmpcmd.ea=tmpcmd.sa;
+    if (tmpcmd.ex==-1) tmpcmd.ex=tmpcmd.sx;
+    if (tmpcmd.ey==-1) tmpcmd.ey=tmpcmd.sy;
+    if (tmpcmd.ew==-1) tmpcmd.ew=tmpcmd.sw;
+    if (tmpcmd.eh==-1) tmpcmd.eh=tmpcmd.sh;
+    if (tmpcmd.ez==-1.0) tmpcmd.ez=tmpcmd.sz;
+    *cmd=tmpcmd;
+    if (pts>tmpcmd.epts || tmpcmd.epts==-1.0 || tmpcmd.spts==-1.0) 
+    	rate=1.0;
+    else
+    	rate=(pts-tmpcmd.spts)/(tmpcmd.epts-tmpcmd.spts);
+    if (rate>1.0) rate=1.0;
+    vf->priv->a=cmd_set_rate_i(tmpcmd.sa,tmpcmd.ea,rate,CMD_RATE_FLAG_NONE);
+    vf->priv->x=cmd_set_rate_i(tmpcmd.sx,tmpcmd.ex,rate,CMD_RATE_FLAG_MIN_HALF);
+    vf->priv->y=cmd_set_rate_i(tmpcmd.sy,tmpcmd.ey,rate,CMD_RATE_FLAG_MIN_HALF);
+    vf->priv->w=cmd_set_rate_i(tmpcmd.sw,tmpcmd.ew,rate,CMD_RATE_FLAG_MAX_HALF);
+    vf->priv->h=cmd_set_rate_i(tmpcmd.sh,tmpcmd.eh,rate,CMD_RATE_FLAG_MAX_HALF);
+    vf->priv->z=(tmpcmd.ez-tmpcmd.sz)*rate+tmpcmd.sz;
+}
+
+static int imgsize(mp_image_t *mpi) {
+
+    switch(mpi->imgfmt){
+    case IMGFMT_I420:
+    case IMGFMT_IYUV:
+    case IMGFMT_YV12:
+        return mpi->w*mpi->h+2*(mpi->w>>1)*(mpi->h>>1);
+    case IMGFMT_YUY2:
+    case IMGFMT_UYVY:
+        return mpi->w*mpi->h*2;
+    case IMGFMT_Y800:
+    case IMGFMT_Y8:
+        return mpi->w*mpi->h;
+    case IMGFMT_BGR24:
+    case IMGFMT_RGB24:
+        return mpi->w * mpi->h * ((IMGFMT_RGB_DEPTH(mpi->imgfmt) + 7) >> 3);
+    }
+    return 0;
+}
+
+static int imgscalex(mp_image_t *mpi) {
+
+    switch(mpi->imgfmt){
+    case IMGFMT_YUY2:
+    case IMGFMT_UYVY:
+        return 2;
+    case IMGFMT_BGR24:
+    case IMGFMT_RGB24:
+        return 3;
+    }
+    return 1;
+}
+
+
+static int query_format(struct vf_instance_s* vf, unsigned int fmt) {
+    switch (fmt) {
+    case IMGFMT_YV12:
+    case IMGFMT_I420:
+    case IMGFMT_IYUV:
+    case IMGFMT_Y800:
+    case IMGFMT_Y8:
+    case IMGFMT_BGR24:
+    case IMGFMT_RGB24:
+    case IMGFMT_YUY2:
+    case IMGFMT_UYVY:
+        return VFCAP_CSP_SUPPORTED;
+    }
+    return 0;
+}
+
+static int set_scaler(struct vf_instance_s* vf) {
+    if (vf->priv->ctx) sws_freeContext(vf->priv->ctx);
+    vf->priv->ctx = NULL;
+    if (vf->priv->dw<8 || vf->priv->dh<8) return;
+    vf->priv->ctx = sws_getContextFromCmdLine(vf->priv->sw, vf->priv->sh,
+                        vf->priv->sfmt,
+                        vf->priv->dw, vf->priv->dh, vf->priv->fmt);
+}
+
+static int config(struct vf_instance_s* vf,
+       int width, int height, int d_width, int d_height,
+       unsigned int flags, unsigned int outfmt) {
+
+    vf->priv->fmt = outfmt;
+    set_scaler(vf);
+    return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
+}
+
+static void uninit(struct vf_instance_s *vf) {
+    if (vf->priv) {
+        if (vf->priv->shmem_stream) free_stream(vf->priv->shmem_stream);
+        if (vf->priv->src) free_mp_image(vf->priv->src);
+        if (vf->priv->dst) free_mp_image(vf->priv->dst);
+        if (vf->priv->ctx) sws_freeContext(vf->priv->ctx);
+	cmd_free(vf);
+        free(vf->priv);
+    }
+}
+
+static void put_rawimage(struct vf_instance_s* vf, mp_image_t* dmpi,
+    mp_image_t *mpi) {
+
+    int ypos, dypos;
+
+    if (vf->priv->x==0 && vf->priv->y==0) {
+        memcpy_pic( dmpi->planes[0], mpi->planes[0], mpi->w * imgscalex(mpi),
+                    mpi->h, dmpi->stride[0], mpi->stride[0] );
+        if (mpi->planes[1])
+            memcpy_pic( dmpi->planes[1], mpi->planes[1], mpi->chroma_width,
+                        mpi->chroma_height, dmpi->stride[1], mpi->stride[1] );
+        if (mpi->planes[2])
+            memcpy_pic( dmpi->planes[2], mpi->planes[2], mpi->chroma_width,
+                        mpi->chroma_height, dmpi->stride[2], mpi->stride[2] );
+    } else {
+    dypos = 0;
+    for( ypos = 0 ; ypos < mpi->h ; ypos++ ) {
+        dypos = vf->priv->y + ypos;
+        fast_memcpy( dmpi->planes[0] +
+                    (dypos*dmpi->stride[0]) + vf->priv->x * imgscalex(mpi),
+                    mpi->planes[0] + (ypos*mpi->stride[0]),
+                    mpi->w * imgscalex(mpi) );
+        if (ypos%2 && mpi->chroma_height) {
+            fast_memcpy( dmpi->planes[1] + ((dypos/2)*dmpi->stride[1]) +
+                        (vf->priv->x/2),
+                        mpi->planes[1] + (((ypos/2)*(mpi->w)/2)),
+                        (mpi->w)/2 );
+            fast_memcpy( dmpi->planes[2] + ((dypos/2)*dmpi->stride[2]) +
+                        (vf->priv->x/2),
+                        mpi->planes[2] + (((ypos/2)*(mpi->w)/2)),
+                        (mpi->w)/2 );
+        }
+        if (mpi->chroma_height==0) {
+            if (mpi->planes[1])
+                fast_memcpy( dmpi->planes[1] + (dypos*dmpi->stride[1]) +
+                                vf->priv->x,
+                                mpi->planes[1] + (ypos*mpi->w),
+                                mpi->w );
+            if (mpi->planes[2])
+                fast_memcpy( dmpi->planes[2] + (dypos*dmpi->stride[2]) +
+                                vf->priv->x,
+                                mpi->planes[2] + (ypos*mpi->w),
+                                mpi->w );
+            }
+        }
+    }
+}
+
+static void cpy_pic_alpha(unsigned char *dst, unsigned char *src, int len, int alpha) {
+    int i;
+    for(i=0;i<len;i++) dst[i]=(dst[i]*(255-alpha)+src[i]*alpha)/255;
+}
+
+static void put_rawimage_alpha(struct vf_instance_s* vf, mp_image_t* dmpi,
+    mp_image_t *mpi, int alpha) {
+
+    int ypos, dypos;
+
+    dypos = 0;
+    for( ypos = 0 ; ypos < mpi->h ; ypos++ ) {
+        dypos = vf->priv->y + ypos;
+        cpy_pic_alpha( dmpi->planes[0] +
+                    (dypos*dmpi->stride[0]) + vf->priv->x * imgscalex(mpi),
+                    mpi->planes[0] + (ypos*mpi->stride[0]),
+                    mpi->w * imgscalex(mpi) ,
+		    alpha);
+        if (ypos%2 && mpi->chroma_height) {
+            cpy_pic_alpha( dmpi->planes[1] + ((dypos/2)*dmpi->stride[1]) +
+                        (vf->priv->x/2),
+                        mpi->planes[1] + (((ypos/2)*(mpi->w)/2)),
+                        (mpi->w)/2,
+			alpha );
+            cpy_pic_alpha( dmpi->planes[2] + ((dypos/2)*dmpi->stride[2]) +
+                        (vf->priv->x/2),
+                        mpi->planes[2] + (((ypos/2)*(mpi->w)/2)),
+                        (mpi->w)/2,
+			alpha );
+        }
+        if (mpi->chroma_height==0) {
+            if (mpi->planes[1])
+                cpy_pic_alpha( dmpi->planes[1] + (dypos*dmpi->stride[1]) +
+                                vf->priv->x,
+                                mpi->planes[1] + (ypos*mpi->w),
+                                mpi->w,
+				alpha );
+            if (mpi->planes[2])
+                cpy_pic_alpha( dmpi->planes[2] + (dypos*dmpi->stride[2]) +
+                                vf->priv->x,
+                                mpi->planes[2] + (ypos*mpi->w),
+                                mpi->w,
+				alpha );
+            }
+        }
+}
+
+static int put_image(struct vf_instance_s* vf, mp_image_t* mpi, double pts) {
+    int total;
+    mp_image_t* dmpi;
+
+    dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_TEMP,
+                        MP_IMGFLAG_ACCEPT_STRIDE |
+                        MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
+                        mpi->w, mpi->h);
+
+    memcpy_pic( dmpi->planes[0], mpi->planes[0], mpi->width, mpi->height,
+                dmpi->stride[0], mpi->stride[0] );
+    memcpy_pic( dmpi->planes[1], mpi->planes[1], mpi->chroma_width,
+                mpi->chroma_height, dmpi->stride[1], mpi->stride[1] );
+    memcpy_pic( dmpi->planes[2], mpi->planes[2], mpi->chroma_width,
+                mpi->chroma_height, dmpi->stride[2], mpi->stride[2] );
+
+    cmd_set(pts,vf,NULL);
+    if (!vf->priv->on) 
+	return  vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+    if(vf->priv->ow!=vf->priv->w || vf->priv->oh!=vf->priv->h) {
+        vf->priv->dw = vf->priv->w;
+    	vf->priv->dh = vf->priv->h;
+        vf->priv->ow = vf->priv->w;
+    	vf->priv->oh = vf->priv->h;
+    	vf->priv->dw = (vf->priv->dw+1)&~1;
+    	vf->priv->dh = (vf->priv->dh+1)&~1;
+	set_scaler(vf);
+        if (vf->priv->dst) free_mp_image(vf->priv->dst);
+	vf->priv->dst=NULL;
+    }
+    if (vf->priv->x+vf->priv->w>mpi->w && vf->priv->w<mpi->w)
+        vf->priv->x = (mpi->w-vf->priv->w) & ~1;
+    if (vf->priv->y+vf->priv->h>mpi->h && vf->priv->h<mpi->h)
+        vf->priv->y = (mpi->h-vf->priv->h) & ~1;
+    if (!vf->priv->ctx)
+        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+    if (vf->priv->x+vf->priv->w>mpi->w)
+        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+    if (vf->priv->y+vf->priv->h>mpi->h)
+        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+    if (!vf->priv->shmem_stream)
+        return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+    if (!vf->priv->dst)
+        vf->priv->dst = alloc_mpi(vf->priv->dw, vf->priv->dh, vf->priv->fmt);
+    if (!vf->priv->src)
+        vf->priv->src = alloc_mpi(vf->priv->sw, vf->priv->sh, vf->priv->sfmt);
+
+    if (vf->priv->total==0) {
+        vf->priv->total = imgsize(vf->priv->src);
+        vf->priv->rbuffer = vf->priv->src->planes[0];
+    }
+    total=stream_read(vf->priv->shmem_stream, vf->priv->rbuffer, vf->priv->total);
+    vf->priv->rbuffer+=total;
+    vf->priv->total-=total;
+    if (vf->priv->total>0) return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+
+    sws_scale_ordered(vf->priv->ctx,
+                      vf->priv->src->planes,
+                      vf->priv->src->stride,
+                      0,
+                      vf->priv->src->h,
+                      vf->priv->dst->planes,
+                      vf->priv->dst->stride);
+
+    if(vf->priv->a>0 && vf->priv->a<255)
+    	put_rawimage_alpha(vf, dmpi, vf->priv->dst,vf->priv->a);
+    if(vf->priv->a>=255)
+    	put_rawimage(vf, dmpi, vf->priv->dst);
+
+    return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE);
+} // put_image
+
+static int control(struct vf_instance_s* vf, int request, void* data) {
+
+    switch(request){
+    case VFCTRL_SET_PTS:
+        vf->priv->pts=*(float*)data;
+        break;
+    }
+    return vf_next_control(vf, request, data);
+}
+
+
+static int vf_open(vf_instance_t* vf, char* args) {
+    char filename[64];
+    int file_format;
+
+    vf->config = config;
+    vf->control = control;
+    vf->put_image = put_image;
+    vf->query_format = query_format;
+    vf->uninit = uninit;
+
+    snprintf(filename,sizeof(filename),"shmem://%d",vf->priv->shmemid);
+    if (NULL==(vf->priv->shmem_stream = open_stream(filename,0,&file_format))) {
+        return 0;
+        }
+    if (file_format!=DEMUXER_TYPE_RAWVIDEO) {
+        free_stream(vf->priv->shmem_stream);
+        vf->priv->shmem_stream=NULL;
+        return 0;
+        }
+    stream_control(vf->priv->shmem_stream, STREAM_CTRL_GET_WIDTH, &vf->priv->sw);
+    stream_control(vf->priv->shmem_stream, STREAM_CTRL_GET_HEIGHT, &vf->priv->sh);
+    stream_control(vf->priv->shmem_stream, STREAM_CTRL_GET_FORMAT, &vf->priv->sfmt);
+    if (vf->priv->sw==0 || vf->priv->sh==0 || vf->priv->sfmt==0) {
+        free_stream(vf->priv->shmem_stream);
+        vf->priv->shmem_stream = NULL;
+        return 0;
+    }
+    vf->priv->x &= ~1;
+    vf->priv->y &= ~1;
+    if (vf->priv->w==0) vf->priv->w = vf->priv->sw;
+    if (vf->priv->h==0) vf->priv->h = vf->priv->sh;
+    vf->priv->dw = vf->priv->w;
+    vf->priv->dh = vf->priv->h;
+    vf->priv->ow = vf->priv->w;
+    vf->priv->oh = vf->priv->h;
+    vf->priv->dw = (vf->priv->dw+1)&~1;
+    vf->priv->dh = (vf->priv->dh+1)&~1;
+    if (vf->priv->cmdfile) cmd_parser(vf->priv->cmdfile,vf);
+    return 1;
+}
+#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
+static m_option_t vf_opts_fields[] = {
+    {"shmemid", ST_OFF(shmemid), CONF_TYPE_INT, 0 , 0, 0, NULL},
+    {"on", ST_OFF(on), CONF_TYPE_INT, M_OPT_MIN,0 , 0, NULL},
+    {"x", ST_OFF(x), CONF_TYPE_INT, M_OPT_MIN,0 , 0, NULL},
+    {"y", ST_OFF(y), CONF_TYPE_INT, M_OPT_MIN,0 , 0, NULL},
+    {"w", ST_OFF(w), CONF_TYPE_INT, M_OPT_MIN,0 , 0, NULL},
+    {"h", ST_OFF(h), CONF_TYPE_INT, M_OPT_MIN,0 , 0, NULL},
+    {"a", ST_OFF(a), CONF_TYPE_INT, M_OPT_MIN,0 , 0, NULL},
+    {"cmdfile", ST_OFF(cmdfile), CONF_TYPE_STRING, 0 ,0 , 0, NULL},
+    { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+
+static m_struct_t vf_opts = {
+    "shmemin",
+    sizeof(struct vf_priv_s),
+    &vf_priv_dflt,
+    vf_opts_fields
+};
+
+vf_info_t vf_info_shmemin = {
+    "Import video from shared memory",
+    "shmemin",
+    "Otvos Attila",
+    "",
+    vf_open,
+    &vf_opts
+};
Index: libmpcodecs/ve_shmem.c
===================================================================
--- libmpcodecs/ve_shmem.c	(revision 0)
+++ libmpcodecs/ve_shmem.c	(revision 0)
@@ -0,0 +1,160 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "codec-cfg.h"
+#include "stream/stream.h"
+#include "libmpdemux/demuxer.h"
+#include "libmpdemux/stheader.h"
+
+#include "stream/stream.h"
+#include "libmpdemux/muxer.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+
+
+//===========================================================================//
+
+struct vf_priv_s {
+    muxer_stream_t* mux;
+};
+#define mux_v (vf->priv->mux)
+
+static int set_format(struct vf_instance_s *vf, unsigned int fmt) {
+    mux_v->bih->biCompression = fmt;
+    
+    mux_v->bih->biPlanes = 1;
+    if (IMGFMT_IS_RGB(fmt)) {
+	if (IMGFMT_RGB_DEPTH(fmt) < 8 && !(fmt&128))
+	    mux_v->bih->biBitCount = IMGFMT_RGB_DEPTH(fmt);
+	else
+	    mux_v->bih->biBitCount = (IMGFMT_RGB_DEPTH(fmt)+7)&(~7);
+	return 1;
+    }
+    if (IMGFMT_IS_BGR(fmt)) {
+	if (IMGFMT_BGR_DEPTH(fmt) < 8 && !(fmt&128))
+	    mux_v->bih->biBitCount = IMGFMT_BGR_DEPTH(fmt);
+	else
+	    mux_v->bih->biBitCount = (IMGFMT_BGR_DEPTH(fmt)+7)&(~7);
+	return 1;
+    }
+    switch (fmt) {
+    case IMGFMT_I420:
+    case IMGFMT_IYUV:
+    case IMGFMT_YV12:
+    case IMGFMT_411P:
+	mux_v->bih->biPlanes = 3;
+	mux_v->bih->biBitCount = 12;
+	break;
+    case IMGFMT_444P:
+	mux_v->bih->biPlanes = 3;
+	mux_v->bih->biBitCount = 24;
+	break;
+    case IMGFMT_422P:
+	mux_v->bih->biPlanes = 3;
+	mux_v->bih->biBitCount = 16;
+	break;
+    case IMGFMT_IF09:
+	mux_v->bih->biPlanes = 4;
+    case IMGFMT_YVU9:
+	mux_v->bih->biBitCount = 9;
+	break;
+    case IMGFMT_UYVY:
+    case IMGFMT_YUY2:
+	mux_v->bih->biBitCount = 16;
+	break;
+    case IMGFMT_Y8:
+        mux_v->bih->biBitCount = 8;
+        break;
+    default:
+	mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_MPCODECS_OutputWithFourccNotSupported, fmt);
+	mux_v->bih->biCompression = 0;
+	return 0;
+    }
+    return 1;
+}
+
+
+static int config(struct vf_instance_s *vf,
+        int width, int height, int d_width, int d_height,
+	unsigned int flags, unsigned int outfmt)
+{
+    int ret;
+    mux_v->bih->biWidth = width;
+    mux_v->bih->biHeight = height;
+    mux_v->aspect = (float)d_width/d_height;
+    ret = set_format(vf, outfmt);
+    if (!ret) return 0;
+
+    mux_v->bih->biSizeImage = mux_v->bih->biWidth*mux_v->bih->biHeight*mux_v->bih->biBitCount/8;
+    return 1;
+}
+
+static int control(struct vf_instance_s *vf, int request, void *data) {
+    return CONTROL_UNKNOWN;
+}
+
+static int query_format(struct vf_instance_s *vf, unsigned int fmt) {
+    if (IMGFMT_IS_RGB(fmt) || IMGFMT_IS_BGR(fmt))
+	return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
+    switch (fmt) {
+    case IMGFMT_I420:
+    case IMGFMT_IYUV:
+    case IMGFMT_YV12:
+    case IMGFMT_411P:
+    case IMGFMT_444P:
+    case IMGFMT_422P:
+    case IMGFMT_UYVY:
+    case IMGFMT_YUY2:
+    case IMGFMT_YVU9:
+    case IMGFMT_IF09:
+    case IMGFMT_Y8:
+	return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
+    }
+
+    return 0;
+}
+
+static int put_image(struct vf_instance_s *vf, mp_image_t *mpi, double pts) {
+    mux_v->buffer = mpi->planes[0];
+//printf("ve_shmem w: %d h: %d l:%d \n",mpi->width,mpi->height, mpi->width*mpi->height*mux_v->bih->biBitCount/8);
+    muxer_write_chunk(mux_v, mpi->width*mpi->height*mux_v->bih->biBitCount/8, 0x10, pts, pts);
+    return 1;
+}
+
+//===========================================================================//
+
+static int vf_open(vf_instance_t *vf, char* args){
+    vf->config = config;
+    vf->default_caps = VFCAP_CONSTANT;
+    vf->control = control;
+    vf->query_format = query_format;
+    vf->put_image = put_image;
+    vf->default_caps = 0;
+    vf->priv = malloc(sizeof(struct vf_priv_s));
+    memset(vf->priv, 0, sizeof(struct vf_priv_s));
+    vf->priv->mux = (muxer_stream_t*)args;
+    
+    mux_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
+    mux_v->bih->biSize = sizeof(BITMAPINFOHEADER);
+    mux_v->bih->biWidth = 0;
+    mux_v->bih->biHeight = 0;
+printf("muxer shmem open\n");
+    return 1;
+}
+
+vf_info_t ve_info_shmem = {
+    "shmem encoder",
+    "shmem",
+    "Otvos Attila",
+    "Based on raw",
+    vf_open
+};
+
+//===========================================================================//
Index: libmpcodecs/Makefile
===================================================================
--- libmpcodecs/Makefile	(revision 25166)
+++ libmpcodecs/Makefile	(working copy)
@@ -121,6 +121,7 @@
 SRCS_COMMON-$(PNG)                   += vd_mpng.c
 SRCS_COMMON-$(QTX_CODECS)            += ad_qtaudio.c vd_qtvideo.c
 SRCS_COMMON-$(REAL_CODECS)           += ad_realaud.c vd_realvid.c
+SRCS_COMMON-$(SHM)                   += vf_shmemout.c vf_shmemin.c
 SRCS_COMMON-$(SPEEX)                 += ad_speex.c
 SRCS_COMMON-$(WIN32DLL)              += ad_acm.c ad_dmo.c ad_dshow.c ad_twin.c \
                                         vd_dmo.c vd_dshow.c vd_vfw.c vd_vfwex.c
@@ -133,6 +134,8 @@
                 ae_pcm.c \
                 ve.c \
                 ve_raw.c \
+                ae_shmem.c \
+                ve_shmem.c \
 
 SRCS_MENCODER-$(LIBAVCODEC)           += ae_lavc.c ve_lavc.c
 SRCS_MENCODER-$(LIBDV)                += ve_libdv.c
Index: libmpcodecs/ve.c
===================================================================
--- libmpcodecs/ve.c	(revision 25166)
+++ libmpcodecs/ve.c	(working copy)
@@ -17,6 +17,7 @@
 extern vf_info_t ve_info_qtvideo;
 extern vf_info_t ve_info_nuv;
 extern vf_info_t ve_info_x264;
+extern vf_info_t ve_info_shmem;
 
 static vf_info_t* encoder_list[]={
 #ifdef USE_LIBAVCODEC
@@ -41,6 +42,7 @@
 #ifdef HAVE_X264
     &ve_info_x264,
 #endif
+    &ve_info_shmem,
     NULL
 };
 
Index: libmpcodecs/ae_shmem.c
===================================================================
--- libmpcodecs/ae_shmem.c	(revision 0)
+++ libmpcodecs/ae_shmem.c	(revision 0)
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include "m_option.h"
+#include "mp_msg.h"
+#include "libmpdemux/aviheader.h"
+#include "libaf/af_format.h"
+#include "libmpdemux/ms_hdr.h"
+#include "stream/stream.h"
+#include "libmpdemux/muxer.h"
+#include "ae_shmem.h"
+
+
+static int bind_shmem(audio_encoder_t *encoder, muxer_stream_t *mux_a)
+{
+	mux_a->h.dwScale=1;
+	mux_a->h.dwRate=encoder->params.sample_rate;
+	mux_a->wf=malloc(sizeof(WAVEFORMATEX));
+	mux_a->wf->wFormatTag=0x1; // PCM
+	mux_a->wf->nChannels=encoder->params.channels;
+	mux_a->h.dwSampleSize=2*mux_a->wf->nChannels;
+	mux_a->wf->nBlockAlign=mux_a->h.dwSampleSize;
+	mux_a->wf->nSamplesPerSec=mux_a->h.dwRate;
+	mux_a->wf->nAvgBytesPerSec=mux_a->h.dwSampleSize*mux_a->wf->nSamplesPerSec;
+	mux_a->wf->wBitsPerSample=16;
+	mux_a->wf->cbSize=0; // FIXME for l3codeca.acm
+	
+	encoder->input_format = (mux_a->wf->wBitsPerSample==8) ? AF_FORMAT_U8 : AF_FORMAT_S16_LE;
+	encoder->min_buffer_size = 16384;
+	encoder->max_buffer_size = mux_a->wf->nAvgBytesPerSec;
+	
+	return 1;
+}
+
+static int encode_shmem(audio_encoder_t *encoder, uint8_t *dest, void *src, int nsamples, int max_size)
+{
+	max_size = FFMIN(nsamples, max_size);
+	memcpy(dest, src, max_size);
+	return max_size;
+}
+
+static int set_decoded_len(audio_encoder_t *encoder, int len)
+{
+	return len;
+}
+
+static int close_shmem(audio_encoder_t *encoder)
+{
+	return 1;
+}
+
+static int get_frame_size(audio_encoder_t *encoder)
+{
+	return 0;
+}
+
+int mpae_init_shmem(audio_encoder_t *encoder)
+{
+	encoder->params.samples_per_frame = encoder->params.sample_rate;
+	encoder->params.bitrate = encoder->params.sample_rate * encoder->params.channels * 2 * 8;
+	
+	encoder->decode_buffer_size = encoder->params.bitrate / 8;
+	encoder->bind = bind_shmem;
+	encoder->get_frame_size = get_frame_size;
+	encoder->set_decoded_len = set_decoded_len;
+	encoder->encode = encode_shmem;
+	encoder->close = close_shmem;
+	
+	return 1;
+}
+
Index: libmpcodecs/ae_shmem.h
===================================================================
--- libmpcodecs/ae_shmem.h	(revision 0)
+++ libmpcodecs/ae_shmem.h	(revision 0)
@@ -0,0 +1,8 @@
+#ifndef AE_SHMEM_H
+#define AE_SHMEM_H
+
+#include "ae.h"
+
+int mpae_init_shmem(audio_encoder_t *encoder);
+
+#endif
Index: libmpcodecs/ae.c
===================================================================
--- libmpcodecs/ae.c	(revision 25166)
+++ libmpcodecs/ae.c	(working copy)
@@ -50,6 +50,9 @@
 		case ACODEC_PCM:
 			ris = mpae_init_pcm(encoder);
 			break;
+		case ACODEC_SHMEM:
+			ris = mpae_init_pcm(encoder);
+			break;
 #ifdef HAVE_TOOLAME
 		case ACODEC_TOOLAME:
 			ris = mpae_init_toolame(encoder);
Index: libmpcodecs/ae.h
===================================================================
--- libmpcodecs/ae.h	(revision 25166)
+++ libmpcodecs/ae.h	(working copy)
@@ -10,6 +10,7 @@
 #define ACODEC_TOOLAME 5
 #define ACODEC_FAAC 6
 #define ACODEC_TWOLAME 7
+#define ACODEC_SHMEM 8
 
 #define AE_NEEDS_COMPRESSED_INPUT 1
 
Index: libmpcodecs/vf.c
===================================================================
--- libmpcodecs/vf.c	(revision 25166)
+++ libmpcodecs/vf.c	(working copy)
@@ -99,6 +99,8 @@
 extern const vf_info_t vf_info_blackframe;
 extern const vf_info_t vf_info_geq;
 extern const vf_info_t vf_info_ow;
+extern const vf_info_t vf_info_shmemout;
+extern const vf_info_t vf_info_shmemin;
 
 // list of available filters:
 static const vf_info_t* const filter_list[]={
@@ -191,6 +193,10 @@
     &vf_info_yadif,
     &vf_info_blackframe,
     &vf_info_ow,
+#ifdef HAVE_SHM
+    &vf_info_shmemout,
+    &vf_info_shmemin,
+#endif
     NULL
 };
 
@@ -689,17 +695,19 @@
 
 //============================================================================
 
-vf_instance_t* append_filters(vf_instance_t* last){
+vf_instance_t* append_filters(vf_instance_t* last, m_obj_settings_t* vf_src){
   vf_instance_t* vf;
   int i; 
 
-  if(vf_settings) {
+  if(!vf_src) vf_src=vf_settings;
+  if(vf_src) {
     // We want to add them in the 'right order'
-    for(i = 0 ; vf_settings[i].name ; i++)
+    for(i = 0 ; vf_src[i].name ; i++)
       /* NOP */;
     for(i-- ; i >= 0 ; i--) {
       //printf("Open filter %s\n",vf_settings[i].name);
-      vf = vf_open_filter(last,vf_settings[i].name,vf_settings[i].attribs);
+      vf = vf_open_filter(last,vf_src[i].name,vf_src[i].attribs);
+printf("append_filters: %s \n",vf_src[i].name);
       if(vf) last=vf;
     }
   }
Index: libmpcodecs/vf.h
===================================================================
--- libmpcodecs/vf.h	(revision 25166)
+++ libmpcodecs/vf.h	(working copy)
@@ -82,6 +82,7 @@
 #define VFCTRL_GET_PTS         17 /* Return last pts value that reached vf_vo*/
 #define VFCTRL_SET_DEINTERLACE 18 /* Set deinterlacing status */
 #define VFCTRL_GET_DEINTERLACE 19 /* Get deinterlacing status */
+#define VFCTRL_SET_PTS         20 /* Send pts value */
 
 #include "vfcap.h"
 
@@ -112,8 +113,10 @@
 int vf_next_put_image(struct vf_instance_s* vf,mp_image_t *mpi, double pts);
 void vf_next_draw_slice (struct vf_instance_s* vf, unsigned char** src, int* stride, int w,int h, int x, int y);
 
-vf_instance_t* append_filters(vf_instance_t* last);
+#include "m_option.h"
 
+vf_instance_t* append_filters(vf_instance_t* last, m_obj_settings_t* vf_src);
+
 void vf_uninit_filter(vf_instance_t* vf);
 void vf_uninit_filter_chain(vf_instance_t* vf);
 
Index: libmpcodecs/vf_shmemout.c
===================================================================
--- libmpcodecs/vf_shmemout.c	(revision 0)
+++ libmpcodecs/vf_shmemout.c	(revision 0)
@@ -0,0 +1,437 @@
+/*
+ *  Export video frame to shared memory
+ *
+ *  Based on vf_screenshot.c and vf_expand.c
+ *
+ *
+ *  Copyright (C) 2007 Attila Ötvös <attila@onebithq.com>
+ *
+ *  MPlayer is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  MPlayer 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with MPlayer; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <string.h>
+#include <inttypes.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "mp_msg.h"
+
+#include "img_format.h"
+#include "mp_image.h"
+#include "vf.h"
+#include "vf_scale.h"
+
+#include "m_option.h"
+#include "m_struct.h"
+
+#include "libswscale/swscale.h"
+#include "stream/stream.h"
+#include "stream/stream_shmem.h"
+#include "libmpdemux/demuxer.h"
+
+#define OSD_SUPPORT
+
+#define OSD_OFF     0
+#define OSD_ON      1
+#define OSD_SCALE   2
+
+#ifdef OSD_SUPPORT
+#include "libvo/sub.h"
+#include "libvo/osd.h"
+
+static struct vf_instance_s* vf=NULL; // fixme (needs sub.c changes)
+static mp_image_t* osdmpi=NULL;
+#endif
+
+static struct vf_priv_s {
+    int store_slices;
+    int w, h;
+    int size;
+    mp_image_t* dst;
+    mp_image_t* odst;
+    struct SwsContext *ctx;
+    struct SwsContext *ctx2;
+    int shmem_opened;
+    stream_t* shmem_stream;
+    int shmemid;
+    int fmt;
+    int ow, oh, ofmt;
+    int osd;
+} const vf_priv_dflt = {
+    0,
+    0, 0,
+    0,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    0,
+    NULL,
+    1000,
+    0,
+    0, 0, 0,
+    0
+};
+
+//===========================================================================//
+
+static int config(struct vf_instance_s* vf,
+          int width, int height, int d_width, int d_height,
+          unsigned int flags, unsigned int outfmt) {
+
+    if (!vf->priv->fmt)
+    switch(outfmt){
+        case IMGFMT_YV12:
+        case IMGFMT_I420:
+        case IMGFMT_IYUV:
+        case IMGFMT_UYVY:
+        case IMGFMT_YUY2:
+        case IMGFMT_BGR24:
+        case IMGFMT_RGB24:
+        case IMGFMT_Y800:
+        case IMGFMT_Y8:
+        vf->priv->fmt=outfmt;
+        break;
+    }
+    if (!vf->priv->fmt) vf->priv->fmt=IMGFMT_BGR24;
+
+    if (!vf->priv->w) vf->priv->w = d_width;
+    if (!vf->priv->h) vf->priv->h = d_height;
+
+    vf->priv->ow = d_width;
+    vf->priv->oh = d_height;
+    vf->priv->ofmt = outfmt;
+#ifdef OSD_SUPPORT
+    if (vf->priv->osd==OSD_SCALE)
+        vf->priv->ctx2 = sws_getContextFromCmdLine(width, height, outfmt,
+                 d_width, d_height, outfmt);
+#endif
+    vf->priv->ctx = sws_getContextFromCmdLine(width, height, outfmt,
+                 vf->priv->w, vf->priv->h, vf->priv->fmt);
+
+    if (vf->priv->dst) free_mp_image(vf->priv->dst);
+    if (vf->priv->odst) free_mp_image(vf->priv->odst);
+    vf->priv->dst = NULL;
+    vf->priv->odst = NULL;
+
+    return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt);
+}
+
+static int imgsize(mp_image_t *mpi) {
+
+    switch(mpi->imgfmt){
+    case IMGFMT_I420:
+    case IMGFMT_IYUV:
+    case IMGFMT_YV12:
+        return mpi->w*mpi->h+2*(mpi->w>>1)*(mpi->h>>1);
+    case IMGFMT_YUY2:
+    case IMGFMT_UYVY:
+        return mpi->w*mpi->h*2;
+    case IMGFMT_Y800:
+    case IMGFMT_Y8:
+        return mpi->w*mpi->h;
+    case IMGFMT_BGR24:
+    case IMGFMT_RGB24:
+        return mpi->w * mpi->h * ((IMGFMT_RGB_DEPTH(mpi->imgfmt) + 7) >> 3);
+    }
+    return 0;
+}
+
+
+static void write_shmem(struct vf_instance_s* vf, mp_image_t *mpi) {
+    char fname[64];
+
+    if (vf->priv->shmem_opened==0 && vf->priv->shmemid>0) {
+        vf->priv->shmem_opened = 1;
+        snprintf(fname,sizeof(fname),"shmem://%d",vf->priv->shmemid);
+        set_shmem_opts(0, imgsize(mpi), DEMUXER_TYPE_RAWVIDEO,
+            mpi->imgfmt, mpi->w, mpi->h);
+        vf->priv->shmem_stream = open_output_stream(fname, NULL);
+    }
+    if (vf->priv->shmem_stream)
+        stream_write_buffer(vf->priv->shmem_stream, mpi->planes[0], imgsize(mpi));
+}
+
+#ifdef OSD_SUPPORT
+static void draw_func(int x0,int y0, int w,int h,unsigned char* src,
+                        unsigned char *srca, int stride) {
+    unsigned char* dst;
+
+    if (w<=0 || h<=0) return; // nothing to do...
+
+    dst = osdmpi->planes[0]+osdmpi->stride[0]*y0+(osdmpi->bpp>>3)*x0;
+
+    switch(osdmpi->imgfmt){
+    case IMGFMT_BGR15:
+    case IMGFMT_RGB15:
+        vo_draw_alpha_rgb15(w, h, src, srca, stride, dst, osdmpi->stride[0]);
+        break;
+    case IMGFMT_BGR16:
+    case IMGFMT_RGB16:
+        vo_draw_alpha_rgb16(w, h, src, srca, stride, dst, osdmpi->stride[0]);
+        break;
+    case IMGFMT_BGR24:
+    case IMGFMT_RGB24:
+        vo_draw_alpha_rgb24(w, h, src, srca, stride, dst, osdmpi->stride[0]);
+        break;
+    case IMGFMT_BGR32:
+    case IMGFMT_RGB32:
+        vo_draw_alpha_rgb32(w, h, src, srca, stride, dst, osdmpi->stride[0]);
+        break;
+    case IMGFMT_YV12:
+    case IMGFMT_I420:
+    case IMGFMT_IYUV:
+    case IMGFMT_YVU9:
+    case IMGFMT_IF09:
+    case IMGFMT_Y800:
+    case IMGFMT_Y8:
+        vo_draw_alpha_yv12(w, h, src, srca, stride, dst, osdmpi->stride[0]);
+        break;
+    case IMGFMT_YUY2:
+        vo_draw_alpha_yuy2(w, h, src, srca, stride, dst, osdmpi->stride[0]);
+        break;
+    case IMGFMT_UYVY:
+        vo_draw_alpha_yuy2(w, h, src, srca, stride, dst+1, osdmpi->stride[0]);
+        break;
+    }
+}
+
+static void draw_osd(struct vf_instance_s* vf_,mp_image_t *mpi) {
+
+    vf = vf_;
+    osdmpi = mpi;
+    vo_draw_text(mpi->w, mpi->h, draw_func);
+}
+#endif
+
+static void scale_image(struct vf_instance_s* vf, mp_image_t *mpi) {
+
+    if (!vf->priv->ctx) return;
+    if (!vf->priv->dst) vf->priv->dst = alloc_mpi(vf->priv->w, vf->priv->h,
+                                                  vf->priv->fmt);
+#ifdef OSD_SUPPORT
+    if (vf->priv->osd==OSD_SCALE) {
+        if (!vf->priv->odst) vf->priv->odst = alloc_mpi(vf->priv->ow,
+                vf->priv->oh, vf->priv->ofmt);
+        sws_scale_ordered(vf->priv->ctx2, mpi->planes, mpi->stride, 0, mpi->h,
+                vf->priv->odst->planes, vf->priv->odst->stride);
+        } else
+#endif
+        sws_scale_ordered(vf->priv->ctx, mpi->planes, mpi->stride, 0, mpi->h,
+                vf->priv->dst->planes, vf->priv->dst->stride);
+}
+
+static void start_slice(struct vf_instance_s* vf, mp_image_t *mpi) {
+                        vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
+                        mpi->type, mpi->flags, mpi->width, mpi->height);
+
+    if (!vf->priv->dst) vf->priv->dst = alloc_mpi(vf->priv->w, vf->priv->h,
+                                                  vf->priv->fmt);
+#ifdef OSD_SUPPORT
+    if (!vf->priv->odst && vf->priv->osd==OSD_SCALE)
+        vf->priv->odst = alloc_mpi(vf->priv->ow, vf->priv->oh, vf->priv->ofmt);
+#endif
+    vf->priv->store_slices = 1;
+}
+
+static void draw_slice(struct vf_instance_s* vf,
+        unsigned char** src, int* stride, int w,int h, int x, int y) {
+
+    if (vf->priv->store_slices && vf->priv->ctx) {
+    if (!vf->priv->dst) vf->priv->dst = alloc_mpi(vf->priv->w, vf->priv->h,
+                                                  vf->priv->fmt);
+#ifdef OSD_SUPPORT
+    if (vf->priv->osd==OSD_SCALE) {
+        if (!vf->priv->odst) vf->priv->odst = alloc_mpi(vf->priv->ow,
+                                                        vf->priv->oh,
+                                                        vf->priv->ofmt);
+        sws_scale_ordered(vf->priv->ctx2, src, stride, y, h,
+                          vf->priv->odst->planes,
+                          vf->priv->odst->stride);
+        } else
+#endif
+        sws_scale_ordered(vf->priv->ctx, src, stride, y, h,
+                            vf->priv->dst->planes,
+                            vf->priv->dst->stride);
+    }
+    vf_next_draw_slice(vf, src, stride, w, h, x, y);
+}
+
+static void get_image(struct vf_instance_s* vf, mp_image_t *mpi) {
+
+    // FIXME: should vf.c really call get_image when using slices??
+    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
+      return;
+    vf->dmpi= vf_get_image(vf->next, mpi->imgfmt,
+               mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/,
+               mpi->width, mpi->height);
+
+    mpi->planes[0] = vf->dmpi->planes[0];
+    mpi->stride[0] = vf->dmpi->stride[0];
+    if (mpi->flags&MP_IMGFLAG_PLANAR){
+        mpi->planes[1] = vf->dmpi->planes[1];
+        mpi->planes[2] = vf->dmpi->planes[2];
+        mpi->stride[1] = vf->dmpi->stride[1];
+        mpi->stride[2] = vf->dmpi->stride[2];
+    }
+    mpi->width = vf->dmpi->width;
+    mpi->flags |= MP_IMGFLAG_DIRECT;
+    mpi->priv = (void*)vf->dmpi;
+}
+
+static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts) {
+    mp_image_t *dmpi = (mp_image_t *)mpi->priv;
+
+    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
+      dmpi = vf->dmpi;
+    else
+    if (!(mpi->flags&MP_IMGFLAG_DIRECT)){
+    dmpi = vf_get_image(vf->next,mpi->imgfmt,
+                    MP_IMGTYPE_EXPORT, 0,
+                    mpi->width, mpi->height);
+    vf_clone_mpi_attributes(dmpi, mpi);
+    dmpi->planes[0] = mpi->planes[0];
+    dmpi->planes[1] = mpi->planes[1];
+    dmpi->planes[2] = mpi->planes[2];
+    dmpi->stride[0] = mpi->stride[0];
+    dmpi->stride[1] = mpi->stride[1];
+    dmpi->stride[2] = mpi->stride[2];
+    dmpi->width = mpi->width;
+    dmpi->height = mpi->height;
+    }
+
+    if (vf->priv->ctx) {
+        if (!vf->priv->store_slices) scale_image(vf, dmpi);
+#ifdef OSD_SUPPORT
+        switch(vf->priv->osd) {
+        case OSD_ON:
+            draw_osd(vf, vf->priv->dst);
+            break;
+        case OSD_SCALE:
+            draw_osd(vf, vf->priv->odst);
+            sws_scale_ordered(vf->priv->ctx, vf->priv->odst->planes,
+                              vf->priv->odst->stride, 0,
+                              vf->priv->odst->h, vf->priv->dst->planes,
+                              vf->priv->dst->stride);
+            break;
+        }
+#endif
+        write_shmem(vf, vf->priv->dst);
+        vf->priv->store_slices = 0;
+    }
+    return vf_next_put_image(vf, dmpi, pts);
+}
+
+//===========================================================================//
+static int control(struct vf_instance_s* vf, int request, void* data) {
+
+#ifdef OSD_SUPPORT
+    switch(request){
+    case VFCTRL_DRAW_OSD:
+    if (vf->priv->osd) return CONTROL_TRUE;
+    }
+#endif
+    return vf_next_control(vf, request, data);
+}
+
+static int query_format(struct vf_instance_s* vf, unsigned int fmt) {
+
+    switch(fmt){
+    case IMGFMT_YV12:
+    case IMGFMT_I420:
+    case IMGFMT_IYUV:
+    case IMGFMT_UYVY:
+    case IMGFMT_YUY2:
+    case IMGFMT_BGR24:
+    case IMGFMT_RGB24:
+    case IMGFMT_Y800:
+    case IMGFMT_Y8:
+    case IMGFMT_BGR32:
+    case IMGFMT_BGR16:
+    case IMGFMT_BGR15:
+    case IMGFMT_RGB32:
+    case IMGFMT_YVU9:
+    case IMGFMT_IF09:
+    case IMGFMT_444P:
+    case IMGFMT_422P:
+    case IMGFMT_411P:
+        return vf_next_query_format(vf, fmt);
+    }
+    return 0;
+}
+
+static void uninit(vf_instance_t *vf);
+// open conflicts with stdio.h at least under MinGW
+
+static int shmem_open(vf_instance_t *vf, char* args) {
+
+    vf->config = config;
+    vf->put_image = put_image;
+    vf->query_format = query_format;
+    vf->start_slice = start_slice;
+    vf->draw_slice = draw_slice;
+    vf->get_image = get_image;
+    vf->uninit = uninit;
+    vf->priv->w = (vf->priv->w+1)&~1;
+    vf->priv->h = (vf->priv->h+1)&~1;
+    return 1;
+}
+
+static void uninit(vf_instance_t *vf) {
+
+    if (vf->priv->shmem_stream) free_stream(vf->priv->shmem_stream);
+    if (vf->priv->ctx) sws_freeContext(vf->priv->ctx);
+    if (vf->priv->ctx2) sws_freeContext(vf->priv->ctx2);
+    if (vf->priv->dst) free_mp_image(vf->priv->dst);
+    if (vf->priv->odst) free_mp_image(vf->priv->odst);
+    free(vf->priv);
+}
+
+#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
+static m_option_t vf_opts_fields[] = {
+    {"shmemid", ST_OFF(shmemid), CONF_TYPE_INT, 0 , 0, 0, NULL},
+    {"fmt", ST_OFF(fmt), CONF_TYPE_IMGFMT, 0,0 ,0, NULL},
+    {"w", ST_OFF(w), CONF_TYPE_INT, M_OPT_MIN,16,0, NULL},
+    {"h", ST_OFF(h), CONF_TYPE_INT, M_OPT_MIN,16,0, NULL},
+    {"osd", ST_OFF(osd), CONF_TYPE_INT, CONF_RANGE , 0, 2, NULL},
+    { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+
+static m_struct_t vf_opts = {
+    "shmemout",
+    sizeof(struct vf_priv_s),
+    &vf_priv_dflt,
+    vf_opts_fields
+};
+
+vf_info_t vf_info_shmemout = {
+    "Export video to shared memory",
+    "shmemout",
+    "Otvos Attila",
+    "",
+    shmem_open,
+    &vf_opts
+};
+
+//===========================================================================//
Index: stream/Makefile
===================================================================
--- stream/Makefile	(revision 25166)
+++ stream/Makefile	(working copy)
@@ -48,6 +48,7 @@
 SRCS_COMMON-$(PVR)               += stream_pvr.c
 SRCS_COMMON-$(RADIO)             += stream_radio.c
 SRCS_COMMON-$(RADIO_CAPTURE)     += audio_in.c
+SRCS_COMMON-$(SHM)               += stream_shmem.c
 SRCS_COMMON-$(STREAM_CACHE)      += cache2.c
 SRCS_COMMON-$(STREAMING_LIVE555) += stream_livedotcom.c
 SRCS_COMMON-$(TV)                += stream_tv.c tv.c frequencies.c tvi_dummy.c
Index: stream/stream_shmem.c
===================================================================
--- stream/stream_shmem.c	(revision 0)
+++ stream/stream_shmem.c	(revision 0)
@@ -0,0 +1,780 @@
+/*
+ *  Share video frames through shared memory.
+ *
+ *  Copyright (C) 2007 Attila Ötvös <attila@onebithq.com>
+ *
+ *  MPlayer is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  MPlayer 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with MPlayer; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include "config.h"
+
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#ifdef HAVE_SEMAPHORE
+#include <sys/sem.h>
+#endif
+
+#include "mp_msg.h"
+#include "stream.h"
+#include "libmpdemux/demuxer.h"
+#include "help_mp.h"
+#include "m_option.h"
+#include "m_struct.h"
+#include "libavutil/common.h"
+#include "mpbswap.h"
+#include "stream_shmem.h"
+
+//#undef HAVE_SEMAPHORE                          // disable semaphore support
+
+#ifdef HAVE_SEMAPHORE
+
+#define SEM_FILE          "/dev/null"            // file with create unique semID
+#define SEM_NUM           1                      // semaphores num
+#define SEM_INIT          1                      // semaphore init values
+#define SEM_USLEEP        1000                   // usleep
+#define SEM_WAIT_TIME     20                     // wait time = 20*1000 usec
+#define SEM_SYNC_TIME     1000                   // wait time = 1000*1000 usec
+#define SEM_REQUIRE       1                      // if can't open semaphore then exit
+#define SEM_MEMBER        0                      // semaphore num
+
+#define SEM_OPEN          0                      // reader - open exist semaphore
+#define SEM_CREATE        1                      // writer - create new semaphore
+
+#if !defined(__GNU_LIBRARY__) || defined(_SEM_SEMUN_UNDEFINED)
+// semun undefined in <sys/sem.h>
+union semun
+{
+  int val;
+  struct semid_ds *buf;
+  unsigned short int *array;
+  struct seminfo *__buf;
+};
+#endif
+#endif
+
+typedef struct shmem_st {
+    char mplayerid[2];
+    int type;
+    int size;
+    int demuxer_type;
+    int format;
+    int width;
+    int height;
+    int flag;
+    int bytes;
+    float pts;
+    float rpts;
+    unsigned char data[0];
+} shmem_t;
+
+typedef struct {
+    int shmid;
+    int semid;
+    char* shmptr;
+    int shmemmaxsize;
+    shmem_t shmem;
+} shmems_t;
+
+struct {
+    int type;
+    int size;
+    int demuxer_type;
+    int format;
+    int width;
+    int height;
+} shmem_opts = {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0
+};
+
+static struct stream_priv_s {
+    char *ids;
+
+    int type;
+    int size;
+    int demuxer_type;
+    int format;
+    int width;
+    int height;
+
+    int shmemcount;
+    int shmemrecno;
+    int shmemid;
+    int semid;
+    int shmemmaxsize;
+    float pts;
+    float dpts;
+    unsigned int now;
+    unsigned int starttime;
+    unsigned char *data;
+    unsigned char *readptr;
+    int readlen;
+    int shmemsize;
+    int shmid;
+    char* shmptr;
+    shmems_t *shmems;
+    int wflg;
+    int attach;
+    shmem_t shmem;
+} stream_priv_dflts = {
+    NULL,   // ids
+
+    0,      // type
+    0,      // size
+    0,      // demuxer_type
+    0,      // format
+    0,      // width
+    0,      // height
+
+    0,      // shmemcount
+    0,      // shmemrecno
+    0,      // shmemid
+    -1,      // semid
+    0,      // shmemmaxsize
+    0.0,    // pts
+    0.0,    // dpts
+    0,      // now
+    0,      // starttime
+    NULL,   // data
+    NULL,   // readptr
+    0,      // readlen
+    0,      // shmemsize
+    0,      // shmid
+    NULL,   // shmptr
+    NULL,   // shmems
+    0,      // wflg
+    0	    // attach
+};
+
+
+#define ST_OFF(f) M_ST_OFF(struct stream_priv_s,f)
+/// URL definition
+static m_option_t stream_opts_fields[] = {
+    {"hostname", ST_OFF(ids), CONF_TYPE_STRING, 0, 0 ,0, NULL},
+    { NULL, NULL, 0, 0, 0, 0,  NULL }
+};
+static struct m_struct_st stream_opts = {
+    "shmem",
+    sizeof(struct stream_priv_s),
+    &stream_priv_dflts,
+    stream_opts_fields
+};
+
+void set_shmem_opts(int type, int size, int demuxer_type, int format, int width,
+                   int height) {
+    shmem_opts.type = type;
+    shmem_opts.size = size;
+    shmem_opts.demuxer_type = demuxer_type;
+    shmem_opts.format = format;
+    shmem_opts.width = width;
+    shmem_opts.height = height;
+    if(size==0)
+      shmem_opts.size = size = width*height*3;
+}
+
+#ifdef HAVE_SEMAPHORE
+/**
+ * \brief get semaphore values
+ * \param semid: semaphore ID
+ * \param member: semaphore number
+ * \return semaphore value
+ */
+static int semgetval(int semid, int member) {
+    return semctl(semid, member, GETVAL, 0);
+}
+
+/**
+ * \brief open semaphore
+ * \param shmid: shared memory ID
+ * \param writer: 0 - reader (open semaphore), 1 - writer (create semaphore)
+ * \return semaphore ID, -1 on error
+ */
+static int semopen(int shmid, int writer) {
+    int cpid, semid, i;
+    key_t key;
+    struct shmid_ds shmem_ds;
+    union semun semopts;
+
+    memset(&shmem_ds,0,sizeof(shmem_ds));
+    cpid = 0;
+    if (shmctl(shmid,IPC_STAT,&shmem_ds)==0)
+        cpid = shmem_ds.shm_cpid;
+    key = ftok(SEM_FILE,cpid);
+    mp_msg(MSGT_OPEN,MSGL_V,"semaphore cpid: %d key: %X\n",cpid,key);
+    if (writer) {
+        if ((semid = semget(key, SEM_NUM, IPC_CREAT|IPC_EXCL|0666)) == -1) {
+          if ((semid = semget(key, 0, 0666))!=-1)
+            semctl(semid, IPC_RMID, 0);
+          if ((semid = semget(key, SEM_NUM, IPC_CREAT|IPC_EXCL|0666)) == -1) {
+            mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open shemaphore. (%s)\n",strerror(errno));
+            return -1;
+	  }
+        }
+        semopts.val = SEM_INIT;
+        for(i=0; i<SEM_NUM; i++)
+            semctl(semid, i, SETVAL, semopts);
+    } else {
+        if ((semid = semget(key, 0, 0666))==-1) {
+            mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open shemaphore. (%s)\n",strerror(errno));
+            return -1;
+        }
+    }
+    return semid;
+}
+
+/**
+ * \brief check member is valid
+ * \param semid: semaphore ID
+ * \param member: semaphore number
+ * \return 0 - on error, 1 - member is valid
+ */
+static int semismember(int semid, int member) {
+    int membernum;
+    union semun semopts;
+    struct semid_ds semids;
+
+    if (semid==-1) return 0;
+    semopts.buf = &semids;
+    semctl(semid, 0, IPC_STAT, semopts);
+    membernum=semopts.buf->sem_nsems;
+    if (member<0 || member>(membernum-1))
+        return 1;
+    return 0;
+}
+
+/**
+ * \brief semaphore lock (no wait)
+ * \param semid: semaphore ID
+ * \param member: semaphore number
+ * \return 0 - on error
+ *         1 - OK
+ *        -1 - semaphore locked
+ */
+static int semlock(int semid, int member) {
+    struct sembuf sem_lock = { 0, -1, IPC_NOWAIT };
+
+    if (semismember(semid, member)) return 0;
+    if (!semgetval(semid, member)) return -1;
+    sem_lock.sem_num = member;
+    if ((semop(semid, &sem_lock, 1)) == -1) return 0;
+    return 1;
+}
+
+/**
+ * \brief semaphore lock (wait)
+ * \param semid: semaphore ID
+ * \param member: semaphore number
+ * \return 0 - on error
+ *         1 - OK
+ */
+static int semlockwait(int semid, int member) {
+    struct sembuf sem_lock = { 0, -1, 0 };
+
+    if (semismember(semid, member)) return 0;
+    sem_lock.sem_num = member;
+    if ((semop(semid, &sem_lock, 1)) == -1) return 0;
+    return 1;
+}
+
+/**
+ * \brief semaphore unlock
+ * \param semid: semaphore ID
+ * \param member: semaphore number
+ */
+static void semunlock(int semid, int member) {
+    struct sembuf sem_unlock = { member, 1, IPC_NOWAIT };
+    int semval;
+
+    if (semismember(semid, member)) return;
+    semval = semgetval(semid, member);
+    if (semval == SEM_INIT) return;
+    sem_unlock.sem_num = member;
+    if ((semop(semid, &sem_unlock, 1)) == -1) return;
+    return;
+}
+#endif
+
+/**
+ * \brief get number of attach clients
+ * \param semid: shmem ID
+ * \return: clients number
+ */
+static int get_shmem_attach(int shmid) {
+    struct shmid_ds smem_ds;
+    
+    smem_ds.shm_nattch=0;    
+    if (shmctl(shmid,IPC_STAT,&smem_ds)==0)
+	return smem_ds.shm_nattch-1;
+    return 0;
+}
+
+static void real_time_sleep(stream_t *s) {
+    struct stream_priv_s* p = (struct stream_priv_s*)s->priv;
+    unsigned int now, corr;
+    float pts_corr = 0.0f;
+
+    if (p->dpts > p->pts) {
+        pts_corr = p->dpts-p->pts;
+        if (p->dpts-p->pts > 10.0f)
+            now = (10.0f)*1000000.0f;
+        else
+            now = (p->dpts-p->pts)*1000000.0f;
+        usleep(now);
+    }
+    now = GetTimer();
+    if (p->now == 0) p->now = now;
+    if (p->now>now) corr = 0; else corr = now-p->now;
+    p->pts += corr/1000000.0f;
+    p->now = now;
+}
+
+static int fill_buffer(stream_t *s, char* buffer, int max_len){
+    struct stream_priv_s* p = (struct stream_priv_s*)s->priv;
+    shmem_t *sptr;
+    int len,j;
+
+    if (!p->shmptr) return -1;
+    if (p->readlen == 0) {
+        p->shmemrecno++;
+        if (p->shmemrecno >= p->shmemcount) p->shmemrecno = 0;
+        p->shmid = p->shmems[p->shmemrecno].shmid;
+        p->semid = p->shmems[p->shmemrecno].semid;
+        p->shmemmaxsize = p->shmems[p->shmemrecno].shmemmaxsize;
+        p->shmptr = p->shmems[p->shmemrecno].shmptr;
+
+        sptr = (shmem_t*)p->shmptr;
+    	for(j=0;j<SEM_SYNC_TIME;j++) {
+#ifdef HAVE_SEMAPHORE
+            if (p->semid!=-1) {
+            	if (!semlockwait(p->semid, SEM_MEMBER)) return -1;
+            }
+#endif
+    	    if (!p->attach && p->type==SHMEM_SYNCREAD && get_shmem_attach(p->semid)) p->attach=1;
+	    if (sptr->type==SHMEM_SYNCREAD && sptr->flag==0 && p->attach && !get_shmem_attach(p->semid)) {
+#ifdef HAVE_SEMAPHORE
+    	    	semunlock(p->semid, SEM_MEMBER);
+#endif
+printf("Read error!\n");
+	    	return -1;
+		}
+    	    if (sptr->type==SHMEM_SYNCREAD && sptr->flag==0 && get_shmem_attach(p->semid)) {
+#ifdef HAVE_SEMAPHORE
+    	    	semunlock(p->semid, SEM_MEMBER);
+#endif
+            	usleep(SEM_USLEEP);
+	    	continue;
+	    }
+	    break;
+        }
+        p->shmemsize = sptr->size;
+	p->readlen = sptr->bytes;
+	if (p->readlen>p->shmemsize || p->readlen<0)
+            p->readlen = p->shmemsize;
+        memcpy(p->data,sptr->data,p->readlen);
+	sptr->flag=0;
+#ifdef HAVE_SEMAPHORE
+        semunlock(p->semid, SEM_MEMBER);
+#endif
+        p->readptr = p->data;
+        if (sptr->pts == MP_NOPTS_VALUE)
+            real_time_sleep(s);
+        else
+            p->pts = sptr->pts;
+    }
+    if (p->readlen > max_len) len = max_len; else len = p->readlen;
+    if (len > 0) {
+        memcpy(buffer,p->readptr,len);
+        p->readptr += len;
+        p->readlen -= len;
+    }
+    return len;
+}
+
+static int write_buffer(stream_t *s, char* buffer, int len) {
+    struct stream_priv_s* p = (struct stream_priv_s*)s->priv;
+    shmem_t *ptr;
+    int i,j, lockstatus;
+
+    for(j=0;j<SEM_SYNC_TIME;j++) {
+#ifdef HAVE_SEMAPHORE
+    if (p->semid != -1) {
+        for(i=0;i<SEM_WAIT_TIME;i++) {
+            lockstatus = semlock(p->semid, SEM_MEMBER);
+            if (lockstatus !=-1 ) break;
+            usleep(SEM_USLEEP);
+            }
+    if (lockstatus == -1) return len;              // skip frame
+    if (lockstatus == 0) return -1;                // error
+    }
+#endif
+    ptr = (shmem_t*)p->shmptr;
+    if (!p->attach && p->type==SHMEM_SYNCREAD && get_shmem_attach(p->semid)) p->attach=1;
+    if (p->attach && p->type==SHMEM_SYNCREAD && ptr->flag==1 && !get_shmem_attach(p->semid)) {
+#ifdef HAVE_SEMAPHORE
+    	semunlock(p->semid, SEM_MEMBER);
+#endif
+printf("Write error!\n");
+    	return -1;
+	}
+    if (p->type==SHMEM_SYNCREAD && ptr->flag==1) {
+#ifdef HAVE_SEMAPHORE
+    	semunlock(p->semid, SEM_MEMBER);
+#endif
+        usleep(SEM_USLEEP);
+	continue;
+    }
+    ptr = (shmem_t*)p->shmptr;
+    ptr->mplayerid[0] = 'M';
+    ptr->mplayerid[1] = 'P';
+    ptr->type = p->type;
+    ptr->size = p->size;
+    ptr->demuxer_type = p->demuxer_type;
+    ptr->format = p->format;
+    ptr->width = p->width;
+    ptr->height = p->height;
+    ptr->pts = MP_NOPTS_VALUE;
+    ptr->flag = 1;
+    if (len > p->size) len = p->size;
+    ptr->bytes = len;
+    memcpy(ptr->data, buffer, len);
+#ifdef HAVE_SEMAPHORE
+    semunlock(p->semid, SEM_MEMBER);
+#endif
+    break;
+    }
+    return len;
+}
+
+static int control(stream_t *stream,int cmd,void* arg) {
+    struct stream_priv_s* p = (struct stream_priv_s*)stream->priv;
+    switch(cmd) {
+    case STREAM_CTRL_GET_CURRENT_TIME:
+        p->dpts = *((float *)arg);
+        *((float *)arg) = p->pts;
+        return 1;
+    case STREAM_CTRL_GET_WIDTH: {
+        *((unsigned int *)arg) = p->shmem.width;
+        return 1; }
+    case STREAM_CTRL_GET_HEIGHT: {
+        *((unsigned int *)arg) = p->shmem.height;
+        return 1; }
+    case STREAM_CTRL_GET_FORMAT: {
+        *((unsigned int *)arg) = p->shmem.format;
+        return 1; }
+    }
+    return STREAM_UNSUPPORTED;
+}
+
+static void close_shmem(int shmemcount, shmems_t *shmems) {
+    int i;
+
+    for(i=0;i<shmemcount;i++)
+        if (shmems[i].shmid) {
+            shmdt(shmems[i].shmptr);
+            shmems[i].shmid = 0;
+            shmems[i].shmemmaxsize = 0;
+            shmems[i].shmptr = NULL;
+        }
+    return;
+}
+
+static void close_s(struct stream_st *s) {
+    struct stream_priv_s* p = (struct stream_priv_s*)s->priv;
+
+    if (p->wflg) {
+        if (p->shmptr) shmdt(p->shmptr);
+        if (p->shmid) shmctl(p->shmid, IPC_RMID, 0);
+#ifdef HAVE_SEMAPHORE
+        if (p->semid != -1) semctl(p->semid, IPC_RMID, 0);
+#endif
+        free(p->data);
+        m_struct_free(&stream_opts,p);
+        return;
+    }
+    close_shmem(p->shmemcount,p->shmems);
+    free(p->shmems);
+    free(p->data);
+    m_struct_free(&stream_opts,p);
+}
+
+static int open_shmem(int shmemid, int *shmid, int *shmemmaxsize, char **shmptr,
+                     shmem_t *shmem, int *semid, int num) {
+    shmem_t *ptr;
+
+    *semid = -1;
+    *shmid = shmget(shmemid, sizeof(shmem_t), 0666); // alloctes a shared memory segment
+    if (*shmid < 0) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open shared memory (%d)\n",shmemid);
+        return 0;
+    }
+    *shmptr = shmat(*shmid,0,0);                   // attach shared memory segment
+    if (*shmptr == (char*)-1) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Can't attach shared memory (%d)\n",shmemid);
+        return 0;
+    }
+    ptr = (shmem_t*)*shmptr;
+#ifdef HAVE_SEMAPHORE
+    *semid = semopen(*shmid,SEM_OPEN);
+    if (*semid == -1 && SEM_REQUIRE) {
+        shmdt(*shmptr);
+        return 0;
+    }
+    if (*semid != -1) {
+        if (!semlockwait(*semid, SEM_MEMBER)) {
+            shmdt(*shmptr);
+            return 0;
+        }
+    }
+#endif
+    if (ptr->mplayerid[0]!='M' || ptr->mplayerid[1]!='P') { // check memory area of MPlayer
+#ifdef HAVE_SEMAPHORE
+        semunlock(*semid, SEM_MEMBER);
+#endif
+        shmdt(*shmptr);
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Illegal shared memory area (%d)\n",shmemid);
+        return 0;
+    }
+    if (ptr->type<0 || ptr->type>SHMEM_MAX_TYPE) { // check valid types
+#ifdef HAVE_SEMAPHORE
+        semunlock(*semid, SEM_MEMBER);
+#endif
+        shmdt(*shmptr);
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Illegal shared memory type (%d)\n",shmemid);
+        return 0;
+    }
+    if (num == 0) {                              // first?
+        shmem->size = ptr->size;
+        shmem->type = ptr->type;
+        shmem->demuxer_type = ptr->demuxer_type;
+        shmem->format = ptr->format;
+        shmem->width = ptr->width;
+        shmem->height = ptr->height;
+    } else {
+        if (shmem->size<ptr->size || shmem->demuxer_type!=ptr->demuxer_type ||
+                shmem->format!=ptr->format || shmem->width!=ptr->width ||
+                shmem->height!=ptr->height) {    // different properies?
+#ifdef HAVE_SEMAPHORE
+            semunlock(*semid, SEM_MEMBER);
+#endif
+            shmdt(*shmptr);
+            mp_msg(MSGT_OPEN,MSGL_ERR, "Different with, height or format (%d)\n",
+                    shmemid);
+            return 0;
+        }
+    }
+    *shmemmaxsize = ptr->size;
+#ifdef HAVE_SEMAPHORE
+    semunlock(*semid, SEM_MEMBER);
+#endif
+    return 1;
+}
+
+static int open_w(stream_t *stream,int mode, void** opts, int* file_format) {
+    struct stream_priv_s* p = (struct stream_priv_s*)opts;
+    int msize, shmemid;
+    shmem_t *ptr;
+
+    if (shmem_opts.width == 0 || shmem_opts.height == 0 ||
+            shmem_opts.demuxer_type == 0 || shmem_opts.format == 0)
+        return STREAM_UNSUPPORTED;
+    shmemid = atoi(p->ids);
+
+    if (shmemid <=0 ) return STREAM_UNSUPPORTED;   // check memory id
+
+    if (shmem_opts.type<0 || shmem_opts.type>SHMEM_MAX_TYPE)
+        return STREAM_UNSUPPORTED;
+
+    p->type = shmem_opts.type;                   // properties from set_shmem_opts()
+    p->size = shmem_opts.size;
+    p->demuxer_type = shmem_opts.demuxer_type;
+    p->format = shmem_opts.format;
+    p->width = shmem_opts.width;
+    p->height = shmem_opts.height;
+    memset(&shmem_opts,0,sizeof(shmem_opts));    // clear shmem_opts
+
+    if (p->type == SHMEM_RAWREAD &&              // check valid demuxer type
+            p->demuxer_type!=DEMUXER_TYPE_RAWVIDEO &&
+            p->demuxer_type!=DEMUXER_TYPE_TV)
+        return STREAM_UNSUPPORTED;
+    if (p->type == SHMEM_SYNCREAD &&              // check valid demuxer type
+            p->demuxer_type!=DEMUXER_TYPE_RAWVIDEO &&
+            p->demuxer_type!=DEMUXER_TYPE_TV)
+        return STREAM_UNSUPPORTED;
+
+    msize=sizeof(shmem_t)+p->size;
+    if ((p->shmid = shmget(shmemid, msize, IPC_CREAT|0666)) < 0) { // alloctes a shared memory segment
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Can't open shared memory! (%d)\n",shmemid);
+        return STREAM_UNSUPPORTED;
+    }
+    if ((p->shmptr=shmat(p->shmid,0,0))==(char*)-1) { // attach shared memory segment
+        mp_msg(MSGT_OPEN,MSGL_ERR, "Can't attach shared memory!\n");
+        shmctl(p->shmid, IPC_RMID, 0);
+        p->shmid=-1;
+        return STREAM_UNSUPPORTED;
+    }
+    p->wflg=1;
+#ifdef HAVE_SEMAPHORE
+    p->semid = semopen(p->shmid, SEM_CREATE);
+    if (p->semid == -1 && SEM_REQUIRE) return STREAM_UNSUPPORTED;
+    if (p->semid != -1) {
+        if (!semlockwait(p->semid, SEM_MEMBER)) {
+            mp_msg(MSGT_OPEN,MSGL_ERR, "Semaphore error!\n");
+            shmctl(p->shmid, IPC_RMID, 0);
+            p->shmid = -1;
+            return STREAM_UNSUPPORTED;
+        }
+    }
+#endif
+    ptr = (shmem_t*)p->shmptr;                   // set propreties to shared memory area
+    ptr->mplayerid[0] = 'M';
+    ptr->mplayerid[1] = 'P';
+    ptr->type = p->type;
+    ptr->size = p->size;
+    ptr->bytes = p->size;
+    ptr->demuxer_type = p->demuxer_type;
+    ptr->format = p->format;
+    ptr->width = p->width;
+    ptr->height = p->height;
+    ptr->flag = 0;
+#ifdef HAVE_SEMAPHORE
+    semunlock(p->semid, SEM_MEMBER);
+#endif
+
+    stream->flags = 0;
+    stream->sector_size = 2048;
+    stream->start_pos = 0;
+    stream->end_pos = 0;
+
+    stream->fill_buffer = fill_buffer;
+    stream->write_buffer = write_buffer;
+    stream->control = control;
+    stream->close = close_s;
+    stream->priv = opts;
+
+    return STREAM_OK;
+}
+
+static int open_s(stream_t *stream,int mode, void* opts, int* file_format) {
+    struct stream_priv_s* p = (struct stream_priv_s*)opts;
+    char *tmp, *pc, *pt;
+    int *shmemids;
+    int i;
+
+    if (mode == STREAM_WRITE)
+        return open_w(stream, mode, opts, file_format);
+    memset(&shmem_opts,0,sizeof(shmem_opts));    // clear shmem_opts
+    if (mode != STREAM_READ)
+        return STREAM_UNSUPPORTED;
+
+    if (!p->ids) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, "We need an shared memory id "
+            "(ex: shmem://1000 or shmem://1000,1001,1002,1003)\n");
+        m_struct_free(&stream_opts,opts);
+        return STREAM_ERROR;
+    }
+
+    pt=p->ids;
+    i=0;
+    do {                                         // How many shared memory
+        if (NULL != (pc=strchr(pt,','))) pc++;
+        pt=pc;
+        i++;
+    } while (pt);
+
+    shmemids = malloc(sizeof(int)*i);
+    memset(shmemids,0,sizeof(int)*i);
+    tmp = strdup(p->ids);
+    pt = tmp;
+    p->shmemcount = 0;
+    do {                                         // scan shmem id from hostname
+        if (NULL != (pc=strchr(pt,','))) *pc++=0;
+        if (atoi(pt) >0 ) {
+            shmemids[p->shmemcount]=atoi(pt);
+            p->shmemcount++;
+            }
+        pt=pc;
+    } while (pt);
+    free(tmp);
+    if (p->shmemcount == 0) {
+        mp_msg(MSGT_OPEN,MSGL_ERR, "We need an shared memory id "
+            "(ex: shmem://1000 or shmem://1000,1001,1002,1003)\n");
+        m_struct_free(&stream_opts,opts);
+        return STREAM_ERROR;
+    }
+    p->shmems = malloc(sizeof(shmems_t)*p->shmemcount);
+    memset(p->shmems,0,sizeof(shmems_t)*p->shmemcount);
+    p->shmemmaxsize=0;
+
+    for(i=0;i<p->shmemcount;i++) {               // open shared memory
+        if (!open_shmem(shmemids[i],
+                &(p->shmems[i].shmid),
+                &(p->shmems[i].shmemmaxsize),
+                &(p->shmems[i].shmptr),
+                &(p->shmem),
+                &(p->shmems[i].semid),i)) {
+            close_shmem(p->shmemcount,p->shmems);
+            free(p->shmems);
+            m_struct_free(&stream_opts,opts);
+            return STREAM_ERROR;
+        }
+        if (p->shmems[i].shmemmaxsize>p->shmemmaxsize)
+            p->shmemmaxsize=p->shmems[i].shmemmaxsize;
+    }
+    free(shmemids);
+    p->data = malloc(p->shmemmaxsize);
+    mp_msg(MSGT_OPEN,MSGL_INFO, "Shared memory stream info:"
+        " format=0x%x width=%d height=%d\n",p->shmem.format,p->shmem.width,
+        p->shmem.height);
+    p->shmemrecno = 0;
+    p->shmid = p->shmems[p->shmemrecno].shmid;
+    p->semid = p->shmems[p->shmemrecno].semid;
+    p->shmemmaxsize = p->shmems[p->shmemrecno].shmemmaxsize;
+    p->shmptr = p->shmems[p->shmemrecno].shmptr;
+
+    *file_format = DEMUXER_TYPE_RAWVIDEO;
+    stream->flags = 0;
+    stream->sector_size = 2048;
+    stream->start_pos = 0;
+    stream->end_pos = 0;
+
+    stream->fill_buffer = fill_buffer;
+    stream->control = control;
+    stream->close = close_s;
+    stream->priv = opts;
+    return STREAM_OK;
+}
+
+stream_info_t stream_info_shmem = {
+    "Shared memory stream",
+    "shmem",
+    "Otvos Attila",
+    "",
+    open_s,
+    { "shmem",NULL },
+    &stream_opts,
+    1 // Url is an option string
+};
Index: stream/stream_shmem.h
===================================================================
--- stream/stream_shmem.h	(revision 0)
+++ stream/stream_shmem.h	(revision 0)
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (C) 2007 Attila Ötvös <attila@onebithq.com>
+ *
+ *  MPlayer is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  MPlayer 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with MPlayer; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define SHMEM_RAWREAD   0
+#define SHMEM_SYNCREAD  1
+#define SHMEM_MAX_TYPE  1
+
+void set_shmem_opts(int type, int size, int demuxer_type, int format, int width, int height);
Index: stream/stream.c
===================================================================
--- stream/stream.c	(revision 25166)
+++ stream/stream.c	(working copy)
@@ -41,6 +41,9 @@
 #ifdef HAVE_CDDA
 extern stream_info_t stream_info_cdda;
 #endif
+#ifdef HAVE_SHM
+extern stream_info_t stream_info_shmem;
+#endif
 #ifdef MPLAYER_NETWORK
 extern stream_info_t stream_info_netstream;
 extern stream_info_t stream_info_pnm;
@@ -95,6 +98,9 @@
 #ifdef HAVE_CDDA
   &stream_info_cdda,
 #endif
+#ifdef HAVE_SHM
+  &stream_info_shmem,
+#endif
 #ifdef MPLAYER_NETWORK
   &stream_info_netstream,
   &stream_info_http1,
Index: stream/stream.h
===================================================================
--- stream/stream.h	(revision 25166)
+++ stream/stream.h	(working copy)
@@ -25,6 +25,7 @@
 #define STREAMTYPE_TV 17
 #define STREAMTYPE_MF 18
 #define STREAMTYPE_RADIO 19
+#define STREAMTYPE_SHMEM 20
 
 #define STREAM_BUFFER_SIZE 2048
 
@@ -61,6 +62,9 @@
 #define STREAM_CTRL_SEEK_TO_TIME 6
 #define STREAM_CTRL_GET_SIZE 7
 #define STREAM_CTRL_GET_ASPECT_RATIO 8
+#define STREAM_CTRL_GET_WIDTH 9
+#define STREAM_CTRL_GET_HEIGHT 10
+#define STREAM_CTRL_GET_FORMAT 11
 
 #ifdef MPLAYER_NETWORK
 #include "network.h"
Index: cfg-mencoder.h
===================================================================
--- cfg-mencoder.h	(revision 25166)
+++ cfg-mencoder.h	(working copy)
@@ -199,6 +199,8 @@
 	// and for 29.97FPS progressive MPEG2 streams
 	{"ofps", &force_ofps, CONF_TYPE_FLOAT, CONF_MIN|CONF_GLOBAL, 0, 0, NULL},
 	{"o", &out_filename, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
+	// video mixer config file
+	{"video-mixer", &vmixer_filename, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
 
 	// limit number of skippable frames after a non-skipped one
 	{"skiplimit", &skip_limit, CONF_TYPE_INT, 0, 0, 0, NULL},
@@ -296,3 +298,43 @@
 //	{"h", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
 	{NULL, NULL, 0, 0, 0, 0, NULL}
 };
+
+m_option_t mencoder_vmixer_opts[]={
+	/* name, pointer, type, flags, min, max */
+
+	{"inputid", &vmixer_inputid, CONF_TYPE_INT, 0, 0, 0, NULL},
+	{"input-file", &vmixer_input_filename, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
+	// limit number of skippable frames after a non-skipped one
+	{"skiplimit", &skip_limit, CONF_TYPE_INT, 0, 0, 0, NULL},
+	{"noskiplimit", &skip_limit, CONF_TYPE_FLAG, 0, 0, -1, NULL},
+	{"noskip", &skip_limit, CONF_TYPE_FLAG, 0, 0, 0, NULL},
+
+	{"audio-density", &audio_density, CONF_TYPE_INT, CONF_RANGE|CONF_GLOBAL, 1, 50, NULL},
+	{"audio-preload", &audio_preload, CONF_TYPE_FLOAT, CONF_RANGE|CONF_GLOBAL, 0, 2, NULL},
+	{"audio-delay",   &audio_delay_fix, CONF_TYPE_FLOAT, CONF_GLOBAL, 0, 0, NULL},
+
+	{"x", "-x has been removed, use -vf scale=w:h for scaling.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
+	{"xsize", "-xsize has been removed, use -vf crop=w:h:x:y for cropping.\n", CONF_TYPE_PRINT, CONF_NOCFG, 0, 0, NULL},
+
+	// override avi aspect autodetection
+	{"force-avi-aspect", &avi_aspect_override, CONF_TYPE_FLOAT, CONF_RANGE|CONF_GLOBAL, 0.2, 3.0, NULL},
+
+	{"vobsubout", &vobsub_out, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
+	{"vobsuboutindex", &vobsub_out_index, CONF_TYPE_INT, CONF_RANGE|CONF_GLOBAL, 0, 31, NULL},
+	{"vobsuboutid", &vobsub_out_id, CONF_TYPE_STRING, CONF_GLOBAL, 0, 0, NULL},
+
+	{"autoexpand", &auto_expand, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"noautoexpand", &auto_expand, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+	
+	{"encodedups", &encode_duplicates, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+	{"noencodedups", &encode_duplicates, CONF_TYPE_FLAG, 0, 1, 0, NULL},
+	
+	// info header strings
+	{"info", info_conf, CONF_TYPE_SUBCONFIG, CONF_GLOBAL, 0, 0, NULL},
+
+#define MAIN_CONF
+#include "cfg-common.h"
+#undef MAIN_CONF
+
+	{NULL, NULL, 0, 0, 0, 0, NULL}
+};
Index: gui/cfg.c
===================================================================
--- gui/cfg.c	(revision 25166)
+++ gui/cfg.c	(working copy)
@@ -82,7 +82,7 @@
 // ---
 
 extern int    stop_xscreensaver;
-extern int    m_config_parse_config_file(m_config_t* config, char *conffile);
+extern int    m_config_parse_config_file(m_config_t* config, char *conffile, int (*skip_line)(char *line));
 
 static m_config_t * gui_conf;
 static m_option_t gui_opts[] =
@@ -222,7 +222,7 @@
  mp_msg( MSGT_GPLAYER,MSGL_V,"[cfg] reading config file: %s\n",cfg );
  gui_conf=m_config_new();
  m_config_register_options( gui_conf,gui_opts );
- if ( m_config_parse_config_file( gui_conf,cfg ) < 0 ) 
+ if ( m_config_parse_config_file( gui_conf,cfg,NULL ) < 0 ) 
   {
    mp_msg( MSGT_GPLAYER,MSGL_FATAL,MSGTR_ConfigFileError );
 //   exit( 1 );
Index: gui/win32/wincfg.c
===================================================================
--- gui/win32/wincfg.c	(revision 25166)
+++ gui/win32/wincfg.c	(working copy)
@@ -55,7 +55,7 @@
 /* External functions */
 extern int frame_dropping;
 extern char *proc_priority;
-extern int m_config_parse_config_file(m_config_t *config, char *conffile);
+extern int m_config_parse_config_file(m_config_t *config, char *conffile, int (*skip_line)(char *line));
 
 static m_config_t *gui_conf;
 static m_option_t gui_opts[] =
@@ -112,7 +112,7 @@
     mp_msg(MSGT_GPLAYER, MSGL_V, "[GUI] [cfg] reading config file: %s\n", cfg);
     gui_conf = m_config_new();
     m_config_register_options(gui_conf, gui_opts);
-    if (m_config_parse_config_file(gui_conf, cfg) < 0)
+    if (m_config_parse_config_file(gui_conf, cfg,NULL) < 0)
         mp_msg(MSGT_GPLAYER, MSGL_FATAL, MSGTR_ConfigFileError);
     free(cfg);
     return 0;
Index: me_core.h
===================================================================
--- me_core.h	(revision 0)
+++ me_core.h	(revision 0)
@@ -0,0 +1,62 @@
+// definitions used internally by the core encoder code
+
+#include "libao2/audio_out.h"
+
+typedef struct {
+    unsigned char* start;
+    int in_size;
+    float frame_time;
+    int already_read;
+} s_frame_data;
+
+typedef struct MEContext {
+    	pthread_t        thread;
+    	pthread_mutex_t  mutex;
+	char *input_file;
+	int vmixerid;
+// input
+	stream_t* stream;
+	int file_format;
+	demuxer_t* demuxer;
+	demuxer_t* demuxer2;
+	demux_stream_t *d_audio;
+	demux_stream_t *d_video;
+	demux_stream_t *d_dvdsub;
+	sh_audio_t *sh_audio;
+	sh_video_t *sh_video;
+	int new_srate;
+	int eof;
+// common
+	void *vobsub_writer;
+	stream_t* stream2;
+// output
+	stream_t* ostream;
+	muxer_t* muxer;
+	muxer_stream_t* mux_v;
+	muxer_stream_t* mux_a;
+    	vf_instance_t * ve;
+    	m_obj_settings_t * vf_settings;
+	
+	ao_data_t ao_data;
+	audio_encoder_t *aencoder;
+	audio_encoding_params_t aparams;
+	int decoded_frameno;
+	unsigned int timer_start;
+	s_frame_data frame_data;
+	uint32_t ptimer_start;
+	uint32_t audiosamples;
+	uint32_t audiorate;
+	double v_timer_corr;
+	int next_frameno;
+	double v_pts_corr;
+	uint32_t badframes;
+	uint32_t videosamples;
+	uint32_t videorate;
+	uint32_t duplicatedframes;
+	uint32_t skippedframes;
+
+	int start;
+	void* next;
+} MEContext;
+
+
Index: parser-cfg.c
===================================================================
--- parser-cfg.c	(revision 25166)
+++ parser-cfg.c	(working copy)
@@ -34,7 +34,7 @@
  *  \param conffile Path to the config file.
  *  \return 1 on sucess, -1 on error.
  */
-int m_config_parse_config_file(m_config_t* config, char *conffile)
+int m_config_parse_config_file(m_config_t* config, char *conffile, int (*skip_line)(char *line))
 {
 #define PRINT_LINENUM	mp_msg(MSGT_CFGPARSER,MSGL_V,"%s(%d): ", conffile, line_num)
 #define MAX_LINE_LEN	10000
@@ -101,6 +101,10 @@
 		if (line[line_pos] == '\0' || line[line_pos] == '#')
 			continue;
 
+		/* skip function */
+		if (skip_line && skip_line(line))
+			continue;
+			
 		/* read option. */
 		for (opt_pos = 0; isprint(line[line_pos]) &&
 				line[line_pos] != ' ' &&
Index: parser-cfg.h
===================================================================
--- parser-cfg.h	(revision 25166)
+++ parser-cfg.h	(working copy)
@@ -1,6 +1,6 @@
 #ifndef _parser_cfg_h
 #define _parser_cfg_h
 
-extern int m_config_parse_config_file(m_config_t* config, char *conffile);
+extern int m_config_parse_config_file(m_config_t* config, char *conffile, int (*skip_line)(char *line));
 
 #endif
Index: configure
===================================================================
--- configure	(revision 25166)
+++ configure	(working copy)
@@ -273,6 +273,7 @@
   --disable-w32threads   disable Win32 threads support [autodetect]
   --disable-ass          disable internal SSA/ASS subtitle support [autodetect]
   --enable-rpath         enable runtime linker path for extra libs [disabled]
+  --disable-semaphore    disable semaphore support [autodetect]
 
 Codecs:
   --enable-gif		    enable GIF support [autodetect]
@@ -665,6 +666,7 @@
 _w32threads=auto
 _ass=auto
 _rpath=no
+_semaphore=auto
 _asmalign_pot=auto
 _color_console=no
 _stream_cache=yes
@@ -1106,6 +1108,8 @@
   --disable-ass)        _ass=no         ;;
   --enable-rpath)       _rpath=yes      ;;
   --disable-rpath)      _rpath=no       ;;
+  --enable-semaphore)   _semaphore=yes  ;;
+  --disable-semaphore)  _samephore=no   ;;
   --enable-color-console)  _color_console=yes ;;
   --disable-color-console) _color_console=no  ;;
 
@@ -5495,6 +5499,25 @@
     _noinputmodules="cddb $_noinputmodules"
 fi
 
+echocheck "semaphore"
+if test "$_semaphore" = auto ; then
+  cat > $TMPC << EOF
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+int main(void) { semget(0, 0, 0); return 0; }
+EOF
+  _semaphore=no
+  cc_check && _semaphore=yes
+fi
+if test "$_semaphore" = yes ; then
+  _def_semaphore='#define HAVE_SEMAPHORE 1'
+else
+  _def_semaphore='#undef HAVE_SEMAPHORE'
+fi
+echores "$_semaphore"
+
+
 echocheck "bitmap font support"
 if test "$_bitmap_font" = yes ; then
   _def_bitmap_font="#define HAVE_BITMAP_FONT 1"
@@ -7682,6 +7705,7 @@
 LIBTHEORA = $_theora
 FAAD_INTERNAL = $_faad_internal
 FAAD_FIXED = $_faad_fixed
+SHM = $_shm
 LIBSMBCLIENT = $_smbsupport
 XMMS_PLUGINS = $_xmms
 MACOSX = $_macosx
@@ -8384,6 +8408,9 @@
 $_def_cdparanoia
 $_def_cddb
 
+/* enable semaphore  */
+$_def_semaphore
+
 /* enables / disables VIDIX usage */
 $_def_vidix
 $_def_vidix_drv_cyberblade
Index: DOCS/man/en/mplayer.1
===================================================================
--- DOCS/man/en/mplayer.1	(revision 25166)
+++ DOCS/man/en/mplayer.1	(working copy)
@@ -122,6 +122,11 @@
 .B mplayer
 tivo://host/[list|llist|fsid]
 [options]
+.br
+.in
+.B mplayer
+shmem://shmemid[,shmemid[,shmemid ... ]]
+[options]
 .
 .br
 .B gmplayer
@@ -6949,8 +6954,41 @@
 Threshold below which a pixel value is considered black (default: 32).
 .RE
 .
+.TP
+.B shmemout[=shmemid:fmt:w:h:o]
+Export video frames to shared memory.
+.RSs
+.IPs <shmemid>
+shared memory ID (default: 1000).
+.IPs <fmt>
+format of exported video frames: yv12, i420, yuy2, y8, y800, rgb24, bgr24.
+.IPs <w,h>
+width and height of expored video frames (default: current video width and height)
+.IPs "<o>\ \ "
+OSD/\:subtitle rendering
+.RSss
+0: disable (default)
+.br
+1: enable (only shared memory, without OSD scale)
+.br
+2: enable (only shared memory, with OSD scale)
+.REss
+.RE
 .
+.TP
+.B shmemin[=shmemid:x:y:w:h]
+Import video frames from shared memory.
+.RSs
+.IPs <shmemid>
+shared memory ID (default: 1000).
+.IPs <x,y>
+top left corner of imported video frames (default: 0,0)
+.IPs <w,h>
+width and height of imported video frames (default: exported video frames width and height)
+.RE
 .
+.
+.
 .SH "GENERAL ENCODING OPTIONS (MENCODER ONLY)"
 .
 .TP
@@ -10767,7 +10805,34 @@
 rar p test-SVCD.rar | mencoder \-ovc lavc \-lavcopts vcodec=mpeg4:vbitrate=800 \-ofps 24 \-
 .fi
 .
+.PP
+.B Show the encoded tv channels on shared screen (eg. CCTV):
+.nf
+mencoder tv:// -vf shmemout=1000 -o cam1.avi [options]
+mencoder tv:// -vf shmemout=1001 -o cam2.avi [options]
+mencoder tv:// -vf shmemout=1002 -o cam3.avi [options]
+mencoder tv:// -vf shmemout=1003 -o cam4.avi [options]
 .
+mplayer shmem://1000,1001,1002,1003 -vf tile=2:2 [options]
+.fi
+.
+.PP
+.B Preview with OSD:
+.nf
+mencoder movie.avi -vf shmemout=1000::::1 -o rec.avi [options]
+.
+mplayer shmem://1000 [options]
+.fi
+.
+.PP
+.B Screen-on-screen (right top corner):
+.nf
+mplayer tv://2 -tv device=/dev/video1:width=320:height=200 -nosound -vo null -vf shmemout=1000 [options]
+.
+mplayer tv://1 -tv device=/dev/video0:width=640:height=480 -vf shmemin=1000:320 [options]
+.fi
+.
+.
 .\" --------------------------------------------------------------------------
 .\" Bugs, authors, standard disclaimer
 .\" --------------------------------------------------------------------------
Index: mplayer.c
===================================================================
--- mplayer.c	(revision 25166)
+++ mplayer.c	(working copy)
@@ -139,7 +139,7 @@
 static int cfg_inc_verbose(m_option_t *conf){ ++verbose; return 0;}
 
 static int cfg_include(m_option_t *conf, char *filename){
-	return m_config_parse_config_file(mconfig, filename);
+	return m_config_parse_config_file(mconfig, filename, NULL);
 }
 
 #include "get_path.h"
@@ -802,7 +802,7 @@
 {
 char *conffile;
 int conffile_fd;
-if (m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf") < 0)
+if (m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf", NULL) < 0)
   exit_player(NULL);
 if ((conffile = get_path("")) == NULL) {
   mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_NoHomeDir);
@@ -821,7 +821,7 @@
       write(conffile_fd, default_config, strlen(default_config));
       close(conffile_fd);
     }
-    if (m_config_parse_config_file(conf, conffile) < 0)
+    if (m_config_parse_config_file(conf, conffile, NULL) < 0)
       exit_player(NULL);
     free(conffile);
   }
@@ -840,7 +840,7 @@
     if (use_filedir_conf && !stat (cfg, &st))
     {
 	mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_LoadingConfig, cfg);
-	m_config_parse_config_file (conf, cfg);
+	m_config_parse_config_file (conf, cfg, NULL);
 	return;
     }
 
@@ -854,7 +854,7 @@
 	if (!stat (confpath, &st))
 	{
 	    mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_LoadingConfig, confpath);
-	    m_config_parse_config_file (conf, confpath);
+	    m_config_parse_config_file (conf, confpath, NULL);
 	}
 
 	free (confpath);
@@ -1953,7 +1953,7 @@
   }
 #endif
 
-  sh_video->vfilter=(void*)append_filters(sh_video->vfilter);
+  sh_video->vfilter=(void*)append_filters(sh_video->vfilter,NULL);
 
 #ifdef USE_ASS
   if (ass_enabled)
Index: libmpdemux/Makefile
===================================================================
--- libmpdemux/Makefile	(revision 25166)
+++ libmpdemux/Makefile	(working copy)
@@ -61,6 +61,7 @@
                 muxer_mpeg.c \
                 muxer_rawaudio.c \
                 muxer_rawvideo.c \
+                muxer_shmem.c \
 
 SRCS_MENCODER-$(LIBAVFORMAT)           += muxer_lavf.c
 
Index: libmpdemux/muxer.c
===================================================================
--- libmpdemux/muxer.c	(revision 25166)
+++ libmpdemux/muxer.c	(working copy)
@@ -32,6 +32,10 @@
         if(! muxer_init_muxer_rawvideo(muxer))
 	  goto fail;
 	break;
+      case MUXER_TYPE_SHMEM:
+        if(! muxer_init_muxer_shmem(muxer))
+	  goto fail;
+	break;
       case MUXER_TYPE_RAWAUDIO:
         if(! muxer_init_muxer_rawaudio(muxer))
 	  goto fail;
Index: libmpdemux/muxer.h
===================================================================
--- libmpdemux/muxer.h	(revision 25166)
+++ libmpdemux/muxer.h	(working copy)
@@ -9,6 +9,7 @@
 #define MUXER_TYPE_RAWVIDEO 2
 #define MUXER_TYPE_LAVF 3
 #define MUXER_TYPE_RAWAUDIO 4
+#define MUXER_TYPE_SHMEM 5
 
 
 typedef struct {
@@ -113,3 +114,4 @@
 int muxer_init_muxer_rawvideo(muxer_t *);
 int muxer_init_muxer_lavf(muxer_t *);
 int muxer_init_muxer_rawaudio(muxer_t *);
+int muxer_init_muxer_shmem(muxer_t *);
Index: libmpdemux/demux_rawvideo.c
===================================================================
--- libmpdemux/demux_rawvideo.c	(revision 25166)
+++ libmpdemux/demux_rawvideo.c	(working copy)
@@ -15,7 +15,7 @@
 #include "libmpcodecs/img_format.h"
 
 extern int demuxer_type;
-static int format = IMGFMT_I420;
+static int format = 0;
 static int size_id = 0;
 static int width = 0;
 static int height = 0;
@@ -55,6 +55,10 @@
 static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) {
   sh_video_t* sh_video;
 
+  if (!width)  stream_control(demuxer->stream, STREAM_CTRL_GET_WIDTH,  &width);
+  if (!height) stream_control(demuxer->stream, STREAM_CTRL_GET_HEIGHT, &height);
+  if (!format) stream_control(demuxer->stream, STREAM_CTRL_GET_FORMAT, &format);
+  if (!format) format = IMGFMT_I420;
   switch(size_id){
   case 1: width=128; height=96; break;
   case 2: width=176; height=144; break;
@@ -112,9 +116,17 @@
 static int demux_rawvideo_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds) {
   sh_video_t* sh = demuxer->video->sh;
   off_t pos;
+  float spts = 0.0f;
   if(demuxer->stream->eof) return 0;
   if(ds!=demuxer->video) return 0;
   pos = stream_tell(demuxer->stream);
+#ifdef HAVE_SHMEM
+  spts=(pos/imgsize)*sh->frametime;
+  if (stream_control(demuxer->stream, STREAM_CTRL_GET_CURRENT_TIME, &spts)==1) {
+     ds_read_packet(ds,demuxer->stream,imgsize,spts,pos,0x10); 
+  }
+  else
+#endif
   ds_read_packet(ds,demuxer->stream,imgsize,(pos/imgsize)*sh->frametime,pos,0x10);
   return 1;
 }
Index: libmpdemux/muxer_shmem.c
===================================================================
--- libmpdemux/muxer_shmem.c	(revision 0)
+++ libmpdemux/muxer_shmem.c	(revision 0)
@@ -0,0 +1,77 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "version.h"
+
+//#include "stream/stream.h"
+//#include "demuxer.h"
+//#include "stheader.h"
+#include "aviheader.h"
+#include "ms_hdr.h"
+
+#include "stream/stream.h"
+#include "muxer.h"
+
+static muxer_stream_t* shmem_new_stream(muxer_t *muxer,int type){
+    muxer_stream_t* s;
+    if (!muxer) return NULL;
+    s=malloc(sizeof(muxer_stream_t));
+    memset(s,0,sizeof(muxer_stream_t));
+    if(!s) return NULL; // no mem!?
+    muxer->streams[muxer->avih.dwStreams]=s;
+    s->type=type;
+    s->id=muxer->avih.dwStreams;
+    s->timer=0.0;
+    s->size=0;
+    s->muxer=muxer;
+    switch(type){
+    case MUXER_TYPE_VIDEO:
+      s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'d','c');
+      s->h.fccType=streamtypeVIDEO;
+      if(!muxer->def_v) muxer->def_v=s;
+      break;
+    }
+    muxer->avih.dwStreams++;
+    return s;
+}
+
+static void write_shmem_chunk(stream_t *stream,int len,void* data){
+    if(len>0){
+	if(data){
+	    // DATA
+            stream_write_buffer(stream,data,len);
+	}
+    }
+}
+
+static void shmem_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags, double dts, double pts){
+    muxer_t *muxer=s->muxer;
+
+    // write out the chunk:
+    if (s->type == MUXER_TYPE_VIDEO)
+    write_shmem_chunk(muxer->stream,len,s->buffer); /* unsigned char */
+
+    // if((unsigned int)len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len;
+
+}
+
+static void shmem_write_header(muxer_t *muxer){
+    return;
+}
+
+static void shmem_write_index(muxer_t *muxer){
+    return;
+}
+
+int muxer_init_muxer_shmem(muxer_t *muxer){
+  muxer->cont_new_stream = &shmem_new_stream;
+  muxer->cont_write_chunk = &shmem_write_chunk;
+  muxer->cont_write_header = &shmem_write_header;
+  muxer->cont_write_index = &shmem_write_index;
+  return 1;
+}
Index: mencoder.c
===================================================================
--- mencoder.c	(revision 25166)
+++ mencoder.c	(working copy)
@@ -9,6 +9,7 @@
 #define VCODEC_NUV 11
 #define VCODEC_RAW 12
 #define VCODEC_X264 13
+#define VCODEC_SHMEM 14
 
 #define ACODEC_COPY 0
 #define ACODEC_PCM 1
@@ -18,6 +19,7 @@
 #define ACODEC_TOOLAME 5
 #define ACODEC_FAAC 6
 #define ACODEC_TWOLAME 7
+#define ACODEC_SHMEM 8
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -84,6 +86,11 @@
 #include "stream/stream_dvdnav.h"
 #endif
 
+#ifdef HAVE_SHM
+#include "stream/stream_shmem.h"
+#endif
+
+
 #ifdef USE_LIBAVCODEC_SO
 #include <ffmpeg/avcodec.h>
 #elif USE_LIBAVCODEC_A
@@ -96,6 +103,8 @@
 int vo_config_count=1;
 int forced_subs_only=0;
 
+#include "me_core.h"
+
 //--------------------------
 
 // cache2:
@@ -249,12 +258,12 @@
 
 m_config_t* mconfig;
 
-extern int m_config_parse_config_file(m_config_t* config, char *conffile);
+extern int m_config_parse_config_file(m_config_t* config, char *conffile, int (*skip_line)(char *line));
 
 static int cfg_inc_verbose(m_option_t *conf){ ++verbose; return 0;}
 
 static int cfg_include(m_option_t *conf, char *filename){
-	return m_config_parse_config_file(mconfig, filename);
+	return m_config_parse_config_file(mconfig, filename, NULL);
 }
 
 static double seek_to_sec;
@@ -264,15 +273,13 @@
 
 static char * frameno_filename=NULL;
 
+static char * vmixer_filename=NULL;
+static char * vmixer_input_filename=NULL;
+static int vmixer_inputid=0;
+static int vmixer_vmixerid=0;
+
 //static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, int height);
 
-typedef struct {
-    unsigned char* start;
-    int in_size;
-    float frame_time;
-    int already_read;
-} s_frame_data;
-
 /// Returns a_pts
 static float calc_a_pts(demux_stream_t *d_audio);
 /** \brief Seeks audio forward to pts by dumping audio packets
@@ -322,7 +329,7 @@
   if ((conffile = get_path("mencoder.conf")) == NULL) {
     mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_GetpathProblem);
   } else {
-    if (m_config_parse_config_file(conf, conffile) < 0)
+    if (m_config_parse_config_file(conf, conffile, NULL) < 0)
       mencoder_exit(1,MSGTR_ConfigFileError);
     free(conffile);
   }
@@ -361,303 +368,182 @@
     interrupted=2; /* 1 means error */
 }
 
-static muxer_t* muxer=NULL;
+//static muxer_t* muxer=NULL;
 
 extern void print_wave_header(WAVEFORMATEX *h, int verbose_level);
 
-int main(int argc,char* argv[]){
+int skip_line(char *line){
 
-stream_t* stream=NULL;
-stream_t* ostream=NULL;
-demuxer_t* demuxer=NULL;
-stream_t* stream2=NULL;
-demuxer_t* demuxer2=NULL;
-demux_stream_t *d_audio=NULL;
-demux_stream_t *d_video=NULL;
-demux_stream_t *d_dvdsub=NULL;
-sh_audio_t *sh_audio=NULL;
-sh_video_t *sh_video=NULL;
-int file_format=DEMUXER_TYPE_UNKNOWN;
-int i=DEMUXER_TYPE_UNKNOWN;
-void *vobsub_writer=NULL;
-s_frame_data frame_data = { .start = NULL, .in_size = 0, .frame_time = 0., .already_read = 0 };
+if(!line) return 1;
+if(strstr(line,"inputid")) return 0;
+if(vmixer_inputid==vmixer_vmixerid) {
+printf("OK: %d:%d %s",vmixer_inputid,vmixer_vmixerid,line);
+  return 0;
+}
+return 1;
+}
 
-uint32_t ptimer_start;
-uint32_t audiorate=0;
-uint32_t videorate=0;
-uint32_t audiosamples=1;
-uint32_t videosamples=1;
-uint32_t skippedframes=0;
-uint32_t duplicatedframes=0;
-uint32_t badframes=0;
+MEContext *new_mectx(){
+  MEContext *mectx;
+  
+  mectx=malloc(sizeof(MEContext));
+  memset(mectx,0,sizeof(MEContext));
+  mectx->file_format=DEMUXER_TYPE_UNKNOWN;
+  mectx->audiosamples=1;
+  mectx->next_frameno=-1;
+  mectx->videosamples=1;
+  mectx->ao_data.outburst=OUTBURST;
+  mectx->ao_data.buffersize=-1;
+  return mectx;
+}
 
-muxer_stream_t* mux_a=NULL;
-muxer_stream_t* mux_v=NULL;
-off_t muxer_f_size=0;
-
-double v_pts_corr=0;
-double v_timer_corr=0;
-
-m_entry_t* filelist = NULL;
-char* filename=NULL;
-
-int decoded_frameno=0;
-int next_frameno=-1;
-int curfile=0;
-int new_srate=0;
-
-unsigned int timer_start=0;
-ao_data_t ao_data = {0,0,0,0,OUTBURST,-1,0};
-
-audio_encoding_params_t aparams;
-audio_encoder_t *aencoder = NULL;
-
-  mp_msg_init();
-
-  for(i=1; i<argc; i++)
-    if(!strcmp(argv[i], "-really-quiet"))
-      verbose= -10;
-
-  mp_msg(MSGT_CPLAYER,MSGL_INFO, "MEncoder " VERSION " (C) 2000-2007 MPlayer Team\n");
-
-  /* Test for cpu capabilities (and corresponding OS support) for optimizing */
-  GetCpuCaps(&gCpuCaps);
-#ifdef ARCH_X86
-  mp_msg(MSGT_CPLAYER,MSGL_INFO,"CPUflags: Type: %d MMX: %d MMX2: %d 3DNow: %d 3DNow2: %d SSE: %d SSE2: %d\n",
-      gCpuCaps.cpuType,gCpuCaps.hasMMX,gCpuCaps.hasMMX2,
-      gCpuCaps.has3DNow, gCpuCaps.has3DNowExt,
-      gCpuCaps.hasSSE, gCpuCaps.hasSSE2);
-#ifdef RUNTIME_CPUDETECT
-  mp_msg(MSGT_CPLAYER,MSGL_INFO, MSGTR_CompiledWithRuntimeDetection);
-#else
-  mp_msg(MSGT_CPLAYER,MSGL_INFO, MSGTR_CompiledWithCPUExtensions);
-#ifdef HAVE_MMX
-  mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX");
-#endif
-#ifdef HAVE_MMX2
-  mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX2");
-#endif
-#ifdef HAVE_3DNOW
-  mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNow");
-#endif
-#ifdef HAVE_3DNOWEX
-  mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNowEx");
-#endif
-#ifdef HAVE_SSE
-  mp_msg(MSGT_CPLAYER,MSGL_INFO," SSE");
-#endif
-#ifdef HAVE_SSE2
-  mp_msg(MSGT_CPLAYER,MSGL_INFO," SSE2");
-#endif
-  mp_msg(MSGT_CPLAYER,MSGL_INFO,"\n\n");
-#endif
-#endif
-
-#if defined(WIN32) && defined(USE_WIN32DLL)
-  set_path_env();
-#endif /*WIN32 && USE_WIN32DLL*/
+static void *vmixer_grabber(void *data){
+  MEContext* mectx = data;
   
-  InitTimer();
-
-// check codec.conf
-if(!codecs_file || !parse_codec_cfg(codecs_file)){
-  if(!parse_codec_cfg(get_path("codecs.conf"))){
-    if(!parse_codec_cfg(MPLAYER_CONFDIR "/codecs.conf")){
-      if(!parse_codec_cfg(NULL)){
-	mencoder_exit(1,NULL);
-      }
-      mp_msg(MSGT_MENCODER,MSGL_V,MSGTR_BuiltinCodecsConf);
-    }
-  }
+  main_loop(mectx,mectx->input_file,0,mectx->vmixerid);
+  if(mectx->sh_audio){ uninit_audio(mectx->sh_audio);mectx->sh_audio=NULL; }
+  if(mectx->sh_video){ uninit_video(mectx->sh_video);mectx->sh_video=NULL; }
+  if(mectx->demuxer) free_demuxer(mectx->demuxer);
+  if(mectx->stream) free_stream(mectx->stream); // kill cache thread
 }
 
- mconfig = m_config_new();
- m_config_register_options(mconfig,mencoder_opts);
- parse_cfgfiles(mconfig);
- filelist = m_config_parse_me_command_line(mconfig, argc, argv);
- if(!filelist) mencoder_exit(1, MSGTR_ErrorParsingCommandLine);
+int vmixerinit(MEContext *mectx, int vmixerid){
+  MEContext* pmectx = new_mectx();
+  m_config_t* mconfig;
+  m_obj_settings_t * vf_orig = vf_settings;
 
-{
-	char *extension;
-	
-	if (!out_filename) mencoder_exit(1,MSGTR_MissingOutputFilename);
-	extension=strrchr(out_filename,'.');
-	if (extension != NULL && strlen(extension) > 3 && strlen(extension) < 6)
-	{
-		extension++;
-		
-		switch (out_file_format)
-		{
-			case MUXER_TYPE_AVI:
-			if (strcasecmp(extension,"avi"))
-				mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_MencoderWrongFormatAVI);
-			break;
+  if(vmixerid) vf_settings=NULL;
+  vmixer_input_filename=NULL;
+  mconfig = m_config_new();
+  m_config_register_options(mconfig, mencoder_vmixer_opts);
+  vmixer_vmixerid=vmixerid;
+  vmixer_inputid=0;
+  if(m_config_parse_config_file(mconfig, vmixer_filename, &skip_line) < 0)
+    return 0;
+  if(!vmixerid) return 1;
+  if(!vmixer_input_filename) return 0;
+ 
+  pmectx->input_file=vmixer_input_filename;
+  pmectx->vmixerid=vmixerid;
+  pmectx->vf_settings=vf_settings;
+  vf_settings=vf_orig;
+//  main_loop(pmectx,pmectx->input_file,0,pmectx->vmixerid);
+  pthread_create(&pmectx->thread, NULL, vmixer_grabber, pmectx);
+  while (mectx->next) mectx=mectx->next;
+  mectx->next=pmectx;
+//  pthread_join(pmectx->thread, NULL);
+//  pthread_mutex_destroy(&mectx->mutex);
+return 1;
+}
 
-			case MUXER_TYPE_MPEG:
-			if (strcasecmp(extension,"mpg") &&
-				strcasecmp(extension,"mpeg") &&
-				strcasecmp(extension,"vob")) 
-				mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_MencoderWrongFormatMPG);
-			break;
-		}
-	}
-}				
- /* Display what configure line was used */
- mp_msg(MSGT_MENCODER, MSGL_V, "Configuration: " CONFIGURATION "\n");
-
-
-if (frameno_filename) {
-  stream2=open_stream(frameno_filename,0,&i);
-  if(stream2){
-    demuxer2=demux_open(stream2,DEMUXER_TYPE_AVI,-1,-1,-2,NULL);
-    if(demuxer2) mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_UsingPass3ControlFile, frameno_filename);
-    else mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_FormatNotRecognized);
+int vmixerstart(MEContext *mectx){
+  mectx=mectx->next;
+  while(mectx) {
+    if(!mectx->start) return 0;
+    mectx=mectx->next;
   }
+  return 1;
 }
 
-#ifdef WIN32
-  if(proc_priority){
-    int i;
-    for(i=0; priority_presets_defs[i].name; i++){
-      if(strcasecmp(priority_presets_defs[i].name, proc_priority) == 0)
-        break;
-    }
-    mp_msg(MSGT_CPLAYER,MSGL_STATUS,MSGTR_SettingProcessPriority,
-					priority_presets_defs[i].name);
-    SetPriorityClass(GetCurrentProcess(), priority_presets_defs[i].prio);
-  }
-#endif	
+int main_loop(MEContext *mectx, char *filename, int curfile, int vmixerid){
+  char *ofilename;
 
-// check font
-#ifdef HAVE_FREETYPE
-  init_freetype();
-#endif
-#ifdef HAVE_FONTCONFIG
-  if(!font_fontconfig)
-  {
-#endif
-#ifdef HAVE_BITMAP_FONT
-  if(font_name){
-       vo_font=read_font_desc(font_name,font_factor,verbose>1);
-       if(!vo_font) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadFont,font_name);
-  } else {
-      // try default:
-       vo_font=read_font_desc(get_path("font/font.desc"),font_factor,verbose>1);
-       if(!vo_font)
-       vo_font=read_font_desc(MPLAYER_DATADIR "/font/font.desc",font_factor,verbose>1);
-  }
-#endif
-#ifdef HAVE_FONTCONFIG
-  }
-#endif
+  mectx->stream=open_stream(filename,0,&mectx->file_format);
 
-  vo_init_osd();
-
-  /* HACK, for some weird reason, push() has to be called twice,
-     otherwise options are not saved correctly */
-  m_config_push(mconfig);
-play_next_file:
-  m_config_push(mconfig);
-  m_entry_set_options(mconfig,&filelist[curfile]);
-  filename = filelist[curfile].name;
- 
-  if(!filename){
-	mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_MissingFilename);
-	mencoder_exit(1,NULL);
-  }
-  stream=open_stream(filename,0,&file_format);
-
-  if(!stream){
+  if(!mectx->stream){
 	mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_CannotOpenFile_Device);
 	mencoder_exit(1,NULL);
   }
 
-  mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_OpenedStream, file_format, (int)(stream->start_pos), (int)(stream->end_pos));
+  mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_OpenedStream, mectx->file_format, (int)(mectx->stream->start_pos), (int)(mectx->stream->end_pos));
 
 #ifdef USE_DVDREAD
-if(stream->type==STREAMTYPE_DVD){
-  if(audio_lang && audio_id==-1) audio_id=dvd_aid_from_lang(stream,audio_lang);
-  if(dvdsub_lang && dvdsub_id==-2) dvdsub_id=dvd_sid_from_lang(stream,dvdsub_lang);
+if(mectx->stream->type==STREAMTYPE_DVD){
+  if(audio_lang && audio_id==-1) audio_id=dvd_aid_from_lang(mectx->stream,audio_lang);
+  if(dvdsub_lang && dvdsub_id==-2) dvdsub_id=dvd_sid_from_lang(mectx->stream,dvdsub_lang);
 }
 #endif
 
 #ifdef USE_DVDNAV
-if(stream->type==STREAMTYPE_DVDNAV){
-  if(audio_lang && audio_id==-1) audio_id=dvdnav_aid_from_lang(stream,audio_lang);
-  if(dvdsub_lang && dvdsub_id==-2) dvdsub_id=dvdnav_sid_from_lang(stream,dvdsub_lang);
+if(mectx->stream->type==STREAMTYPE_DVDNAV){
+  if(audio_lang && audio_id==-1) audio_id=dvdnav_aid_from_lang(mectx->stream,audio_lang);
+  if(dvdsub_lang && dvdsub_id==-2) dvdsub_id=dvdnav_sid_from_lang(mectx->stream,dvdsub_lang);
 }
 #endif
 
-  stream->start_pos+=seek_to_byte;
+  mectx->stream->start_pos+=seek_to_byte;
 
-  if(stream_cache_size>0) stream_enable_cache(stream,stream_cache_size*1024,0,0);
+  if(stream_cache_size>0) stream_enable_cache(mectx->stream,stream_cache_size*1024,0,0);
 
-  if(demuxer2) audio_id=-2; /* do NOT read audio packets... */
+  if(mectx->demuxer2) audio_id=-2; /* do NOT read audio packets... */
 
-  //demuxer=demux_open(stream,file_format,video_id,audio_id,dvdsub_id);
-  demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id,filename);
-  if(!demuxer){
+  //mectx->demuxer=demux_open(mectx->stream,mectx->file_format,video_id,audio_id,dvdsub_id);
+if(vmixerid)	// FIXME nosound
+  mectx->demuxer=demux_open(mectx->stream,mectx->file_format,-1,video_id,dvdsub_id,filename);
+else
+  mectx->demuxer=demux_open(mectx->stream,mectx->file_format,audio_id,video_id,dvdsub_id,filename);
+  if(!mectx->demuxer){
     mp_msg(MSGT_DEMUXER, MSGL_FATAL, MSGTR_FormatNotRecognized);
     mp_msg(MSGT_DEMUXER, MSGL_FATAL, MSGTR_CannotOpenDemuxer);
 	mencoder_exit(1,NULL);
   }
 
-d_audio=demuxer2 ? demuxer2->audio : demuxer->audio;
-d_video=demuxer->video;
-d_dvdsub=demuxer->sub;
-sh_audio=d_audio->sh;
-sh_video=d_video->sh;
+mectx->d_audio=mectx->demuxer2 ? mectx->demuxer2->audio : mectx->demuxer->audio;
+mectx->d_video=mectx->demuxer->video;
+mectx->d_dvdsub=mectx->demuxer->sub;
+mectx->sh_audio=mectx->d_audio->sh;
+mectx->sh_video=mectx->d_video->sh;
 
-  if(!sh_video)
+  if(!mectx->sh_video)
   {
 	mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_VideoStreamRequired); 
 	mencoder_exit(1,NULL);
   }
 
-  if(!video_read_properties(sh_video)){
+  if(!video_read_properties(mectx->sh_video)){
       mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_CannotReadVideoProperties);
       mencoder_exit(1,NULL);
   }
 
   mp_msg(MSGT_MENCODER,MSGL_INFO, MSGTR_FilefmtFourccSizeFpsFtime,
-   demuxer->file_format,sh_video->format, sh_video->disp_w,sh_video->disp_h,
-   sh_video->fps,sh_video->frametime
+   mectx->demuxer->file_format,mectx->sh_video->format, mectx->sh_video->disp_w,mectx->sh_video->disp_h,
+   mectx->sh_video->fps,mectx->sh_video->frametime
   );
 
   if(force_fps){
-    sh_video->fps=force_fps;
-    sh_video->frametime=1.0f/sh_video->fps;
-    mp_msg(MSGT_MENCODER,MSGL_INFO,MSGTR_ForcingInputFPS, sh_video->fps);
+    mectx->sh_video->fps=force_fps;
+    mectx->sh_video->frametime=1.0f/mectx->sh_video->fps;
+    mp_msg(MSGT_MENCODER,MSGL_INFO,MSGTR_ForcingInputFPS, mectx->sh_video->fps);
   }
 
-  if(sh_audio && out_audio_codec<0){
+  if(mectx->sh_audio && out_audio_codec<0){
     if(audio_id==-2)
 	mp_msg(MSGT_MENCODER,MSGL_ERR,MSGTR_DemuxerDoesntSupportNosound);
     mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_NoAudioEncoderSelected);
     mencoder_exit(1,NULL);
   }
-  if(sh_video && out_video_codec<0){
+  if(mectx->sh_video && out_video_codec<0){
     mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_NoVideoEncoderSelected);
     mencoder_exit(1,NULL);
   }
 
-if(sh_audio && (out_audio_codec || seek_to_sec || !sh_audio->wf || playback_speed != 1.0)){
+if(mectx->sh_audio && (out_audio_codec || seek_to_sec || !mectx->sh_audio->wf || playback_speed != 1.0)){
   // Go through the codec.conf and find the best codec...
   mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
-  if(!init_best_audio_codec(sh_audio,audio_codec_list,audio_fm_list)){
-    sh_audio=d_audio->sh=NULL; // failed to init :(
+  if(!init_best_audio_codec(mectx->sh_audio,audio_codec_list,audio_fm_list)){
+    mectx->sh_audio=mectx->d_audio->sh=NULL; // failed to init :(
   }
   mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
 }
 
-  if (sh_audio) {
-    new_srate = sh_audio->samplerate;
+  if (mectx->sh_audio) {
+    mectx->new_srate = mectx->sh_audio->samplerate;
     if (playback_speed != 1.0) {
-        new_srate *= playback_speed;
+        mectx->new_srate *= playback_speed;
         // limits are taken from libaf/af_resample.c
-        if (new_srate < 8000) new_srate = 8000;
-        if (new_srate > 192000) new_srate = 192000;
-        playback_speed = (float)new_srate / (float)sh_audio->samplerate;
+        if (mectx->new_srate < 8000) mectx->new_srate = 8000;
+        if (mectx->new_srate > 192000) mectx->new_srate = 192000;
+        playback_speed = (float)mectx->new_srate / (float)mectx->sh_audio->samplerate;
     }
   }
 
@@ -666,7 +552,7 @@
 // check .sub
 //  current_module="read_subtitles_file";
   if(sub_name && sub_name[0]){
-    subdata=sub_read_file(sub_name[0], sh_video->fps);
+    subdata=sub_read_file(sub_name[0], mectx->sh_video->fps);
     if(!subdata) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub,sub_name[0]);
   } else
   if(sub_auto && filename) { // auto load sub file ...
@@ -675,7 +561,7 @@
     char *psub = get_path( "sub/" );
     tmp = sub_filenames((psub ? psub : ""), filename);
     free(psub);
-    subdata=sub_read_file(tmp[0], sh_video->fps);
+    subdata=sub_read_file(tmp[0], mectx->sh_video->fps);
     while (tmp[i])
       free(tmp[i++]);
     free(tmp);
@@ -688,14 +574,14 @@
     unsigned int palette[16], width, height;
     unsigned char tmp[3] = { 0, 0, 0 };
     if (spudec_ifo && vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1, dvdsub_id, tmp) >= 0)
-	vobsub_writer = vobsub_out_open(vobsub_out, palette, sh_video->disp_w, sh_video->disp_h,
+	mectx->vobsub_writer = vobsub_out_open(vobsub_out, palette, mectx->sh_video->disp_w, mectx->sh_video->disp_h,
 					vobsub_out_id?vobsub_out_id:(char *)tmp, vobsub_out_index);
 #ifdef USE_DVDREAD
-    if (vobsub_writer == NULL) {
+    if (mectx->vobsub_writer == NULL) {
 	char tmp[3];
-	if (vobsub_out_id == NULL && stream->type == STREAMTYPE_DVD) {
+	if (vobsub_out_id == NULL && mectx->stream->type == STREAMTYPE_DVD) {
 	    int i;
-	    dvd_priv_t *dvd = (dvd_priv_t*)stream->priv;
+	    dvd_priv_t *dvd = (dvd_priv_t*)mectx->stream->priv;
 	    for (i = 0; i < dvd->nr_of_subtitles; ++i)
 		if (dvd->subtitles[i].id == dvdsub_id) {
 		    tmp[0] = (dvd->subtitles[i].language >> 8) & 0xff;
@@ -705,8 +591,8 @@
 		    break;
 		}
 	}
-	vobsub_writer=vobsub_out_open(vobsub_out, stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL,
-				      sh_video->disp_w, sh_video->disp_h, vobsub_out_id, vobsub_out_index);
+	mectx->vobsub_writer=vobsub_out_open(vobsub_out, mectx->stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(mectx->stream->priv))->cur_pgc->palette:NULL,
+				      mectx->sh_video->disp_w, mectx->sh_video->disp_h, vobsub_out_id, vobsub_out_index);
     }
 #endif
 }
@@ -714,12 +600,12 @@
 if (spudec_ifo) {
   unsigned int palette[16], width, height;
   if (vobsub_parse_ifo(NULL,spudec_ifo, palette, &width, &height, 1, -1, NULL) >= 0)
-    vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h);
+    vo_spudec=spudec_new_scaled(palette, mectx->sh_video->disp_w, mectx->sh_video->disp_h);
 }
 #ifdef USE_DVDREAD
 if (vo_spudec==NULL) {
-vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL,
-			    sh_video->disp_w, sh_video->disp_h);
+vo_spudec=spudec_new_scaled(mectx->stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(mectx->stream->priv))->cur_pgc->palette:NULL,
+			    mectx->sh_video->disp_w, mectx->sh_video->disp_h);
 }
 #endif
 }
@@ -727,14 +613,25 @@
 // Apply current settings for forced subs
 spudec_set_forced_subs_only(vo_spudec,forced_subs_only);
 
-ostream = open_output_stream(out_filename, 0);
-if(!ostream) {
+if(vmixerid) {
+  ofilename=malloc(256);
+  snprintf(ofilename,256,"shmem://%d",vmixerid);
+  set_shmem_opts(SHMEM_SYNCREAD, 0, DEMUXER_TYPE_RAWVIDEO, IMGFMT_YV12, mectx->sh_video->disp_w, mectx->sh_video->disp_h);
+  mectx->ostream = open_output_stream(ofilename, 0);
+  free(ofilename);
+} else
+  mectx->ostream = open_output_stream(out_filename, 0);
+if(!mectx->ostream) {
   mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_CannotOpenOutputFile, out_filename);
   mencoder_exit(1,NULL);
 }
 
-muxer=muxer_new_muxer(out_file_format,ostream);
-if(!muxer) {
+if(vmixerid)
+  mectx->muxer=muxer_new_muxer(MUXER_TYPE_SHMEM,mectx->ostream);
+else
+  mectx->muxer=muxer_new_muxer(out_file_format,mectx->ostream);
+
+if(!mectx->muxer) {
   mp_msg(MSGT_MENCODER, MSGL_FATAL, MSGTR_CannotInitializeMuxer);
   mencoder_exit(1,NULL);
 }
@@ -743,77 +640,80 @@
 if(out_file_format == MUXER_TYPE_MPEG) audio_preload = 0;
 #endif
 
-muxer->audio_delay_fix = audio_delay_fix;
+mectx->muxer->audio_delay_fix = audio_delay_fix;
 
 // ============= VIDEO ===============
 
-mux_v=muxer_new_stream(muxer,MUXER_TYPE_VIDEO);
+mectx->mux_v=muxer_new_stream(mectx->muxer,MUXER_TYPE_VIDEO);
 
-mux_v->buffer_size=0x200000; // 2MB
-mux_v->buffer=malloc(mux_v->buffer_size);
+mectx->mux_v->buffer_size=0x200000; // 2MB
+mectx->mux_v->buffer=malloc(mectx->mux_v->buffer_size);
 
-mux_v->source=sh_video;
+mectx->mux_v->source=mectx->sh_video;
 
-mux_v->h.dwSampleSize=0; // VBR
+mectx->mux_v->h.dwSampleSize=0; // VBR
 #ifdef USE_LIBAVCODEC
 {
-    AVRational q= av_d2q(force_ofps?force_ofps:sh_video->fps*playback_speed, 30000);
-    mux_v->h.dwScale= q.den;
-    mux_v->h.dwRate = q.num;
+    AVRational q= av_d2q(force_ofps?force_ofps:mectx->sh_video->fps*playback_speed, 30000);
+    mectx->mux_v->h.dwScale= q.den;
+    mectx->mux_v->h.dwRate = q.num;
 }
 #else
-mux_v->h.dwScale=10000;
-mux_v->h.dwRate=mux_v->h.dwScale*(force_ofps?force_ofps:sh_video->fps*playback_speed);
+mectx->mux_v->h.dwScale=10000;
+mectx->mux_v->h.dwRate=mectx->mux_v->h.dwScale*(force_ofps?force_ofps:mectx->sh_video->fps*playback_speed);
 #endif
 
-mux_v->codec=out_video_codec;
+if(vmixerid)
+  mectx->mux_v->codec=VCODEC_SHMEM;
+else
+  mectx->mux_v->codec=out_video_codec;
 
-mux_v->bih=NULL;
+mectx->mux_v->bih=NULL;
 }
-sh_video->codec=NULL;
-sh_video->vfilter=NULL; // fixme!
+mectx->sh_video->codec=NULL;
+mectx->sh_video->vfilter=NULL; // fixme!
 
-switch(mux_v->codec){
+switch(mectx->mux_v->codec){
 case VCODEC_COPY:
 	if (!curfile) {
-		if (sh_video->bih) {
-			mux_v->bih=malloc(sh_video->bih->biSize);
-			memcpy(mux_v->bih, sh_video->bih, sh_video->bih->biSize);
+		if (mectx->sh_video->bih) {
+			mectx->mux_v->bih=malloc(mectx->sh_video->bih->biSize);
+			memcpy(mectx->mux_v->bih, mectx->sh_video->bih, mectx->sh_video->bih->biSize);
 		}
     else
     {
-	mux_v->bih=calloc(1,sizeof(BITMAPINFOHEADER));
-	mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
-	mux_v->bih->biWidth=sh_video->disp_w;
-	mux_v->bih->biHeight=sh_video->disp_h;
-	mux_v->bih->biCompression=sh_video->format;
-	mux_v->bih->biPlanes=1;
-	mux_v->bih->biBitCount=24; // FIXME!!!
-	mux_v->bih->biSizeImage=mux_v->bih->biWidth*mux_v->bih->biHeight*(mux_v->bih->biBitCount/8);
+	mectx->mux_v->bih=calloc(1,sizeof(BITMAPINFOHEADER));
+	mectx->mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
+	mectx->mux_v->bih->biWidth=mectx->sh_video->disp_w;
+	mectx->mux_v->bih->biHeight=mectx->sh_video->disp_h;
+	mectx->mux_v->bih->biCompression=mectx->sh_video->format;
+	mectx->mux_v->bih->biPlanes=1;
+	mectx->mux_v->bih->biBitCount=24; // FIXME!!!
+	mectx->mux_v->bih->biSizeImage=mectx->mux_v->bih->biWidth*mectx->mux_v->bih->biHeight*(mectx->mux_v->bih->biBitCount/8);
     }
 	}
     mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_VCodecFramecopy,
-	mux_v->bih->biWidth, mux_v->bih->biHeight,
-	mux_v->bih->biBitCount, mux_v->bih->biCompression);
+	mectx->mux_v->bih->biWidth, mectx->mux_v->bih->biHeight,
+	mectx->mux_v->bih->biBitCount, mectx->mux_v->bih->biCompression);
 
 	if (curfile) {
-		if (sh_video->bih) {
-			if ((mux_v->bih->biSize != sh_video->bih->biSize) ||
-			    memcmp(mux_v->bih, sh_video->bih, sh_video->bih->biSize))
+		if (mectx->sh_video->bih) {
+			if ((mectx->mux_v->bih->biSize != mectx->sh_video->bih->biSize) ||
+			    memcmp(mectx->mux_v->bih, mectx->sh_video->bih, mectx->sh_video->bih->biSize))
 			{
 				mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_VCodecFramecopy,
-				       sh_video->bih->biWidth, sh_video->bih->biHeight,
-				       sh_video->bih->biBitCount, sh_video->bih->biCompression);
+				       mectx->sh_video->bih->biWidth, mectx->sh_video->bih->biHeight,
+				       mectx->sh_video->bih->biBitCount, mectx->sh_video->bih->biCompression);
 				mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_FrameCopyFileMismatch);
 				mencoder_exit(1,NULL);
 			}
 		}
 		else {
-			if ((mux_v->bih->biWidth != sh_video->disp_w) ||
-			    (mux_v->bih->biHeight != sh_video->disp_h) ||
-			    (mux_v->bih->biCompression != sh_video->format)) {
+			if ((mectx->mux_v->bih->biWidth != mectx->sh_video->disp_w) ||
+			    (mectx->mux_v->bih->biHeight != mectx->sh_video->disp_h) ||
+			    (mectx->mux_v->bih->biCompression != mectx->sh_video->format)) {
 				mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_VCodecFramecopy,
-				       sh_video->disp_w, sh_video->disp_w, 24, sh_video->format);
+				       mectx->sh_video->disp_w, mectx->sh_video->disp_w, 24, mectx->sh_video->format);
 				mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_FrameCopyFileMismatch);
 				mencoder_exit(1,NULL);
 			}
@@ -822,54 +722,56 @@
     break;
 case VCODEC_FRAMENO:
 	if (!curfile) {
-    mux_v->bih=calloc(1,sizeof(BITMAPINFOHEADER));
-    mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
-    mux_v->bih->biWidth=sh_video->disp_w;
-    mux_v->bih->biHeight=sh_video->disp_h;
-    mux_v->bih->biPlanes=1;
-    mux_v->bih->biBitCount=24;
-    mux_v->bih->biCompression=mmioFOURCC('F','r','N','o');
-    mux_v->bih->biSizeImage=mux_v->bih->biWidth*mux_v->bih->biHeight*(mux_v->bih->biBitCount/8);
+    mectx->mux_v->bih=calloc(1,sizeof(BITMAPINFOHEADER));
+    mectx->mux_v->bih->biSize=sizeof(BITMAPINFOHEADER);
+    mectx->mux_v->bih->biWidth=mectx->sh_video->disp_w;
+    mectx->mux_v->bih->biHeight=mectx->sh_video->disp_h;
+    mectx->mux_v->bih->biPlanes=1;
+    mectx->mux_v->bih->biBitCount=24;
+    mectx->mux_v->bih->biCompression=mmioFOURCC('F','r','N','o');
+    mectx->mux_v->bih->biSizeImage=mectx->mux_v->bih->biWidth*mectx->mux_v->bih->biHeight*(mectx->mux_v->bih->biBitCount/8);
 	}
     break;
 default: {
-    static vf_instance_t * ve = NULL;
-  if (!ve) {
-    switch(mux_v->codec){
+  if (!mectx->ve) {
+    switch(mectx->mux_v->codec){
     case VCODEC_LIBAVCODEC:
-        sh_video->vfilter=vf_open_encoder(NULL,"lavc",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"lavc",(char *)mectx->mux_v); break;
     case VCODEC_RAW:
-        sh_video->vfilter=vf_open_encoder(NULL,"raw",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"raw",(char *)mectx->mux_v); break;
     case VCODEC_VFW:
-        sh_video->vfilter=vf_open_encoder(NULL,"vfw",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"vfw",(char *)mectx->mux_v); break;
     case VCODEC_LIBDV:
-        sh_video->vfilter=vf_open_encoder(NULL,"libdv",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"libdv",(char *)mectx->mux_v); break;
     case VCODEC_XVID:
-        sh_video->vfilter=vf_open_encoder(NULL,"xvid",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"xvid",(char *)mectx->mux_v); break;
     case VCODEC_QTVIDEO:
-        sh_video->vfilter=vf_open_encoder(NULL,"qtvideo",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"qtvideo",(char *)mectx->mux_v); break;
     case VCODEC_NUV:        
-        sh_video->vfilter=vf_open_encoder(NULL,"nuv",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"nuv",(char *)mectx->mux_v); break;
     case VCODEC_X264:
-        sh_video->vfilter=vf_open_encoder(NULL,"x264",(char *)mux_v); break;
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"x264",(char *)mectx->mux_v); break;
+    case VCODEC_SHMEM:
+        mectx->sh_video->vfilter=vf_open_encoder(NULL,"shmem",(char *)mectx->mux_v); break;
     }
-    if(!mux_v->bih || !sh_video->vfilter){
+    if(!mectx->mux_v->bih || !mectx->sh_video->vfilter){
         mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_EncoderOpenFailed);
         mencoder_exit(1,NULL);
     }
-    ve = sh_video->vfilter;
-  } else sh_video->vfilter = ve;
+    mectx->ve = mectx->sh_video->vfilter;
+  } else mectx->sh_video->vfilter = mectx->ve;
     // append 'expand' filter, it fixes stride problems and renders osd:
     if (auto_expand) {
       char* vf_args[] = { "osd", "1", NULL };
-      sh_video->vfilter=vf_open_filter(sh_video->vfilter,"expand",vf_args);
+      mectx->sh_video->vfilter=vf_open_filter(mectx->sh_video->vfilter,"expand",vf_args);
     }
-    sh_video->vfilter=append_filters(sh_video->vfilter);
+    if(mectx->vf_settings)
+      mectx->sh_video->vfilter=append_filters(mectx->sh_video->vfilter,mectx->vf_settings);
 
     mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
-    init_best_video_codec(sh_video,video_codec_list,video_fm_list);
+    init_best_video_codec(mectx->sh_video,video_codec_list,video_fm_list);
     mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
-    if(!sh_video->inited) mencoder_exit(1,NULL);
+    if(!mectx->sh_video->inited) mencoder_exit(1,NULL);
  }
 }
 
@@ -877,112 +779,115 @@
 /* force output fourcc to .. */
 if ((force_fourcc != NULL) && (strlen(force_fourcc) >= 4))
 {
-    mux_v->bih->biCompression = mmioFOURCC(force_fourcc[0], force_fourcc[1],
+    mectx->mux_v->bih->biCompression = mmioFOURCC(force_fourcc[0], force_fourcc[1],
 					    force_fourcc[2], force_fourcc[3]);
     mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_ForcingOutputFourcc,
-	mux_v->bih->biCompression, (char *)&mux_v->bih->biCompression);
+	mectx->mux_v->bih->biCompression, (char *)&mectx->mux_v->bih->biCompression);
 }
 
 if (! ignore_start)
-    muxer->audio_delay_fix -= sh_video->stream_delay;
+    mectx->muxer->audio_delay_fix -= mectx->sh_video->stream_delay;
 
-//if(demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf!
+//if(mectx->demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf!
 
 // ============= AUDIO ===============
-if(sh_audio){
+if(mectx->sh_audio){
 
 if (force_audiofmttag != -1) {
-	sh_audio->format = force_audiofmttag;
-	if (sh_audio->wf) {
-		sh_audio->wf->wFormatTag = sh_audio->format;
+	mectx->sh_audio->format = force_audiofmttag;
+	if (mectx->sh_audio->wf) {
+		mectx->sh_audio->wf->wFormatTag = mectx->sh_audio->format;
 	}
 	mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_ForcingOutputAudiofmtTag,
 	       force_audiofmttag);
 }
 
-mux_a=muxer_new_stream(muxer,MUXER_TYPE_AUDIO);
+mectx->mux_a=muxer_new_stream(mectx->muxer,MUXER_TYPE_AUDIO);
 
-mux_a->buffer_size=0x100000; //16384;
-mux_a->buffer=malloc(mux_a->buffer_size);
-if (!mux_a->buffer)
+mectx->mux_a->buffer_size=0x100000; //16384;
+mectx->mux_a->buffer=malloc(mectx->mux_a->buffer_size);
+if (!mectx->mux_a->buffer)
     mencoder_exit(1,MSGTR_MemAllocFailed);
 
-mux_a->source=sh_audio;
+mectx->mux_a->source=mectx->sh_audio;
 
-mux_a->codec=out_audio_codec;
+if(vmixerid)
+  mectx->mux_a->codec=ACODEC_PCM;
+else
+  mectx->mux_a->codec=out_audio_codec;
 
-ao_data.samplerate = force_srate;
-ao_data.channels = 0;
-ao_data.format = audio_output_format;
-if(!init_audio_filters(sh_audio,
+mectx->ao_data.samplerate = force_srate;
+mectx->ao_data.channels = 0;
+mectx->ao_data.format = audio_output_format;
+if(!init_audio_filters(mectx->sh_audio,
    // input:
-   new_srate,
+   mectx->new_srate,
    // output:
-   &ao_data.samplerate, &ao_data.channels, &ao_data.format)) {
+   &mectx->ao_data.samplerate, &mectx->ao_data.channels, &mectx->ao_data.format)) {
      mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_AudioFilterChainPreinitError);
      mencoder_exit(1, NULL);
    }
 
-aparams.channels = ao_data.channels;
-aparams.sample_rate = ao_data.samplerate;
-aparams.audio_preload = 1000 * audio_preload;
-if(mux_a->codec != ACODEC_COPY) {
-    aencoder = new_audio_encoder(mux_a, &aparams);
-    if(!aencoder)
+mectx->aparams.channels = mectx->ao_data.channels;
+mectx->aparams.sample_rate = mectx->ao_data.samplerate;
+mectx->aparams.audio_preload = 1000 * audio_preload;
+if(mectx->mux_a->codec != ACODEC_COPY) {
+    mectx->aencoder = new_audio_encoder(mectx->mux_a, &mectx->aparams);
+    if(!mectx->aencoder)
         mencoder_exit(1, NULL);
-    if(!init_audio_filters(sh_audio, 
-        new_srate,
-        &aparams.sample_rate, &aparams.channels, &aencoder->input_format)) {
+    if(!init_audio_filters(mectx->sh_audio, 
+        mectx->new_srate,
+        &mectx->aparams.sample_rate, &mectx->aparams.channels, &mectx->aencoder->input_format)) {
       mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_NoMatchingFilter);
       mencoder_exit(1,NULL);
     }
 }
-switch(mux_a->codec){
+switch(mectx->mux_a->codec){
 case ACODEC_COPY:
     if (playback_speed != 1.0) mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_NoSpeedWithFrameCopy);
-    if (sh_audio->format >= 0x10000) {
-	mp_msg(MSGT_MENCODER,MSGL_ERR,MSGTR_CantCopyAudioFormat, sh_audio->format);
+    if (mectx->sh_audio->format >= 0x10000) {
+	mp_msg(MSGT_MENCODER,MSGL_ERR,MSGTR_CantCopyAudioFormat, mectx->sh_audio->format);
 	mencoder_exit(1,NULL);
     }
-    if (sh_audio->wf){
-	mux_a->wf=malloc(sizeof(WAVEFORMATEX) + sh_audio->wf->cbSize);
-	memcpy(mux_a->wf, sh_audio->wf, sizeof(WAVEFORMATEX) + sh_audio->wf->cbSize);
-	if(!sh_audio->i_bps) sh_audio->i_bps=mux_a->wf->nAvgBytesPerSec;
+    if (mectx->sh_audio->wf){
+	mectx->mux_a->wf=malloc(sizeof(WAVEFORMATEX) + mectx->sh_audio->wf->cbSize);
+	memcpy(mectx->mux_a->wf, mectx->sh_audio->wf, sizeof(WAVEFORMATEX) + mectx->sh_audio->wf->cbSize);
+	if(!mectx->sh_audio->i_bps) mectx->sh_audio->i_bps=mectx->mux_a->wf->nAvgBytesPerSec;
     } else {
-	mux_a->wf = malloc(sizeof(WAVEFORMATEX));
-	mux_a->wf->nBlockAlign = 1; //mux_a->h.dwSampleSize;
-	mux_a->wf->wFormatTag = sh_audio->format;
-	mux_a->wf->nChannels = sh_audio->channels;
-	mux_a->wf->nSamplesPerSec = sh_audio->samplerate;
-	mux_a->wf->nAvgBytesPerSec=sh_audio->i_bps; //mux_a->h.dwSampleSize*mux_a->wf->nSamplesPerSec;
-	mux_a->wf->wBitsPerSample = 16; // FIXME
-	mux_a->wf->cbSize=0; // FIXME for l3codeca.acm
+	mectx->mux_a->wf = malloc(sizeof(WAVEFORMATEX));
+	mectx->mux_a->wf->nBlockAlign = 1; //mectx->mux_a->h.dwSampleSize;
+	mectx->mux_a->wf->wFormatTag = mectx->sh_audio->format;
+	mectx->mux_a->wf->nChannels = mectx->sh_audio->channels;
+	mectx->mux_a->wf->nSamplesPerSec = mectx->sh_audio->samplerate;
+	mectx->mux_a->wf->nAvgBytesPerSec=mectx->sh_audio->i_bps; //mectx->mux_a->h.dwSampleSize*mectx->mux_a->wf->nSamplesPerSec;
+	mectx->mux_a->wf->wBitsPerSample = 16; // FIXME
+	mectx->mux_a->wf->cbSize=0; // FIXME for l3codeca.acm
     }
-    if(sh_audio->audio.dwScale){
-	mux_a->h.dwSampleSize=sh_audio->audio.dwSampleSize;
-	mux_a->h.dwScale=sh_audio->audio.dwScale;
-	mux_a->h.dwRate=sh_audio->audio.dwRate;
+    if(mectx->sh_audio->audio.dwScale){
+	mectx->mux_a->h.dwSampleSize=mectx->sh_audio->audio.dwSampleSize;
+	mectx->mux_a->h.dwScale=mectx->sh_audio->audio.dwScale;
+	mectx->mux_a->h.dwRate=mectx->sh_audio->audio.dwRate;
     } else {
-	mux_a->h.dwSampleSize=mux_a->wf->nBlockAlign;
-	mux_a->h.dwScale=mux_a->h.dwSampleSize;
-	mux_a->h.dwRate=mux_a->wf->nAvgBytesPerSec;
+	mectx->mux_a->h.dwSampleSize=mectx->mux_a->wf->nBlockAlign;
+	mectx->mux_a->h.dwScale=mectx->mux_a->h.dwSampleSize;
+	mectx->mux_a->h.dwRate=mectx->mux_a->wf->nAvgBytesPerSec;
     }
-    mux_a->h.dwRate *= playback_speed;
-    mux_a->wf->nSamplesPerSec *= playback_speed;
+    mectx->mux_a->h.dwRate *= playback_speed;
+    mectx->mux_a->wf->nSamplesPerSec *= playback_speed;
     mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_ACodecFramecopy,
-	mux_a->wf->wFormatTag, mux_a->wf->nChannels, mux_a->wf->nSamplesPerSec,
-	mux_a->wf->wBitsPerSample, mux_a->wf->nAvgBytesPerSec, mux_a->h.dwSampleSize);
+	mectx->mux_a->wf->wFormatTag, mectx->mux_a->wf->nChannels, mectx->mux_a->wf->nSamplesPerSec,
+	mectx->mux_a->wf->wBitsPerSample, mectx->mux_a->wf->nAvgBytesPerSec, mectx->mux_a->h.dwSampleSize);
     break;
 }
 
-if ( mp_msg_test(MSGT_MENCODER,MSGL_DBG2) ) print_wave_header(mux_a->wf, MSGL_DBG2);
+if ( mp_msg_test(MSGT_MENCODER,MSGL_DBG2) ) print_wave_header(mectx->mux_a->wf, MSGL_DBG2);
 
 if (! ignore_start)
-    muxer->audio_delay_fix += sh_audio->stream_delay;
+    mectx->muxer->audio_delay_fix += mectx->sh_audio->stream_delay;
 
 } // if(sh_audio)
 
-decoded_frameno=0;
+mectx->decoded_frameno=0;
 
 signal(SIGINT,exit_sighandler);  // Interrupt from keyboard
 signal(SIGQUIT,exit_sighandler); // Quit from keyboard
@@ -990,58 +895,58 @@
 signal(SIGHUP,exit_sighandler);  // broken terminal line
 signal(SIGPIPE,exit_sighandler); // broken pipe
 
-timer_start=GetTimerMS();
+mectx->timer_start=GetTimerMS();
 } // if (!curfile) // if this was the first file.
 else {
-	if (!mux_a != !sh_audio) {
+	if (!mectx->mux_a != !mectx->sh_audio) {
 		mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_NoAudioFileMismatch);
 		mencoder_exit(1,NULL);
 	}
-	if (sh_audio && mux_a->codec == ACODEC_COPY) {
+	if (mectx->sh_audio && mectx->mux_a->codec == ACODEC_COPY) {
 		if (playback_speed != 1.0) mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_NoSpeedWithFrameCopy);
 		mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_ACodecFramecopy,
-		       mux_a->wf->wFormatTag, mux_a->wf->nChannels, mux_a->wf->nSamplesPerSec,
-		       mux_a->wf->wBitsPerSample, mux_a->wf->nAvgBytesPerSec, mux_a->h.dwSampleSize);
-		if (sh_audio->wf) {
-			if ((mux_a->wf->wFormatTag != sh_audio->wf->wFormatTag) ||
-			    (mux_a->wf->nChannels != sh_audio->wf->nChannels) ||
-			    (mux_a->wf->nSamplesPerSec != sh_audio->wf->nSamplesPerSec * playback_speed))
+		       mectx->mux_a->wf->wFormatTag, mectx->mux_a->wf->nChannels, mectx->mux_a->wf->nSamplesPerSec,
+		       mectx->mux_a->wf->wBitsPerSample, mectx->mux_a->wf->nAvgBytesPerSec, mectx->mux_a->h.dwSampleSize);
+		if (mectx->sh_audio->wf) {
+			if ((mectx->mux_a->wf->wFormatTag != mectx->sh_audio->wf->wFormatTag) ||
+			    (mectx->mux_a->wf->nChannels != mectx->sh_audio->wf->nChannels) ||
+			    (mectx->mux_a->wf->nSamplesPerSec != mectx->sh_audio->wf->nSamplesPerSec * playback_speed))
 			{
 				mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_ACodecFramecopy,
-				       sh_audio->wf->wFormatTag, sh_audio->wf->nChannels, (int)(sh_audio->wf->nSamplesPerSec * playback_speed),
-				       sh_audio->wf->wBitsPerSample, sh_audio->wf->nAvgBytesPerSec, 0);
+				       mectx->sh_audio->wf->wFormatTag, mectx->sh_audio->wf->nChannels, (int)(mectx->sh_audio->wf->nSamplesPerSec * playback_speed),
+				       mectx->sh_audio->wf->wBitsPerSample, mectx->sh_audio->wf->nAvgBytesPerSec, 0);
 				mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_AudioCopyFileMismatch);
 				mencoder_exit(1,NULL);
 			}
 		} else {
-			if ((mux_a->wf->wFormatTag != sh_audio->format) ||
-			    (mux_a->wf->nChannels != sh_audio->channels) ||
-			    (mux_a->wf->nSamplesPerSec != sh_audio->samplerate * playback_speed))
+			if ((mectx->mux_a->wf->wFormatTag != mectx->sh_audio->format) ||
+			    (mectx->mux_a->wf->nChannels != mectx->sh_audio->channels) ||
+			    (mectx->mux_a->wf->nSamplesPerSec != mectx->sh_audio->samplerate * playback_speed))
 			{
 				mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_ACodecFramecopy,
-				       sh_audio->wf->wFormatTag, sh_audio->wf->nChannels, (int)(sh_audio->wf->nSamplesPerSec * playback_speed),
-				       sh_audio->wf->wBitsPerSample, sh_audio->wf->nAvgBytesPerSec, 0);
+				       mectx->sh_audio->wf->wFormatTag, mectx->sh_audio->wf->nChannels, (int)(mectx->sh_audio->wf->nSamplesPerSec * playback_speed),
+				       mectx->sh_audio->wf->wBitsPerSample, mectx->sh_audio->wf->nAvgBytesPerSec, 0);
 				mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_AudioCopyFileMismatch);
 				mencoder_exit(1,NULL);
 			}
 		}
-	} else if (sh_audio) {
-		int out_srate = mux_a->wf->nSamplesPerSec;
-		int out_channels = mux_a->wf->nChannels;
-		int out_format = aencoder->input_format;
-		if (!init_audio_filters(sh_audio, new_srate,
+	} else if (mectx->sh_audio) {
+		int out_srate = mectx->mux_a->wf->nSamplesPerSec;
+		int out_channels = mectx->mux_a->wf->nChannels;
+		int out_format = mectx->aencoder->input_format;
+		if (!init_audio_filters(mectx->sh_audio, mectx->new_srate,
 					&out_srate, &out_channels,
 					&out_format)) {
 			mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_NoMatchingFilter);
 			mencoder_exit(1, NULL);
 		}
-		mux_a->wf->nSamplesPerSec = out_srate;
-		mux_a->wf->nChannels = out_channels;
+		mectx->mux_a->wf->nSamplesPerSec = out_srate;
+		mectx->mux_a->wf->nChannels = out_channels;
 	}
 }
 
 if (seek_to_sec) {
-    demux_seek(demuxer, seek_to_sec, audio_delay, 1);
+    demux_seek(mectx->demuxer, seek_to_sec, audio_delay, 1);
 //  there is 2 way to handle the -ss option in 3-pass mode:
 // > 1. do the first pass for the whole file, and use -ss for 2nd/3rd pases only
 // > 2. do all the 3 passes with the same -ss value
@@ -1061,7 +966,7 @@
 	}
 	}
 
-if(file_format == DEMUXER_TYPE_TV) 
+if(mectx->file_format == DEMUXER_TYPE_TV) 
 	{
 	mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_ZeroingAudioPreloadAndMaxPtsCorrection);
 	audio_preload = 0.0;
@@ -1069,7 +974,7 @@
 	}
 
 play_n_frames=play_n_frames_mf;
-if (curfile && end_at.type == END_AT_TIME) end_at.pos += mux_v->timer;
+if (curfile && end_at.type == END_AT_TIME) end_at.pos += mectx->mux_v->timer;
 
 if (edl_records) free_edl(edl_records);
 next_edl_record = edl_records = NULL;
@@ -1079,17 +984,17 @@
     next_edl_record = edl_records = edl_parse_file();
 }
 
-if (sh_audio && audio_delay != 0.) fixdelay(d_video, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
+if (mectx->sh_audio && audio_delay != 0.) fixdelay(mectx->d_video, mectx->d_audio, mectx->mux_a, &mectx->frame_data, mectx->mux_v->codec==VCODEC_COPY);
 
-while(!at_eof){
+while(!(at_eof || mectx->eof)){
 
     int blit_frame=0;
     float a_pts=0;
     float v_pts=0;
     int skip_flag=0; // 1=skip  -1=duplicate
 
-    if((end_at.type == END_AT_SIZE && end_at.pos <= stream_tell(muxer->stream))  ||
-       (end_at.type == END_AT_TIME && end_at.pos < mux_v->timer))
+    if((end_at.type == END_AT_SIZE && end_at.pos <= stream_tell(mectx->muxer->stream))  ||
+       (end_at.type == END_AT_TIME && end_at.pos < mectx->mux_v->timer))
         break;
 
     if(play_n_frames>=0){
@@ -1098,20 +1003,20 @@
     }
 
 goto_redo_edl:
-    if (next_edl_record && sh_video && sh_video->pts >= next_edl_record->start_sec) {
+    if (next_edl_record && mectx->sh_video && mectx->sh_video->pts >= next_edl_record->start_sec) {
         if (next_edl_record->action == EDL_SKIP && edl_seeking) {
-            float last_pos = d_video->pts;
+            float last_pos = mectx->d_video->pts;
             int result;
             mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: start [%f], stop [%f], length [%f]\n",
                    next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec);
 
-            result = edl_seek(next_edl_record, demuxer, d_audio, mux_a, &frame_data, mux_v->codec==VCODEC_COPY);
+            result = edl_seek(next_edl_record, mectx->demuxer, mectx->d_audio, mectx->mux_a, &mectx->frame_data, mectx->mux_v->codec==VCODEC_COPY);
 
-            if (result == 2) { at_eof=1; break; } // EOF
+            if (result == 2) { mectx->eof=1; break; } // EOF
             else if (result == 0) edl_seeking = 0; // no seeking
             else { // sucess
                 edl_muted = 0;
-                if (last_pos >= sh_video->pts) {
+                if (last_pos >= mectx->sh_video->pts) {
                     // backwards seek detected!! Forget about this EDL skip altogether.
                     next_edl_record = next_edl_record->next;
                 }
@@ -1120,7 +1025,7 @@
                        meaning if by some magical way we landed in the MIDDLE of a censored area,
                        in the next loop it will jump out of it.
                     */
-                    if (next_edl_record->stop_sec > sh_video->pts) break; // we got to the right place.
+                    if (next_edl_record->stop_sec > mectx->sh_video->pts) break; // we got to the right place.
                     if (next_edl_record->action == EDL_MUTE) edl_muted = !edl_muted; // toggle mute each time.
                 }
 
@@ -1135,19 +1040,18 @@
         }
     }
 
-
-if(sh_audio){
+if(mectx->sh_audio){
     // get audio:
-    while(mux_a->timer-audio_preload<mux_v->timer){
+    while(mectx->mux_a->timer-audio_preload<mectx->mux_v->timer){
         float tottime;
 	int len=0;
 
-	ptimer_start = GetTimerMS();
+	mectx->ptimer_start = GetTimerMS();
 	// CBR - copy 0.5 sec of audio
 	// or until the end of video:
-	tottime = stop_time(demuxer, mux_v);
+	tottime = stop_time(mectx->demuxer, mectx->mux_v);
 	if (tottime != -1) {
-		tottime -= mux_a->timer;
+		tottime -= mectx->mux_a->timer;
 		if (tottime > 1./audio_density) tottime = 1./audio_density;
 	}
 	else tottime = 1./audio_density;
@@ -1155,25 +1059,25 @@
 	// let's not output more audio than necessary
 	if (tottime <= 0) break;
 
-	if(aencoder)
+	if(mectx->aencoder)
 	{
-		if(mux_a->h.dwSampleSize) /* CBR */
+		if(mectx->mux_a->h.dwSampleSize) /* CBR */
 		{
-			if(aencoder->set_decoded_len)
+			if(mectx->aencoder->set_decoded_len)
 			{
-				len = mux_a->h.dwSampleSize*(int)(mux_a->h.dwRate*tottime);
-				aencoder->set_decoded_len(aencoder, len);
+				len = mectx->mux_a->h.dwSampleSize*(int)(mectx->mux_a->h.dwRate*tottime);
+				mectx->aencoder->set_decoded_len(mectx->aencoder, len);
 			}
 			else
-				len = aencoder->decode_buffer_size;
+				len = mectx->aencoder->decode_buffer_size;
 
-			len = dec_audio(sh_audio, aencoder->decode_buffer, len);
-			mux_a->buffer_len += aencoder->encode(aencoder, mux_a->buffer + mux_a->buffer_len, 
-				aencoder->decode_buffer, len, mux_a->buffer_size-mux_a->buffer_len);
-			if(mux_a->buffer_len < mux_a->wf->nBlockAlign)
+			len = dec_audio(mectx->sh_audio, mectx->aencoder->decode_buffer, len);
+			mectx->mux_a->buffer_len += mectx->aencoder->encode(mectx->aencoder, mectx->mux_a->buffer + mectx->mux_a->buffer_len, 
+				mectx->aencoder->decode_buffer, len, mectx->mux_a->buffer_size-mectx->mux_a->buffer_len);
+			if(mectx->mux_a->buffer_len < mectx->mux_a->wf->nBlockAlign)
 				len = 0;
 			else 
-				len = mux_a->wf->nBlockAlign*(mux_a->buffer_len/mux_a->wf->nBlockAlign);
+				len = mectx->mux_a->wf->nBlockAlign*(mectx->mux_a->buffer_len/mectx->mux_a->wf->nBlockAlign);
 		}
 		else	/* VBR */
 		{
@@ -1182,151 +1086,155 @@
 			{
 				len = 0;
 				if(! sz)
-					sz = aencoder->get_frame_size(aencoder);
-				if(sz > 0 && mux_a->buffer_len >= sz)
+					sz = mectx->aencoder->get_frame_size(mectx->aencoder);
+				if(sz > 0 && mectx->mux_a->buffer_len >= sz)
 				{
 					len = sz;
 					break;
 				}
-				len = dec_audio(sh_audio,aencoder->decode_buffer, aencoder->decode_buffer_size);
+				len = dec_audio(mectx->sh_audio,mectx->aencoder->decode_buffer, mectx->aencoder->decode_buffer_size);
 				if(len <= 0)
 				{
 					len = 0;
 					break;
 				}
-				len = aencoder->encode(aencoder, mux_a->buffer + mux_a->buffer_len, aencoder->decode_buffer, len, mux_a->buffer_size-mux_a->buffer_len);
-				mux_a->buffer_len += len;
+				len = mectx->aencoder->encode(mectx->aencoder, mectx->mux_a->buffer + mectx->mux_a->buffer_len, mectx->aencoder->decode_buffer, len, mectx->mux_a->buffer_size-mectx->mux_a->buffer_len);
+				mectx->mux_a->buffer_len += len;
 			}
 	    }
-	    if (mux_v->timer == 0) mux_a->h.dwInitialFrames++;
+	    if (mectx->mux_v->timer == 0) mectx->mux_a->h.dwInitialFrames++;
 	}
 	else {
-	if(mux_a->h.dwSampleSize){
-	    switch(mux_a->codec){
+	if(mectx->mux_a->h.dwSampleSize){
+	    switch(mectx->mux_a->codec){
 	    case ACODEC_COPY: // copy
-		len=mux_a->wf->nAvgBytesPerSec*tottime;
-		len/=mux_a->h.dwSampleSize;if(len<1) len=1;
-		len*=mux_a->h.dwSampleSize;
-		len=demux_read_data(sh_audio->ds,mux_a->buffer,len);
+		len=mectx->mux_a->wf->nAvgBytesPerSec*tottime;
+		len/=mectx->mux_a->h.dwSampleSize;if(len<1) len=1;
+		len*=mectx->mux_a->h.dwSampleSize;
+		len=demux_read_data(mectx->sh_audio->ds,mectx->mux_a->buffer,len);
 		break;
 	    }
 	} else {
 	    // VBR - encode/copy an audio frame
-	    switch(mux_a->codec){
+	    switch(mectx->mux_a->codec){
 	    case ACODEC_COPY: // copy
-		len=ds_get_packet(sh_audio->ds,(unsigned char**) &mux_a->buffer);
+		len=ds_get_packet(mectx->sh_audio->ds,(unsigned char**) &mectx->mux_a->buffer);
 		break;
 		}
 	    }
 	}
 	if(len<=0) break; // EOF?
-	muxer_write_chunk(mux_a,len,0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
-	if(!mux_a->h.dwSampleSize && mux_a->timer>0)
-	    mux_a->wf->nAvgBytesPerSec=0.5f+(double)mux_a->size/mux_a->timer; // avg bps (VBR)
-	if(mux_a->buffer_len>=len){
-	    mux_a->buffer_len-=len;
-	    fast_memcpy(mux_a->buffer,mux_a->buffer+len,mux_a->buffer_len);
+	muxer_write_chunk(mectx->mux_a,len,0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
+	if(!mectx->mux_a->h.dwSampleSize && mectx->mux_a->timer>0)
+	    mectx->mux_a->wf->nAvgBytesPerSec=0.5f+(double)mectx->mux_a->size/mectx->mux_a->timer; // avg bps (VBR)
+	if(mectx->mux_a->buffer_len>=len){
+	    mectx->mux_a->buffer_len-=len;
+	    fast_memcpy(mectx->mux_a->buffer,mectx->mux_a->buffer+len,mectx->mux_a->buffer_len);
 	}
 
 
-	audiosamples++;
-	audiorate+= (GetTimerMS() - ptimer_start);
+	mectx->audiosamples++;
+	mectx->audiorate+= (GetTimerMS() - mectx->ptimer_start);
 	
     }
 }
 
     // get video frame!
 
-    if (!frame_data.already_read) {
-        frame_data.in_size=video_read_frame(sh_video,&frame_data.frame_time,&frame_data.start,force_fps);
-        sh_video->timer+=frame_data.frame_time;
+    if (!mectx->frame_data.already_read) {
+        mectx->frame_data.in_size=video_read_frame(mectx->sh_video,&mectx->frame_data.frame_time,&mectx->frame_data.start,force_fps);
+        mectx->sh_video->timer+=mectx->frame_data.frame_time;
     }
-    frame_data.frame_time /= playback_speed;
-    if(frame_data.in_size<0){ at_eof=1; break; }
-    ++decoded_frameno;
+    mectx->frame_data.frame_time /= playback_speed;
+    if(mectx->frame_data.in_size<0){ mectx->eof=1; break; }
+    ++mectx->decoded_frameno;
 
-    v_timer_corr-=frame_data.frame_time-(float)mux_v->h.dwScale/mux_v->h.dwRate;
+    mectx->v_timer_corr-=mectx->frame_data.frame_time-(float)mectx->mux_v->h.dwScale/mectx->mux_v->h.dwRate;
 
-if(demuxer2){	// 3-pass encoding, read control file (frameno.avi)
+if(mectx->demuxer2){	// 3-pass encoding, read control file (frameno.avi)
     // find our frame:
-	while(next_frameno<decoded_frameno){
+	while(mectx->next_frameno<mectx->decoded_frameno){
 	    int* start;
-	    int len=ds_get_packet(demuxer2->video,(unsigned char**) &start);
-	    if(len<0){ at_eof=1;break;}
+	    int len=ds_get_packet(mectx->demuxer2->video,(unsigned char**) &start);
+	    if(len<0){ mectx->eof=1;break;}
 	    if(len==0) --skip_flag; else  // duplicate
-	    if(len==4) next_frameno=start[0];
+	    if(len==4) mectx->next_frameno=start[0];
 	}
-    if(at_eof) break;
+    if(at_eof || mectx->eof) break;
 	// if(skip_flag) printf("!!!!!!!!!!!!\n");
-	skip_flag=next_frameno-decoded_frameno;
+	skip_flag=mectx->next_frameno-mectx->decoded_frameno;
     // find next frame:
-	while(next_frameno<=decoded_frameno){
+	while(mectx->next_frameno<=mectx->decoded_frameno){
 	    int* start;
-	    int len=ds_get_packet(demuxer2->video,(unsigned char**) &start);
-	    if(len<0){ at_eof=1;break;}
+	    int len=ds_get_packet(mectx->demuxer2->video,(unsigned char**) &start);
+	    if(len<0){ mectx->eof=1;break;}
 	    if(len==0) --skip_flag; else  // duplicate
-	    if(len==4) next_frameno=start[0];
+	    if(len==4) mectx->next_frameno=start[0];
 	}
 //    if(at_eof) break;
-//	    printf("Current fno=%d  requested=%d  skip=%d  \n",decoded_frameno,fno,skip_flag);
+//	    printf("Current fno=%d  requested=%d  skip=%d  \n",mectx->decoded_frameno,fno,skip_flag);
 } else {
 
 // check frame duplicate/drop:
 
-//printf("\r### %5.3f ###\n",v_timer_corr);
-float mux_frametime = (float)mux_v->h.dwScale/mux_v->h.dwRate;
+//printf("\r### %5.3f ###\n",mectx->v_timer_corr);
+float mux_frametime = (float)mectx->mux_v->h.dwScale/mectx->mux_v->h.dwRate;
 
-if (v_timer_corr >= mux_frametime && (skip_limit<0 || skip_flag < skip_limit)) {
-    v_timer_corr-=mux_frametime;
+if (mectx->v_timer_corr >= mux_frametime && (skip_limit<0 || skip_flag < skip_limit)) {
+    mectx->v_timer_corr-=mux_frametime;
     ++skip_flag; // skip
 }
-while (v_timer_corr <= -mux_frametime && (skip_limit<0 || -skip_flag < skip_limit)) {
-    v_timer_corr+=mux_frametime;
+while (mectx->v_timer_corr <= -mux_frametime && (skip_limit<0 || -skip_flag < skip_limit)) {
+    mectx->v_timer_corr+=mux_frametime;
     --skip_flag; // dup
 }
 
-// either v_pts_corr is big, more than 2 times framerate, then we follow its advice,
-// or, it cancels out v_timer_corr, in which case be happy and do nothing.
+// either mectx->v_pts_corr is big, more than 2 times framerate, then we follow its advice,
+// or, it cancels out mectx->v_timer_corr, in which case be happy and do nothing.
 
-while ((v_pts_corr <= -mux_frametime && skip_flag > 0) || (v_pts_corr <= -2*mux_frametime)) {
-    v_pts_corr+=mux_frametime;
+while ((mectx->v_pts_corr <= -mux_frametime && skip_flag > 0) || (mectx->v_pts_corr <= -2*mux_frametime)) {
+    mectx->v_pts_corr+=mux_frametime;
     --skip_flag; // dup
 }
-if ((v_pts_corr >= mux_frametime && skip_flag < 0) || (v_pts_corr >= 2*mux_frametime)) {
+if ((mectx->v_pts_corr >= mux_frametime && skip_flag < 0) || (mectx->v_pts_corr >= 2*mux_frametime)) {
   if (skip_flag<=0) { // we can't skip more than 1 frame now
-    v_pts_corr-=mux_frametime;
+    mectx->v_pts_corr-=mux_frametime;
     ++skip_flag; // skip
   }
 }
 
-} // demuxer2
+} // mectx->demuxer2
 
-ptimer_start = GetTimerMS();
+mectx->ptimer_start = GetTimerMS();
 
-switch(mux_v->codec){
+switch(mectx->mux_v->codec){
 case VCODEC_COPY:
-    mux_v->buffer=frame_data.start;
-    if(skip_flag<=0) muxer_write_chunk(mux_v,frame_data.in_size,(sh_video->ds->flags&1)?0x10:0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
+    mectx->mux_v->buffer=mectx->frame_data.start;
+    if(skip_flag<=0) muxer_write_chunk(mectx->mux_v,mectx->frame_data.in_size,(mectx->sh_video->ds->flags&1)?0x10:0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
     break;
 case VCODEC_FRAMENO:
-    mux_v->buffer=(unsigned char *)&decoded_frameno; // tricky
-    if(skip_flag<=0) muxer_write_chunk(mux_v,sizeof(int),0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
+    mectx->mux_v->buffer=(unsigned char *)&mectx->decoded_frameno; // tricky
+    if(skip_flag<=0) muxer_write_chunk(mectx->mux_v,sizeof(int),0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
     break;
 default:
     // decode_video will callback down to ve_*.c encoders, through the video filters
-    {void *decoded_frame = decode_video(sh_video,frame_data.start,frame_data.in_size,
-      skip_flag>0 && (!sh_video->vfilter || ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) != CONTROL_TRUE), MP_NOPTS_VALUE);
-    blit_frame = decoded_frame && filter_video(sh_video, decoded_frame, MP_NOPTS_VALUE);}
+    {void *decoded_frame = decode_video(mectx->sh_video,mectx->frame_data.start,mectx->frame_data.in_size,
+      skip_flag>0 && (!mectx->sh_video->vfilter || ((vf_instance_t *)mectx->sh_video->vfilter)->control(mectx->sh_video->vfilter, VFCTRL_SKIP_NEXT_FRAME, 0) != CONTROL_TRUE), MP_NOPTS_VALUE);
+    v_pts=mectx->sh_video ? mectx->sh_video->pts : mectx->d_video->pts;
+    ((vf_instance_t *)mectx->sh_video->vfilter)->control(mectx->sh_video->vfilter, VFCTRL_SET_PTS, &v_pts);
+    blit_frame = decoded_frame && filter_video(mectx->sh_video, decoded_frame, MP_NOPTS_VALUE);}
     
-    if (sh_video->vf_inited < 0) mencoder_exit(1, NULL);
+    if (mectx->sh_video->vf_inited < 0) mencoder_exit(1, NULL);
     
+    if (blit_frame && !mectx->start) mectx->start=1;
+    
     if(!blit_frame){
       if (play_n_frames >= 0)
         play_n_frames++;
-      badframes++;
+      mectx->badframes++;
       if(skip_flag<=0){
 	// unwanted skipping of a frame, what to do?
-        v_timer_corr-=(float)mux_v->h.dwScale/mux_v->h.dwRate;
+        mectx->v_timer_corr-=(float)mectx->mux_v->h.dwScale/mectx->mux_v->h.dwRate;
 #if 0
         // Old code apparently made under the assumption that !blit_frame means
         // decoding failed due to corruption or something.. but duplication and
@@ -1335,66 +1243,66 @@
         // Eventually this entire block should probably be removed.
 	if(skip_limit==0){
 	    // skipping not allowed -> write empty frame:
-	    if (!encode_duplicates || !sh_video->vfilter || ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_DUPLICATE_FRAME, 0) != CONTROL_TRUE)
-	      muxer_write_chunk(mux_v,0,0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
+	    if (!encode_duplicates || !mectx->sh_video->vfilter || ((vf_instance_t *)mectx->sh_video->vfilter)->control(mectx->sh_video->vfilter, VFCTRL_DUPLICATE_FRAME, 0) != CONTROL_TRUE)
+	      muxer_write_chunk(mectx->mux_v,0,0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 	} else {
 	    // skipping allowed -> skip it and distriubute timer error:
-	    v_timer_corr-=(float)mux_v->h.dwScale/mux_v->h.dwRate;
+	    mectx->v_timer_corr-=(float)mectx->mux_v->h.dwScale/mectx->mux_v->h.dwRate;
 	}
 #endif
       }
     }
 }
 
-videosamples++;
-videorate+=(GetTimerMS() - ptimer_start);
+mectx->videosamples++;
+mectx->videorate+=(GetTimerMS() - mectx->ptimer_start);
 
 if(skip_flag<0){
     // duplicate frame
 	if(!quiet) mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_DuplicateFrames,-skip_flag);
     while(skip_flag<0){
-	duplicatedframes++;
-	if (!encode_duplicates || !sh_video->vfilter || ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_DUPLICATE_FRAME, 0) != CONTROL_TRUE)
-	    muxer_write_chunk(mux_v,0,0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
+	mectx->duplicatedframes++;
+	if (!encode_duplicates || !mectx->sh_video->vfilter || ((vf_instance_t *)mectx->sh_video->vfilter)->control(mectx->sh_video->vfilter, VFCTRL_DUPLICATE_FRAME, 0) != CONTROL_TRUE)
+	    muxer_write_chunk(mectx->mux_v,0,0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
 	++skip_flag;
     }
 } else
 if(skip_flag>0){
     // skip frame
 	if(!quiet) mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_SkipFrame);
-	skippedframes++;
+	mectx->skippedframes++;
     --skip_flag;
 }
 
-if(sh_audio && !demuxer2){
+if(mectx->sh_audio && !mectx->demuxer2){
     float AV_delay,x;
     // A-V sync!
 #if 0
     if(pts_from_bps){
-        unsigned int samples=(sh_audio->audio.dwSampleSize)?
-          ((ds_tell(d_audio)-sh_audio->a_in_buffer_len)/sh_audio->audio.dwSampleSize) :
-          (d_audio->block_no); // <- used for VBR audio
+        unsigned int samples=(mectx->sh_audio->audio.dwSampleSize)?
+          ((ds_tell(mectx->d_audio)-mectx->sh_audio->a_in_buffer_len)/mectx->sh_audio->audio.dwSampleSize) :
+          (mectx->d_audio->block_no); // <- used for VBR audio
 //	printf("samples=%d  \n",samples);
-        a_pts=samples*(float)sh_audio->audio.dwScale/(float)sh_audio->audio.dwRate;
+        a_pts=samples*(float)mectx->sh_audio->audio.dwScale/(float)mectx->sh_audio->audio.dwRate;
       delay_corrected=1;
     } else 
 #endif
     {
       // PTS = (last timestamp) + (bytes after last timestamp)/(bytes per sec)
-      a_pts=d_audio->pts;
+      a_pts=mectx->d_audio->pts;
       if(!delay_corrected) if(a_pts) delay_corrected=1;
       //printf("*** %5.3f ***\n",a_pts);
-      a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
+      a_pts+=(ds_tell_pts(mectx->d_audio)-mectx->sh_audio->a_in_buffer_len)/(float)mectx->sh_audio->i_bps;
     }
-    v_pts=sh_video ? sh_video->pts : d_video->pts;
+    v_pts=mectx->sh_video ? mectx->sh_video->pts : mectx->d_video->pts;
     // av = compensated (with out buffering delay) A-V diff
     AV_delay=(a_pts-v_pts);
     AV_delay-=audio_delay;
     AV_delay /= playback_speed;
-    AV_delay-=mux_a->timer-(mux_v->timer-(v_timer_corr+v_pts_corr));
+    AV_delay-=mectx->mux_a->timer-(mectx->mux_v->timer-(mectx->v_timer_corr+mectx->v_pts_corr));
     // adjust for encoder delays
-    AV_delay -= (float) mux_a->encoder_delay * mux_a->h.dwScale/mux_a->h.dwRate;
-    AV_delay += (float) mux_v->encoder_delay * mux_v->h.dwScale/mux_v->h.dwRate;
+    AV_delay -= (float) mectx->mux_a->encoder_delay * mectx->mux_a->h.dwScale/mectx->mux_a->h.dwRate;
+    AV_delay += (float) mectx->mux_v->encoder_delay * mectx->mux_v->h.dwScale/mectx->mux_v->h.dwRate;
 	// compensate input video timer by av:
         x=AV_delay*0.1f;
         if(x<-max_pts_correction) x=-max_pts_correction; else
@@ -1402,88 +1310,90 @@
         if(default_max_pts_correction>=0)
           max_pts_correction=default_max_pts_correction*playback_speed;
         else
-          max_pts_correction=sh_video->frametime*0.10 *playback_speed; // +-10% of time
-	// sh_video->timer-=x;
+          max_pts_correction=mectx->sh_video->frametime*0.10 *playback_speed; // +-10% of time
+	// mectx->sh_video->timer-=x;
 	c_total+=x;
-	v_pts_corr+=x;
+	mectx->v_pts_corr+=x;
 }
 
 //    printf("A:%6.1f V:%6.1f A-V:%7.3f oAV:%7.3f diff:%7.3f ct:%7.3f vpc:%7.3f   \r",
 //	a_pts,v_pts,a_pts-v_pts,
-//	(float)(mux_a->timer-mux_v->timer),
-//	AV_delay, c_total, v_pts_corr );
+//	(float)(mectx->mux_a->timer-mectx->mux_v->timer),
+//	AV_delay, c_total, mectx->v_pts_corr );
 //    printf("V:%6.1f \r", d_video->pts );
 
 #if 0
     mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f  %3d/%3d  %2d%% %2d%% %4.1f%%  %d%%\r",
 	  a_pts,v_pts,a_pts-v_pts,c_total,
-          (int)sh_video->num_frames,(int)sh_video->num_frames_decoded,
-          (sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)sh_video->timer):0,
-          (sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)sh_video->timer):0,
-          (sh_video->timer>0.5)?(100.0*audio_time_usage/(double)sh_video->timer):0
+          (int)mectx->sh_video->num_frames,(int)mectx->sh_video->num_frames_decoded,
+          (mectx->sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)mectx->sh_video->timer):0,
+          (mectx->sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)mectx->sh_video->timer):0,
+          (mectx->sh_video->timer>0.5)?(100.0*audio_time_usage/(double)mectx->sh_video->timer):0
 	  ,cache_fill_status
         );
 #endif
 
-    {	float t=(GetTimerMS()-timer_start)*0.001f;
-	float len=(demuxer->movi_end-demuxer->movi_start);
-	float p=len>1000 ? (float)(demuxer->filepos-demuxer->movi_start) / len :
-                (demuxer_get_percent_pos(demuxer) / 100.0);
+    {	float t=(GetTimerMS()-mectx->timer_start)*0.001f;
+	float len=(mectx->demuxer->movi_end-mectx->demuxer->movi_start);
+	float p=len>1000 ? (float)(mectx->demuxer->filepos-mectx->demuxer->movi_start) / len :
+                (demuxer_get_percent_pos(mectx->demuxer) / 100.0);
 #if 0
-	if(!len && sh_audio && sh_audio->audio.dwLength>100){
-	    p=(sh_audio->audio.dwSampleSize? ds_tell(sh_audio->ds)/sh_audio->audio.dwSampleSize : sh_audio->ds->block_no)
-	     / (float)(sh_audio->audio.dwLength);
+	if(!len && mectx->sh_audio && mectx->sh_audio->audio.dwLength>100){
+	    p=(mectx->sh_audio->audio.dwSampleSize? ds_tell(mectx->sh_audio->ds)/mectx->sh_audio->audio.dwSampleSize : mectx->sh_audio->ds->block_no)
+	     / (float)(mectx->sh_audio->audio.dwLength);
 	}
 #endif
 #if 0
 	mp_msg(MSGT_AVSYNC,MSGL_STATUS,"%d < %d < %d  \r",
-	    (int)demuxer->movi_start,
-	    (int)demuxer->filepos,
-	    (int)demuxer->movi_end);
+	    (int)mectx->demuxer->movi_start,
+	    (int)mectx->demuxer->filepos,
+	    (int)mectx->demuxer->movi_end);
 #else
+    if(!vmixerid || 1) {
       if(!quiet) {
 	if( mp_msg_test(MSGT_STATUSLINE,MSGL_V) ) {
 		mp_msg(MSGT_STATUSLINE,MSGL_STATUS,"Pos:%6.1fs %6df (%2d%%) %3dfps Trem:%4dmin %3dmb  A-V:%5.3f [%d:%d] A/Vms %d/%d D/B/S %d/%d/%d \r",
-	    	mux_v->timer, decoded_frameno, (int)(p*100),
-	    	(t>1) ? (int)(decoded_frameno/t+0.5) : 0,
+	    	mectx->mux_v->timer, mectx->decoded_frameno, (int)(p*100),
+	    	(t>1) ? (int)(mectx->decoded_frameno/t+0.5) : 0,
 	    	(p>0.001) ? (int)((t/p-t)/60) : 0, 
-	    	(p>0.001) ? (int)(stream_tell(muxer->stream)/p/1024/1024) : 0,
-	    	v_pts_corr,
-	    	(mux_v->timer>1) ? (int)(mux_v->size/mux_v->timer/125) : 0,
-	    	(mux_a && mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0,
-			audiorate/audiosamples, videorate/videosamples,
-			duplicatedframes, badframes, skippedframes
+	    	(p>0.001) ? (int)(stream_tell(mectx->muxer->stream)/p/1024/1024) : 0,
+	    	mectx->v_pts_corr,
+	    	(mectx->mux_v->timer>1) ? (int)(mectx->mux_v->size/mectx->mux_v->timer/125) : 0,
+	    	(mectx->mux_a && mectx->mux_a->timer>1) ? (int)(mectx->mux_a->size/mectx->mux_a->timer/125) : 0,
+			mectx->audiorate/mectx->audiosamples, mectx->videorate/mectx->videosamples,
+			mectx->duplicatedframes, mectx->badframes, mectx->skippedframes
 		);
 	} else
 	mp_msg(MSGT_STATUSLINE,MSGL_STATUS,"Pos:%6.1fs %6df (%2d%%) %5.2ffps Trem:%4dmin %3dmb  A-V:%5.3f [%d:%d]\r",
-	    mux_v->timer, decoded_frameno, (int)(p*100),
-	    (t>1) ? (float)(decoded_frameno/t) : 0,
+	    mectx->mux_v->timer, mectx->decoded_frameno, (int)(p*100),
+	    (t>1) ? (float)(mectx->decoded_frameno/t) : 0,
 	    (p>0.001) ? (int)((t/p-t)/60) : 0, 
-	    (p>0.001) ? (int)(stream_tell(muxer->stream)/p/1024/1024) : 0,
-	    v_pts_corr,
-	    (mux_v->timer>1) ? (int)(mux_v->size/mux_v->timer/125) : 0,
-	    (mux_a && mux_a->timer>1) ? (int)(mux_a->size/mux_a->timer/125) : 0
+	    (p>0.001) ? (int)(stream_tell(mectx->muxer->stream)/p/1024/1024) : 0,
+	    mectx->v_pts_corr,
+	    (mectx->mux_v->timer>1) ? (int)(mectx->mux_v->size/mectx->mux_v->timer/125) : 0,
+	    (mectx->mux_a && mectx->mux_a->timer>1) ? (int)(mectx->mux_a->size/mectx->mux_a->timer/125) : 0
 	);
       }
+    }
 #endif
     }
         fflush(stdout);
 
 #ifdef USE_DVDREAD
 // DVD sub:
- if(vobsub_writer){
+ if(mectx->vobsub_writer){
      unsigned char* packet=NULL;
      int len;
-     while((len=ds_get_packet_sub(d_dvdsub,&packet))>0){
-	 mp_msg(MSGT_MENCODER,MSGL_V,"\rDVD sub: len=%d  v_pts=%5.3f  s_pts=%5.3f  \n",len,sh_video->pts,d_dvdsub->pts);
-	     vobsub_out_output(vobsub_writer,packet,len,mux_v->timer + d_dvdsub->pts - sh_video->pts);
+     while((len=ds_get_packet_sub(mectx->d_dvdsub,&packet))>0){
+	 mp_msg(MSGT_MENCODER,MSGL_V,"\rDVD sub: len=%d  v_pts=%5.3f  s_pts=%5.3f  \n",len,mectx->sh_video->pts,mectx->d_dvdsub->pts);
+	     vobsub_out_output(mectx->vobsub_writer,packet,len,mectx->mux_v->timer + mectx->d_dvdsub->pts - mectx->sh_video->pts);
      }
  }
  else
 #endif
-    update_subtitles(sh_video, d_dvdsub, 0);
+    update_subtitles(mectx->sh_video, mectx->d_dvdsub, 0);
 
- frame_data = (s_frame_data){ .start = NULL, .in_size = 0, .frame_time = 0., .already_read = 0 };
+ mectx->frame_data = (s_frame_data){ .start = NULL, .in_size = 0, .frame_time = 0., .already_read = 0 };
 
 #if 0
  if(ferror(muxer_f)) {
@@ -1494,73 +1404,276 @@
 
 } // while(!at_eof)
 
-if (!interrupted && filelist[++curfile].name != 0) {
-	if (sh_video && sh_video->vfilter) { // Before uniniting sh_video and the filter chain, break apart the VE.
+if(vmixerid)
+  free_stream(mectx->ostream);
+
+return 1;
+}
+
+int main(int argc,char* argv[]){
+
+MEContext *mectx = NULL;
+int i=DEMUXER_TYPE_UNKNOWN;
+off_t muxer_f_size=0;
+m_entry_t* filelist = NULL;
+char* filename=NULL;
+int curfile=0;
+
+  mp_msg_init();
+
+  for(i=1; i<argc; i++)
+    if(!strcmp(argv[i], "-really-quiet"))
+      verbose= -10;
+
+  mp_msg(MSGT_CPLAYER,MSGL_INFO, "MEncoder " VERSION " (C) 2000-2007 MPlayer Team\n");
+
+  /* Test for cpu capabilities (and corresponding OS support) for optimizing */
+  GetCpuCaps(&gCpuCaps);
+#ifdef ARCH_X86
+  mp_msg(MSGT_CPLAYER,MSGL_INFO,"CPUflags: Type: %d MMX: %d MMX2: %d 3DNow: %d 3DNow2: %d SSE: %d SSE2: %d\n",
+      gCpuCaps.cpuType,gCpuCaps.hasMMX,gCpuCaps.hasMMX2,
+      gCpuCaps.has3DNow, gCpuCaps.has3DNowExt,
+      gCpuCaps.hasSSE, gCpuCaps.hasSSE2);
+#ifdef RUNTIME_CPUDETECT
+  mp_msg(MSGT_CPLAYER,MSGL_INFO, MSGTR_CompiledWithRuntimeDetection);
+#else
+  mp_msg(MSGT_CPLAYER,MSGL_INFO, MSGTR_CompiledWithCPUExtensions);
+#ifdef HAVE_MMX
+  mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX");
+#endif
+#ifdef HAVE_MMX2
+  mp_msg(MSGT_CPLAYER,MSGL_INFO," MMX2");
+#endif
+#ifdef HAVE_3DNOW
+  mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNow");
+#endif
+#ifdef HAVE_3DNOWEX
+  mp_msg(MSGT_CPLAYER,MSGL_INFO," 3DNowEx");
+#endif
+#ifdef HAVE_SSE
+  mp_msg(MSGT_CPLAYER,MSGL_INFO," SSE");
+#endif
+#ifdef HAVE_SSE2
+  mp_msg(MSGT_CPLAYER,MSGL_INFO," SSE2");
+#endif
+  mp_msg(MSGT_CPLAYER,MSGL_INFO,"\n\n");
+#endif
+#endif
+
+#if defined(WIN32) && defined(USE_WIN32DLL)
+  set_path_env();
+#endif /*WIN32 && USE_WIN32DLL*/
+  
+  InitTimer();
+
+// check codec.conf
+if(!codecs_file || !parse_codec_cfg(codecs_file)){
+  if(!parse_codec_cfg(get_path("codecs.conf"))){
+    if(!parse_codec_cfg(MPLAYER_CONFDIR "/codecs.conf")){
+      if(!parse_codec_cfg(NULL)){
+	mencoder_exit(1,NULL);
+      }
+      mp_msg(MSGT_MENCODER,MSGL_V,MSGTR_BuiltinCodecsConf);
+    }
+  }
+}
+
+ mconfig = m_config_new();
+ m_config_register_options(mconfig,mencoder_opts);
+ parse_cfgfiles(mconfig);
+ filelist = m_config_parse_me_command_line(mconfig, argc, argv);
+ if(!filelist) mencoder_exit(1, MSGTR_ErrorParsingCommandLine);
+
+ mectx=new_mectx();
+
+
+{
+	char *extension;
+	
+	if (!out_filename) mencoder_exit(1,MSGTR_MissingOutputFilename);
+	extension=strrchr(out_filename,'.');
+	if (extension != NULL && strlen(extension) > 3 && strlen(extension) < 6)
+	{
+		extension++;
+		
+		switch (out_file_format)
+		{
+			case MUXER_TYPE_AVI:
+			if (strcasecmp(extension,"avi"))
+				mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_MencoderWrongFormatAVI);
+			break;
+
+			case MUXER_TYPE_MPEG:
+			if (strcasecmp(extension,"mpg") &&
+				strcasecmp(extension,"mpeg") &&
+				strcasecmp(extension,"vob")) 
+				mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_MencoderWrongFormatMPG);
+			break;
+		}
+	}
+}				
+ /* Display what configure line was used */
+ mp_msg(MSGT_MENCODER, MSGL_V, "Configuration: " CONFIGURATION "\n");
+
+
+if (frameno_filename) {
+  mectx->stream2=open_stream(frameno_filename,0,&i);
+  if(mectx->stream2){
+    mectx->demuxer2=demux_open(mectx->stream2,DEMUXER_TYPE_AVI,-1,-1,-2,NULL);
+    if(mectx->demuxer2) mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_UsingPass3ControlFile, frameno_filename);
+    else mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_FormatNotRecognized);
+  }
+}
+
+#ifdef WIN32
+  if(proc_priority){
+    int i;
+    for(i=0; priority_presets_defs[i].name; i++){
+      if(strcasecmp(priority_presets_defs[i].name, proc_priority) == 0)
+        break;
+    }
+    mp_msg(MSGT_CPLAYER,MSGL_STATUS,MSGTR_SettingProcessPriority,
+					priority_presets_defs[i].name);
+    SetPriorityClass(GetCurrentProcess(), priority_presets_defs[i].prio);
+  }
+#endif	
+
+// check font
+#ifdef HAVE_FREETYPE
+  init_freetype();
+#endif
+#ifdef HAVE_FONTCONFIG
+  if(!font_fontconfig)
+  {
+#endif
+#ifdef HAVE_BITMAP_FONT
+  if(font_name){
+       vo_font=read_font_desc(font_name,font_factor,verbose>1);
+       if(!vo_font) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadFont,font_name);
+  } else {
+      // try default:
+       vo_font=read_font_desc(get_path("font/font.desc"),font_factor,verbose>1);
+       if(!vo_font)
+       vo_font=read_font_desc(MPLAYER_DATADIR "/font/font.desc",font_factor,verbose>1);
+  }
+#endif
+#ifdef HAVE_FONTCONFIG
+  }
+#endif
+
+  vo_init_osd();
+
+  /* HACK, for some weird reason, push() has to be called twice,
+     otherwise options are not saved correctly */
+  m_config_push(mconfig);
+
+//play_next_file:
+
+  int ret, vmixerid;
+
+  if(vmixer_filename){
+    m_config_push(mconfig);
+    for(vmixerid=1;;vmixerid++) {
+      if(vmixerinit(mectx,vmixerid)) {
+//        m_config_pop(mconfig);
+        break;
+	}
+      }
+    m_config_pop(mconfig);
+    }
+
+  {
+    if(vmixer_filename) {
+      vmixerinit(mectx,0);
+      for(ret=0;ret<10000 && !vmixerstart(mectx);ret++) usleep(1000);
+      mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
+      mp_msg(MSGT_CPLAYER,MSGL_INFO," Open master video\n");
+      mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n");
+    }
+    do {
+      m_config_push(mconfig);
+      m_entry_set_options(mconfig,&filelist[curfile]);
+      filename = filelist[curfile].name;
+ 
+      if(!filename){
+	mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_MissingFilename);
+	mencoder_exit(1,NULL);
+      }
+    
+      mectx->vf_settings=vf_settings;
+      ret=main_loop(mectx,filename,curfile,0);
+      if (ret && !interrupted && filelist[++curfile].name != 0) {
+	if (mectx->sh_video && mectx->sh_video->vfilter) { // Before uniniting mectx->sh_video and the filter chain, break apart the VE.
  		vf_instance_t * ve; // this will be the filter right before the ve.
-		for (ve = sh_video->vfilter; ve->next && ve->next->next; ve = ve->next);
+		for (ve = mectx->sh_video->vfilter; ve->next && ve->next->next; ve = ve->next);
 
 		if (ve->next) ve->next = NULL; // I'm telling the last filter, before the VE, there is nothing after it
-		else sh_video->vfilter = NULL; // There is no chain except the VE.
+		else mectx->sh_video->vfilter = NULL; // There is no chain except the VE.
 	}
 
-	if(sh_audio){ uninit_audio(sh_audio);sh_audio=NULL; }
-	if(sh_video){ uninit_video(sh_video);sh_video=NULL; }
-	if(demuxer) free_demuxer(demuxer);
-	if(stream) free_stream(stream); // kill cache thread
+	if(mectx->sh_audio){ uninit_audio(mectx->sh_audio);mectx->sh_audio=NULL; }
+	if(mectx->sh_video){ uninit_video(mectx->sh_video);mectx->sh_video=NULL; }
+	if(mectx->demuxer) free_demuxer(mectx->demuxer);
+	if(mectx->stream) free_stream(mectx->stream); // kill cache thread
 
-	at_eof = 0;
+	mectx->eof = 0;
 
 	m_config_pop(mconfig);
-	goto play_next_file;
-}
+	ret=2;
+      }
+      if (ret!=2) ret=0;
+    } while (ret);
+  }
 
+
 /* Emit the remaining frames in the video system */
 /*TODO emit frmaes delayed by decoder lag*/
-if(sh_video && sh_video->vfilter){
+if(mectx->sh_video && mectx->sh_video->vfilter){
 	mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_FlushingVideoFrames);
-	if (!((vf_instance_t *)sh_video->vfilter)->fmt.have_configured)
+	if (!((vf_instance_t *)mectx->sh_video->vfilter)->fmt.have_configured)
 		mp_msg(MSGT_MENCODER, MSGL_WARN, MSGTR_FiltersHaveNotBeenConfiguredEmptyFile);
 	else
-		((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter,
+		((vf_instance_t *)mectx->sh_video->vfilter)->control(mectx->sh_video->vfilter,
     	                                              VFCTRL_FLUSH_FRAMES, 0);
 }
 
-if(aencoder)
-    if(aencoder->fixup)
-        aencoder->fixup(aencoder);
+if(mectx->aencoder)
+    if(mectx->aencoder->fixup)
+        mectx->aencoder->fixup(mectx->aencoder);
 
-if (muxer->cont_write_index) muxer_write_index(muxer);
-muxer_f_size=stream_tell(muxer->stream);
-stream_seek(muxer->stream,0);
-if (muxer->cont_write_header) muxer_write_header(muxer); // update header
+if (mectx->muxer->cont_write_index) muxer_write_index(mectx->muxer);
+muxer_f_size=stream_tell(mectx->muxer->stream);
+stream_seek(mectx->muxer->stream,0);
+if (mectx->muxer->cont_write_header) muxer_write_header(mectx->muxer); // update header
 #if 0
 if(ferror(muxer_f) || fclose(muxer_f) != 0) {
     mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_ErrorWritingFile, out_filename);
     mencoder_exit(1, NULL);
 }
 #endif
-if(vobsub_writer)
-    vobsub_out_close(vobsub_writer);
+if(mectx->vobsub_writer)
+    vobsub_out_close(mectx->vobsub_writer);
 
-if(out_video_codec==VCODEC_FRAMENO && mux_v->timer>100){
-    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"650MB",(int)((650*1024*1024-muxer_f_size)/mux_v->timer/125));
-    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"700MB",(int)((700*1024*1024-muxer_f_size)/mux_v->timer/125));
-    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"800MB",(int)((800*1024*1024-muxer_f_size)/mux_v->timer/125));
-    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"2 x 650MB",(int)((2*650*1024*1024-muxer_f_size)/mux_v->timer/125));
-    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"2 x 700MB",(int)((2*700*1024*1024-muxer_f_size)/mux_v->timer/125));
-    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"2 x 800MB",(int)((2*800*1024*1024-muxer_f_size)/mux_v->timer/125));
+if(out_video_codec==VCODEC_FRAMENO && mectx->mux_v->timer>100){
+    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"650MB",(int)((650*1024*1024-muxer_f_size)/mectx->mux_v->timer/125));
+    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"700MB",(int)((700*1024*1024-muxer_f_size)/mectx->mux_v->timer/125));
+    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"800MB",(int)((800*1024*1024-muxer_f_size)/mectx->mux_v->timer/125));
+    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"2 x 650MB",(int)((2*650*1024*1024-muxer_f_size)/mectx->mux_v->timer/125));
+    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"2 x 700MB",(int)((2*700*1024*1024-muxer_f_size)/mectx->mux_v->timer/125));
+    mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_RecommendedVideoBitrate,"2 x 800MB",(int)((2*800*1024*1024-muxer_f_size)/mectx->mux_v->timer/125));
 }
 
 mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_VideoStreamResult,
-    (float)(mux_v->size/mux_v->timer*8.0f/1000.0f), (int)(mux_v->size/mux_v->timer), (uint64_t)mux_v->size, (float)mux_v->timer, decoded_frameno);
-if(sh_audio)
+    (float)(mectx->mux_v->size/mectx->mux_v->timer*8.0f/1000.0f), (int)(mectx->mux_v->size/mectx->mux_v->timer), (uint64_t)mectx->mux_v->size, (float)mectx->mux_v->timer, mectx->decoded_frameno);
+if(mectx->sh_audio)
 mp_msg(MSGT_MENCODER, MSGL_INFO, MSGTR_AudioStreamResult,
-    (float)(mux_a->size/mux_a->timer*8.0f/1000.0f), (int)(mux_a->size/mux_a->timer), (uint64_t)mux_a->size, (float)mux_a->timer);
+    (float)(mectx->mux_a->size/mectx->mux_a->timer*8.0f/1000.0f), (int)(mectx->mux_a->size/mectx->mux_a->timer), (uint64_t)mectx->mux_a->size, (float)mectx->mux_a->timer);
 
-if(sh_audio){ uninit_audio(sh_audio);sh_audio=NULL; }
-if(sh_video){ uninit_video(sh_video);sh_video=NULL; }
-if(demuxer) free_demuxer(demuxer);
-if(stream) free_stream(stream); // kill cache thread
+if(mectx->sh_audio){ uninit_audio(mectx->sh_audio);mectx->sh_audio=NULL; }
+if(mectx->sh_video){ uninit_video(mectx->sh_video);mectx->sh_video=NULL; }
+if(mectx->demuxer) free_demuxer(mectx->demuxer);
+if(mectx->stream) free_stream(mectx->stream); // kill cache thread
+free(mectx);
 
 return interrupted;
 }
