Index: libmpcodecs/vf_stereo.c =================================================================== --- libmpcodecs/vf_stereo.c (revision 0) +++ libmpcodecs/vf_stereo.c (revision 0) @@ -0,0 +1,961 @@ +/* + * Copyright (C) 2010 Gordon Schmidt + * + * This file is part of MPlayer. + * + * 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 of the License, 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. + */ + +//==includes==// +#include +#include +#include + +#include "config.h" +#include "mp_msg.h" +#include "help_mp.h" + +#include "img_format.h" +#include "mp_image.h" +#include "vf.h" + +#include "libvo/fastmemcpy.h" + +//==macros==// +#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) +#define MAX(X,Y) ((X) < (Y) ? (Y) : (X)) + +#define YUV2R(Y,V,U) (MIN(255,MAX(0,((1192*((Y) - 16) + 1634*((V) - 128) ) >> 10)))) +#define YUV2G(Y,V,U) (MIN(255,MAX(0,((1192*((Y) - 16) - 833*((V) - 128) - 400*((U) - 128)) >> 10)))) +#define YUV2B(Y,V,U) (MIN(255,MAX(0,((1192*((Y) - 16) + 2066*((U) - 128)) >> 10)))) + +#define RGB2Y(R,G,B) (MIN(255,MAX(0,((( 263*(R) + 516*(G) + 100*(B)) >> 10) + 16)))) +#define RGB2V(R,G,B) (MIN(255,MAX(0,((( 450*(R) - 377*(G) - 73*(B)) >> 10) + 128)))) +#define RGB2U(R,G,B) (MIN(255,MAX(0,(((-152*(R) - 298*(G) + 450*(B)) >> 10) + 128)))) + +#define RC_R(RL,RR,GL,GR,BL,BR) (RL) +#define RC_G(RL,RR,GL,GR,BL,BR) (GR) +#define RC_B(RL,RR,GL,GR,BL,BR) (BR) + +#define GM_R(RL,RR,GL,GR,BL,BR) (RR) +#define GM_G(RL,RR,GL,GR,BL,BR) (GL) +#define GM_B(RL,RR,GL,GR,BL,BR) (BR) + +#define YB_R(RL,RR,GL,GR,BL,BR) (RR) +#define YB_G(RL,RR,GL,GR,BL,BR) (GR) +#define YB_B(RL,RR,GL,GR,BL,BR) (BL) + +//slow version, that uses the RC transformation for RGB (should also work if these makros change) +#define RC_Y(YL,YR,VL,VR,UL,UR) (RGB2Y(RC_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + RC_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + RC_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) +#define RC_V(YL,YR,VL,VR,UL,UR) (RGB2V(RC_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + RC_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + RC_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) +#define RC_U(YL,YR,VL,VR,UL,UR) (RGB2U(RC_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + RC_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + RC_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) + +//slow version, that uses the GM transformation for RGB (should also work if these makros change) +#define GM_Y(YL,YR,VL,VR,UL,UR) (RGB2Y(GM_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + GM_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + GM_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) +#define GM_V(YL,YR,VL,VR,UL,UR) (RGB2V(GM_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + GM_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + GM_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) +#define GM_U(YL,YR,VL,VR,UL,UR) (RGB2U(GM_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + GM_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + GM_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) + +//slow version, that uses the YB transformation for RGB (should also work if these makros change) +#define YB_Y(YL,YR,VL,VR,UL,UR) (RGB2Y(YB_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + YB_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + YB_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) +#define YB_V(YL,YR,VL,VR,UL,UR) (RGB2V(YB_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + YB_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + YB_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) +#define YB_U(YL,YR,VL,VR,UL,UR) (RGB2U(YB_R(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + YB_G(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)), \ + YB_B(YUV2R(YL,VL,UL),YUV2R(YR,VR,UR),YUV2G(YL,VL,UL), \ + YUV2G(YR,VR,UR),YUV2B(YL,VL,UL),YUV2B(YR,VR,UR)))) + +#define M4(V1,V2,V3,V4) (MIN(255,MAX(0,(((V1) + (V2) + (V3) + (V4)) >> 2)))) + +//==types==// +typedef enum stereo_code +{ + NOT_SET, //no value set - TODO: needs autodetection + SIDE_BY_SIDE_LR, //side by side parallel (left eye left - right eye right) + SIDE_BY_SIDE_RL, //side by side crosseye (right eye left - left eye right) + ABOVE_BELOW_LR, //above-below (left eye above - right eye below) + ABOVE_BELOW_RL, //above-below (right eye above - left eye below) + ABOVE_BELOW_2_LR, //above-below (left eye above - right eye below) only half high resolution + ABOVE_BELOW_2_RL, //above-below (right eye above - left eye below) only half high resolution + INTERLACED_LR, //interlaced starting with left eye line (left eye on lines 0,2,..) + INTERLACED_RL, //interlaced starting with right eye line (right eye on lines 0,2,..) + INTERLACED_2_LR, //interlaced starting with left eye line (left eye on lines 0,2,..) only half high resolution + INTERLACED_2_RL, //interlaced starting with right eye line (right eye on lines 0,2,..) only half high resolution + ANAGLYPH_RC, //anaglyph red/cyan (red filter on left eye - cyan filter on right eye) + ANAGLYPH_GM, //anaglyph green/magenta (green filter on left eye - magenta filter on right eye) + ANAGLYPH_YB, //anaglyph yellow/blue (yellow filter on left eye - blue filter on right eye) + MONO_L, //mono output for debugging - left eye only + MONO_R //mono output for debugging - right eye only +} stereo_code; + +//==global variables==// +struct vf_priv_s +{ + unsigned int w; + unsigned int h; + unsigned int out_w; + unsigned int out_h; + stereo_code in_fmt; + stereo_code out_fmt; + mp_image_t* img_src; + mp_image_t* img_dst; + unsigned char* img_l; + unsigned char* img_r; +}; + +extern int opt_screen_size_x; +extern int opt_screen_size_y; + +//==functions==// +static int config( struct vf_instance_s* vf, int width, int height, int d_width, + int d_height, unsigned int flags, unsigned int outfmt ) +{ + switch( vf->priv->in_fmt ) + { + case SIDE_BY_SIDE_LR: + case SIDE_BY_SIDE_RL: + { + if( 0 != width % 2 ) //test for odd width + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] odd width of input\n" ); + return 0; + } + vf->priv->w = ( width / 2 ); + vf->priv->h = height; + break; + } + case ABOVE_BELOW_LR: + case ABOVE_BELOW_RL: +// case INTERLACED_LR: +// case INTERLACED_RL: + { + if( 0 != height % 2 ) //test for odd height + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] odd height of input\n" ); + return 0; + } + vf->priv->w = width; + vf->priv->h = height / 2; + break; + } + case ABOVE_BELOW_2_LR: + case ABOVE_BELOW_2_RL: +// case INTERLACED_2_LR: +// case INTERLACED_2_RL: + { + if( 0 != height % 2 ) //test for odd height + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] odd height of input\n" ); + return 0; + } + vf->priv->w = width; + vf->priv->h = height; + break; + } + case ANAGLYPH_RC: + case ANAGLYPH_GM: + case ANAGLYPH_YB: + case MONO_L: + case MONO_R: + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] stereo format of input is not supported\n" ); + return 0; + break; + } + } + switch( vf->priv->out_fmt ) + { + case ANAGLYPH_RC: + case ANAGLYPH_GM: + case ANAGLYPH_YB: + case ABOVE_BELOW_2_LR: + case ABOVE_BELOW_2_RL: +// case INTERLACED_2_LR: +// case INTERLACED_2_RL: + case MONO_L: + case MONO_R: + { + vf->priv->out_w = vf->priv->w; + vf->priv->out_h = vf->priv->h; + break; + } + case SIDE_BY_SIDE_LR: + case SIDE_BY_SIDE_RL: + { + vf->priv->out_w = vf->priv->w * 2; + vf->priv->out_h = vf->priv->h; + break; + } + case ABOVE_BELOW_LR: + case ABOVE_BELOW_RL: +// case INTERLACED_LR: +// case INTERLACED_RL: + { + vf->priv->out_w = vf->priv->w; + vf->priv->out_h = vf->priv->h * 2; + break; + } + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] stereo format of output is not supported\n" ); + return 0; + break; + } + } + switch( outfmt ) + { + case IMGFMT_YV12: + { + vf->priv->img_l = malloc( ( ( 3 * vf->priv->w * vf->priv->h ) >> 1 ) ); + vf->priv->img_r = malloc( ( ( 3 * vf->priv->w * vf->priv->h ) >> 1 ) ); + break; + } + case IMGFMT_RGB24: + { + vf->priv->img_l = malloc( 3 * vf->priv->w * vf->priv->h ); + vf->priv->img_r = malloc( 3 * vf->priv->w * vf->priv->h ); + break; + } + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] unsupported input/output fmt\n" ); + return 0; + break; + } + } + if( !opt_screen_size_x && !opt_screen_size_y ) + { + d_width = d_width * vf->priv->out_w / width; + d_height = d_height * vf->priv->out_h / height; + } + mp_msg( MSGT_VFILTER, MSGL_INFO, "[stereo] DEBUG %d x %d -> %d x %d\n", width, height, vf->priv->out_w, vf->priv->out_h ); + return vf_next_config( vf, vf->priv->out_w, vf->priv->out_h, d_width, d_height, flags, outfmt ); +} + +static int get_yv12( struct vf_instance_s* vf ) +{ + switch( vf->priv->in_fmt ) + { + case SIDE_BY_SIDE_LR: + { + int size = vf->priv->w * vf->priv->h; + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h, vf->priv->w, 2 * vf->priv->w ); + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0] + vf->priv->w, vf->priv->w, vf->priv->h, vf->priv->w, 2 * vf->priv->w ); + + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[1] + vf->priv->w / 2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + + size = size + ( size >> 2 ); + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[2] + vf->priv->w / 2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + break; + } + case SIDE_BY_SIDE_RL: + { + int size = vf->priv->w * vf->priv->h; + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0] + vf->priv->w, vf->priv->w, vf->priv->h, vf->priv->w, 2 * vf->priv->w ); + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h, vf->priv->w, 2 * vf->priv->w ); + + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[1] + vf->priv->w / 2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + + size = size + ( size >> 2 ); + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[2] + vf->priv->w / 2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w ); + break; + } + case ABOVE_BELOW_LR: + { + int size = vf->priv->w * vf->priv->h; + int size2 = ( size >> 2 ); + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0] + size, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[1] + size2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_l + size + size2, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size + size2, vf->priv->img_src->planes[2] + size2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + break; + } + case ABOVE_BELOW_RL: + { + int size = vf->priv->w * vf->priv->h; + int size2 = ( size >> 2 ); + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0] + size, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[1] + size2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_r + size + size2, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size + size2, vf->priv->img_src->planes[2] + size2, vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + break; + } + case ABOVE_BELOW_2_LR: + { + int size = vf->priv->w * vf->priv->h; + int size2 = ( size >> 2 ); + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_l + vf->priv->w, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0] + size / 2, vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_r + vf->priv->w, vf->priv->img_src->planes[0] + size / 2, vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size + vf->priv->w / 2, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[1] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size + vf->priv->w / 2, vf->priv->img_src->planes[1] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_l + size + size2, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size + size2 + vf->priv->w / 2, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size + size2, vf->priv->img_src->planes[2] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size + size2 + vf->priv->w / 2, vf->priv->img_src->planes[2] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + break; + } + case ABOVE_BELOW_2_RL: + { + int size = vf->priv->w * vf->priv->h; + int size2 = ( size >> 2 ); + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_r + vf->priv->w, vf->priv->img_src->planes[0], vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0] + size / 2, vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_l + vf->priv->w, vf->priv->img_src->planes[0] + size / 2, vf->priv->w, vf->priv->h / 2, 2 * vf->priv->w, vf->priv->w ); + + memcpy_pic( vf->priv->img_r + size, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size + vf->priv->w / 2, vf->priv->img_src->planes[1], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size, vf->priv->img_src->planes[1] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size + vf->priv->w / 2, vf->priv->img_src->planes[1] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_r + size + size2, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_r + size + size2 + vf->priv->w / 2, vf->priv->img_src->planes[2], vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size + size2, vf->priv->img_src->planes[2] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_l + size + size2 + vf->priv->w / 2, vf->priv->img_src->planes[2] + size2 / 2, vf->priv->w / 2, vf->priv->h / 4, vf->priv->w, vf->priv->w / 2 ); + break; + } + //TODO: support for interlaced input + //TODO: support for anaglyph input + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] stereo format of input is not supported\n" ); + return 0; + break; + } + } + return 1; +} + +static int set_yv12( struct vf_instance_s* vf ) +{ + switch( vf->priv->out_fmt ) + { + case SIDE_BY_SIDE_LR: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, vf->priv->w, vf->priv->h, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], vf->priv->img_l + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2], vf->priv->img_l + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_dst->planes[0] + vf->priv->w, vf->priv->img_r, vf->priv->w, vf->priv->h, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1] + vf->priv->w / 2, vf->priv->img_r + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2] + vf->priv->w / 2, vf->priv->img_r + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + break; + } + case SIDE_BY_SIDE_RL: + { + memcpy_pic( vf->priv->img_dst->planes[0] + vf->priv->w, vf->priv->img_l, vf->priv->w, vf->priv->h, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1] + vf->priv->w / 2, ( vf->priv->img_l + ( vf->priv->w * vf->priv->h ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2] + vf->priv->w / 2, ( vf->priv->img_l + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, vf->priv->w, vf->priv->h, 2 * vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], ( vf->priv->img_r + ( vf->priv->w * vf->priv->h ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2], ( vf->priv->img_r + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w, vf->priv->w / 2 ); + break; + } + case ABOVE_BELOW_LR: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], vf->priv->img_l + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2], vf->priv->img_l + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_dst->planes[0] + vf->priv->w * vf->priv->h, vf->priv->img_r, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1] + ( ( vf->priv->w * vf->priv->h) >> 2 ), vf->priv->img_r + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2] + ( ( vf->priv->w * vf->priv->h) >> 2 ), vf->priv->img_r + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + break; + } + case ABOVE_BELOW_RL: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], vf->priv->img_r + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2], vf->priv->img_r + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + + memcpy_pic( vf->priv->img_dst->planes[0] + vf->priv->w * vf->priv->h, vf->priv->img_l, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1] + ( ( vf->priv->w * vf->priv->h) >> 2 ), vf->priv->img_l + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2] + ( ( vf->priv->w * vf->priv->h) >> 2 ), vf->priv->img_l + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + break; + } + case ABOVE_BELOW_2_LR: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, vf->priv->w, vf->priv->h / 2, vf->priv->w, 2 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], vf->priv->img_l + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[2], vf->priv->img_l + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + + memcpy_pic( vf->priv->img_dst->planes[0] + ( ( vf->priv->w * vf->priv->h) >> 1 ), vf->priv->img_r, vf->priv->w, vf->priv->h / 2, vf->priv->w, 2 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1] + ( ( vf->priv->w * vf->priv->h) >> 3 ), vf->priv->img_r + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[2] + ( ( vf->priv->w * vf->priv->h) >> 3 ), vf->priv->img_r + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + break; + } + case ABOVE_BELOW_2_RL: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, vf->priv->w, vf->priv->h / 2, vf->priv->w, 2 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], vf->priv->img_r + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[2], vf->priv->img_r + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + + memcpy_pic( vf->priv->img_dst->planes[0] + ( ( vf->priv->w * vf->priv->h) >> 1 ), vf->priv->img_l, vf->priv->w, vf->priv->h / 2, vf->priv->w, 2 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1] + ( ( vf->priv->w * vf->priv->h) >> 3 ), vf->priv->img_l + ( vf->priv->w * vf->priv->h ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[2] + ( ( vf->priv->w * vf->priv->h) >> 3 ), vf->priv->img_l + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ), vf->priv->w / 2, vf->priv->h / 4, vf->priv->w / 2, vf->priv->w ); + break; + } + case MONO_L: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], ( vf->priv->img_l + ( vf->priv->w * vf->priv->h ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2], ( vf->priv->img_l + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + break; + } + case MONO_R: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, vf->priv->w, vf->priv->h, vf->priv->w, vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[1], ( vf->priv->img_r + ( vf->priv->w * vf->priv->h ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + memcpy_pic( vf->priv->img_dst->planes[2], ( vf->priv->img_r + 5 * ( ( vf->priv->w * vf->priv->h ) >> 2 ) ), vf->priv->w / 2, vf->priv->h / 2, vf->priv->w / 2, vf->priv->w / 2 ); + break; + } + case ANAGLYPH_RC: + { //somehow u and v get mixed up - just switched it as a workaround + int x,y,i,j; + int size = vf->priv->w * vf->priv->h; + int size2 = size + ( size >> 2 ); + unsigned char ml,mr; + for( y = 0; y < vf->priv->h; y++ ) + { + for( x = 0; x < vf->priv->w; x++ ) + { + i = vf->priv->w * y + x; + j = ( vf->priv->w >> 1 ) * ( y >> 1 ) + ( x >> 1 ); + vf->priv->img_dst->planes[0][i] = RC_Y( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + } + } + for( y = 0; y < vf->priv->h; y+=2 ) + { + for( x = 0; x < vf->priv->w; x+=2 ) + { + i = vf->priv->w * y + x; + j = ( vf->priv->w >> 1 ) * ( y >> 1 ) + ( x >> 1 ); + ml = M4( vf->priv->img_l[i], vf->priv->img_l[i + 1], vf->priv->img_l[i + vf->priv->w], vf->priv->img_l[i + vf->priv->w + 1] ); + mr = M4( vf->priv->img_l[i], vf->priv->img_l[i + 1], vf->priv->img_l[i + vf->priv->w], vf->priv->img_l[i + vf->priv->w + 1] ); + vf->priv->img_dst->planes[1][j] = RC_U( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + vf->priv->img_dst->planes[2][j] = RC_V( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + } + } + break; + } + case ANAGLYPH_GM: + { //somehow u and v get mixed up - just switched it as a workaround + int x,y,i,j; + int size = vf->priv->w * vf->priv->h; + int size2 = size + ( size >> 2 ); + unsigned char ml,mr; + for( y = 0; y < vf->priv->h; y++ ) + { + for( x = 0; x < vf->priv->w; x++ ) + { + i = vf->priv->w * y + x; + j = ( vf->priv->w >> 1 ) * ( y >> 1 ) + ( x >> 1 ); + vf->priv->img_dst->planes[0][i] = GM_Y( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + } + } + for( y = 0; y < vf->priv->h; y+=2 ) + { + for( x = 0; x < vf->priv->w; x+=2 ) + { + i = vf->priv->w * y + x; + j = ( vf->priv->w >> 1 ) * ( y >> 1 ) + ( x >> 1 ); + ml = M4( vf->priv->img_l[i], vf->priv->img_l[i + 1], vf->priv->img_l[i + vf->priv->w], vf->priv->img_l[i + vf->priv->w + 1] ); + mr = M4( vf->priv->img_l[i], vf->priv->img_l[i + 1], vf->priv->img_l[i + vf->priv->w], vf->priv->img_l[i + vf->priv->w + 1] ); + vf->priv->img_dst->planes[1][j] = GM_U( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + vf->priv->img_dst->planes[2][j] = GM_V( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + } + } + break; + } + case ANAGLYPH_YB: + { //somehow u and v get mixed up - just switched it as a workaround + int x,y,i,j; + int size = vf->priv->w * vf->priv->h; + int size2 = size + ( size >> 2 ); + unsigned char ml,mr; + for( y = 0; y < vf->priv->h; y++ ) + { + for( x = 0; x < vf->priv->w; x++ ) + { + i = vf->priv->w * y + x; + j = ( vf->priv->w >> 1 ) * ( y >> 1 ) + ( x >> 1 ); + vf->priv->img_dst->planes[0][i] = YB_Y( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + } + } + for( y = 0; y < vf->priv->h; y+=2 ) + { + for( x = 0; x < vf->priv->w; x+=2 ) + { + i = vf->priv->w * y + x; + j = ( vf->priv->w >> 1 ) * ( y >> 1 ) + ( x >> 1 ); + ml = M4( vf->priv->img_l[i], vf->priv->img_l[i + 1], vf->priv->img_l[i + vf->priv->w], vf->priv->img_l[i + vf->priv->w + 1] ); + mr = M4( vf->priv->img_l[i], vf->priv->img_l[i + 1], vf->priv->img_l[i + vf->priv->w], vf->priv->img_l[i + vf->priv->w + 1] ); + vf->priv->img_dst->planes[1][j] = YB_U( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + vf->priv->img_dst->planes[2][j] = YB_V( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[size2 + j], vf->priv->img_r[size2 + j], + vf->priv->img_l[size + j], vf->priv->img_r[size + j] ); + } + } + break; + } + //TODO: support for interlaced output + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] stereo format of output is not supported\n" ); + return 0; + break; + } + } + return 1; +} + +static int get_rgb24( struct vf_instance_s* vf ) +{ + switch( vf->priv->in_fmt ) + { + case SIDE_BY_SIDE_LR: + { + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 6 * vf->priv->w ); + memcpy_pic( vf->priv->img_r, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w ), 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 6 * vf->priv->w ); + break; + } + case SIDE_BY_SIDE_RL: + { + memcpy_pic( vf->priv->img_l, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w ), 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 6 * vf->priv->w ); + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 6 * vf->priv->w ); + break; + } + case ABOVE_BELOW_LR: + { + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_r, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w * vf->priv->h ), 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case ABOVE_BELOW_RL: + { + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_l, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w * vf->priv->h ), 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case ABOVE_BELOW_2_LR: + { + memcpy_pic( vf->priv->img_l, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_l + 3 * vf->priv->w, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_r, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w * vf->priv->h / 2 ), 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_r + 3 * vf->priv->w, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w * vf->priv->h / 2 ), 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case ABOVE_BELOW_2_RL: + { + memcpy_pic( vf->priv->img_r, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_r + 3 * vf->priv->w, vf->priv->img_src->planes[0], 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_l, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w * vf->priv->h / 2 ), 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_l + 3 * vf->priv->w, ( vf->priv->img_src->planes[0] + 3 * vf->priv->w * vf->priv->h / 2 ), 3 * vf->priv->w, vf->priv->h / 2, 6 * vf->priv->w, 3 * vf->priv->w ); + break; + } + //TODO: support for interlaced input + //TODO: support for anaglyph input + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] stereo format of input is not supported\n" ); + return 0; + break; + } + } + return 1; +} + +static int set_rgb24( struct vf_instance_s* vf ) +{ + switch( vf->priv->out_fmt ) + { + case SIDE_BY_SIDE_LR: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, 3 * vf->priv->w, vf->priv->h, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( ( vf->priv->img_dst->planes[0] + 3 * vf->priv->w ), vf->priv->img_r, 3 * vf->priv->w, vf->priv->h, 6 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case SIDE_BY_SIDE_RL: + { + memcpy_pic( ( vf->priv->img_dst->planes[0] + 3 * vf->priv->w ), vf->priv->img_l, 3 * vf->priv->w, vf->priv->h, 6 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, 3 * vf->priv->w, vf->priv->h, 6 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case ABOVE_BELOW_LR: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[0] + 3 * vf->priv->w * vf->priv->h, vf->priv->img_r, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case ABOVE_BELOW_RL: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[0] + 3 * vf->priv->w * vf->priv->h, vf->priv->img_l, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case ABOVE_BELOW_2_LR: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, 3 * vf->priv->w, vf->priv->h / 2, 3 * vf->priv->w, 6 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[0] + 3 * vf->priv->w * vf->priv->h / 2, vf->priv->img_r, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 6 * vf->priv->w ); + break; + } + case ABOVE_BELOW_2_RL: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, 3 * vf->priv->w, vf->priv->h / 2, 3 * vf->priv->w, 6 * vf->priv->w ); + memcpy_pic( vf->priv->img_dst->planes[0] + 3 * vf->priv->w * vf->priv->h / 2, vf->priv->img_l, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 6 * vf->priv->w ); + break; + } + case MONO_L: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_l, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case MONO_R: + { + memcpy_pic( vf->priv->img_dst->planes[0], vf->priv->img_r, 3 * vf->priv->w, vf->priv->h, 3 * vf->priv->w, 3 * vf->priv->w ); + break; + } + case ANAGLYPH_RC: + { + int i; + int size = 3 * vf->priv->w * vf->priv->h; + for( i = 0; i < size; i += 3 ) + { //merge + vf->priv->img_dst->planes[0][i] = RC_R( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + vf->priv->img_dst->planes[0][i + 1] = RC_G( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + vf->priv->img_dst->planes[0][i + 2] = RC_B( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + } + break; + } + case ANAGLYPH_GM: + { + int i; + int size = 3 * vf->priv->w * vf->priv->h; + for( i = 0; i < size; i += 3 ) + { //merge + vf->priv->img_dst->planes[0][i] = GM_R( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + vf->priv->img_dst->planes[0][i + 1] = GM_G( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + vf->priv->img_dst->planes[0][i + 2] = GM_B( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + } + break; + } + case ANAGLYPH_YB: + { + int i; + int size = 3 * vf->priv->w * vf->priv->h; + for( i = 0; i < size; i += 3 ) + { //merge + vf->priv->img_dst->planes[0][i] = YB_R( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + vf->priv->img_dst->planes[0][i + 1] = YB_G( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + vf->priv->img_dst->planes[0][i + 2] = YB_B( vf->priv->img_l[i ], vf->priv->img_r[i ], + vf->priv->img_l[i + 1], vf->priv->img_r[i + 1], + vf->priv->img_l[i + 2], vf->priv->img_r[i + 2] ); + } + break; + } + //TODO: support for interlaced output + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] stereo format of output is not supported\n" ); + return 0; + break; + } + } + return 1; +} + + +static int put_image( struct vf_instance_s* vf, mp_image_t* mpi, double pts ) +{ + if( vf->priv->in_fmt == vf->priv->out_fmt ) + { //nothing to do + vf->priv->img_dst = mpi; + } + else + { + vf->priv->img_src = mpi; + switch( mpi->imgfmt ) + { + case IMGFMT_YV12: + { + vf->priv->img_dst = vf_get_image( vf->next, IMGFMT_YV12, MP_IMGTYPE_TEMP, 0, vf->priv->out_w, vf->priv->out_h ); + vf->priv->img_dst->h = vf->priv->out_h; + vf->priv->img_dst->width = vf->priv->out_w; + memset( vf->priv->img_dst->planes[0], 0, vf->priv->out_w * vf->priv->out_h ); + memset( vf->priv->img_dst->planes[1], 128, ( ( vf->priv->out_w * vf->priv->out_h ) >> 2 ) ); + memset( vf->priv->img_dst->planes[2], 128, ( ( vf->priv->out_w * vf->priv->out_h ) >> 2 ) ); + if( 0 == get_yv12( vf ) ) + { + return 0; + } + if( 0 == set_yv12( vf ) ) + { + return 0; + } + break; + } + case IMGFMT_RGB24: + { + vf->priv->img_dst = vf_get_image( vf->next, IMGFMT_RGB24, MP_IMGTYPE_TEMP, 0, vf->priv->out_w, vf->priv->out_h ); + vf->priv->img_dst->h = vf->priv->out_h; + vf->priv->img_dst->width = vf->priv->out_w; + if( 0 == get_rgb24( vf ) ) + { + return 0; + } + if( 0 == set_rgb24( vf ) ) + { + return 0; + } + break; + } + default: + { + mp_msg( MSGT_VFILTER, MSGL_WARN, "[stereo] unsupported input/output fmt\n" ); + return 0; + break; + } + } + } + return vf_next_put_image( vf, vf->priv->img_dst, pts ); +} + +static int query_format( struct vf_instance_s* vf, unsigned int fmt ) +{ + switch( fmt ) + { + case IMGFMT_YV12: + case IMGFMT_RGB24: + return vf_next_query_format( vf, fmt ); + } + return 0; +} + +static stereo_code get_arg( char* arg ) +{ + stereo_code return_value = NOT_SET; + if( arg ) + { + if( 0 == strcmp( arg, "slr" ) ) + { + return_value = SIDE_BY_SIDE_LR; + } + else if( 0 == strcmp( arg, "srl" ) ) + { + return_value = SIDE_BY_SIDE_RL; + } + else if( 0 == strcmp( arg, "ablr" ) ) + { + return_value = ABOVE_BELOW_LR; + } + else if( 0 == strcmp( arg, "abrl" ) ) + { + return_value = ABOVE_BELOW_RL; + } + else if( 0 == strcmp( arg, "ab2lr" ) ) + { + return_value = ABOVE_BELOW_2_LR; + } + else if( 0 == strcmp( arg, "ab2rl" ) ) + { + return_value = ABOVE_BELOW_2_RL; + } +/*interlaced in not support yet + else if( 0 == strcmp( arg, "ilr" ) ) + { + return_value = INTERLACED_LR; + } + else if( 0 == strcmp( arg, "irl" ) ) + { + return_value = INTERLACED_RL; + } + else if( 0 == strcmp( arg, "i2lr" ) ) + { + return_value = INTERLACED_2_LR; + } + else if( 0 == strcmp( arg, "i2rl" ) ) + { + return_value = INTERLACED_2_RL; + } + else if( 0 == strcmp( arg, "i2rl" ) ) + { + return_value = INTERLACED_2_RL; + } +*/ + else if( 0 == strcmp( arg, "arc" ) ) + { + return_value = ANAGLYPH_RC; + } + else if( 0 == strcmp( arg, "agm" ) ) + { + return_value = ANAGLYPH_GM; + } + else if( 0 == strcmp( arg, "ayb" ) ) + { + return_value = ANAGLYPH_YB; + } + else if( 0 == strcmp( arg, "ml" ) ) + { + return_value = MONO_L; + } + else if( 0 == strcmp( arg, "mr" ) ) + { + return_value = MONO_R; + } + } + return return_value; +} + +static void uninit( struct vf_instance_s* vf ) +{ + free( vf->priv->img_l ); + free( vf->priv->img_r ); + if( vf->priv ) + { + free( vf->priv ); + } +} + +static int open( vf_instance_t* vf, char* args ) +{ + //init priv + vf->priv = malloc( sizeof( struct vf_priv_s ) ); + if( !vf->priv ) + { + return 0; + } + vf->priv->in_fmt = NOT_SET; + vf->priv->out_fmt = NOT_SET; + + vf->config = config; + vf->put_image = put_image; + vf->query_format = query_format; + vf->uninit = uninit; + vf->default_reqs = VFCAP_ACCEPT_STRIDE; + + if( args ) + { + char* arg; + //input code + arg = strtok( args, ": \0\n" ); + vf->priv->in_fmt = get_arg( arg ); + //output code + arg = strtok( NULL, ": \0\n" ); + vf->priv->out_fmt = get_arg( arg ); + } + return 1; +} + +//==info struct==// +const vf_info_t vf_info_stereo = { + "stereoscopic 3d view", + "stereo", + "Gordon Schmidt", + "view stereoscopic videos", + open, + NULL +}; Index: libmpcodecs/vf.c =================================================================== --- libmpcodecs/vf.c (revision 30392) +++ libmpcodecs/vf.c (working copy) @@ -100,6 +100,7 @@ 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_stereo; // list of available filters: static const vf_info_t* const filter_list[]={ @@ -193,6 +194,7 @@ &vf_info_yadif, &vf_info_blackframe, &vf_info_ow, + &vf_info_stereo, NULL }; Index: Makefile =================================================================== --- Makefile (revision 30392) +++ Makefile (working copy) @@ -453,6 +453,7 @@ libmpcodecs/vf_smartblur.c \ libmpcodecs/vf_softpulldown.c \ libmpcodecs/vf_softskip.c \ + libmpcodecs/vf_stereo.c \ libmpcodecs/vf_swapuv.c \ libmpcodecs/vf_telecine.c \ libmpcodecs/vf_test.c \