blend.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:36k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * blend.c: alpha blend 2 pictures together
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: blend.c 9200 2004-11-06 16:51:26Z gbazin $
  6.  *
  7.  * Author: Gildas Bazin <gbazin@videolan.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <vlc/vlc.h>
  27. #include <vlc/decoder.h>
  28. #include "vlc_filter.h"
  29. /*****************************************************************************
  30.  * filter_sys_t : filter descriptor
  31.  *****************************************************************************/
  32. struct filter_sys_t
  33. {
  34.     int i_dummy;
  35. };
  36. /****************************************************************************
  37.  * Local prototypes
  38.  ****************************************************************************/
  39. static int  OpenFilter ( vlc_object_t * );
  40. static void CloseFilter( vlc_object_t * );
  41. /* TODO i_alpha support for BlendR16 */
  42. static void Blend( filter_t *, picture_t *, picture_t *, picture_t *,
  43.                    int, int, int );
  44. static void BlendI420( filter_t *, picture_t *, picture_t *, picture_t *,
  45.                        int, int, int, int, int );
  46. static void BlendR16( filter_t *, picture_t *, picture_t *, picture_t *,
  47.                       int, int, int, int, int );
  48. static void BlendR24( filter_t *, picture_t *, picture_t *, picture_t *,
  49.                       int, int, int, int, int );
  50. static void BlendYUY2( filter_t *, picture_t *, picture_t *, picture_t *,
  51.                        int, int, int, int, int );
  52. static void BlendPalI420( filter_t *, picture_t *, picture_t *, picture_t *,
  53.                           int, int, int, int, int );
  54. static void BlendPalYUY2( filter_t *, picture_t *, picture_t *, picture_t *,
  55.                           int, int, int, int, int );
  56. static void BlendPalRV( filter_t *, picture_t *, picture_t *, picture_t *,
  57.                         int, int, int, int, int );
  58. /*****************************************************************************
  59.  * Module descriptor
  60.  *****************************************************************************/
  61. vlc_module_begin();
  62.     set_description( _("Video pictures blending") );
  63.     set_capability( "video blending", 100 );
  64.     set_callbacks( OpenFilter, CloseFilter );
  65. vlc_module_end();
  66. /*****************************************************************************
  67.  * OpenFilter: probe the filter and return score
  68.  *****************************************************************************/
  69. static int OpenFilter( vlc_object_t *p_this )
  70. {
  71.     filter_t *p_filter = (filter_t*)p_this;
  72.     filter_sys_t *p_sys;
  73.     /* Check if we can handle that format.
  74.      * We could try to use a chroma filter if we can't. */
  75.     if( ( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','U','V','A') &&
  76.           p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','U','V','P') ) ||
  77.         ( p_filter->fmt_out.video.i_chroma != VLC_FOURCC('I','4','2','0') &&
  78.           p_filter->fmt_out.video.i_chroma != VLC_FOURCC('Y','U','Y','2') &&
  79.           p_filter->fmt_out.video.i_chroma != VLC_FOURCC('Y','V','1','2') &&
  80.           p_filter->fmt_out.video.i_chroma != VLC_FOURCC('R','V','1','6') &&
  81.           p_filter->fmt_out.video.i_chroma != VLC_FOURCC('R','V','2','4') &&
  82.           p_filter->fmt_out.video.i_chroma != VLC_FOURCC('R','V','3','2') ) )
  83.     {
  84.         return VLC_EGENERIC;
  85.     }
  86.     /* Allocate the memory needed to store the decoder's structure */
  87.     if( ( p_filter->p_sys = p_sys =
  88.           (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
  89.     {
  90.         msg_Err( p_filter, "out of memory" );
  91.         return VLC_EGENERIC;
  92.     }
  93.     /* Misc init */
  94.     p_filter->pf_video_blend = Blend;
  95.     msg_Dbg( p_filter, "chroma: %4.4s -> %4.4s",
  96.              (char *)&p_filter->fmt_in.video.i_chroma,
  97.              (char *)&p_filter->fmt_out.video.i_chroma );
  98.     return VLC_SUCCESS;
  99. }
  100. /****************************************************************************
  101.  * Blend: the whole thing
  102.  ****************************************************************************
  103.  * This function is called just after the thread is launched.
  104.  ****************************************************************************/
  105. static void Blend( filter_t *p_filter, picture_t *p_dst,
  106.                    picture_t *p_dst_orig, picture_t *p_src,
  107.                    int i_x_offset, int i_y_offset, int i_alpha )
  108. {
  109.     int i_width, i_height;
  110.     i_width = __MIN((int)p_filter->fmt_out.video.i_visible_width - i_x_offset,
  111.                     (int)p_filter->fmt_in.video.i_visible_width);
  112.     i_height = __MIN((int)p_filter->fmt_out.video.i_visible_height -i_y_offset,
  113.                      (int)p_filter->fmt_in.video.i_visible_height);
  114.     if( i_width <= 0 || i_height <= 0 ) return;
  115.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
  116.         ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('I','4','2','0') ||
  117.           p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','1','2') ) )
  118.     {
  119.         BlendI420( p_filter, p_dst, p_dst_orig, p_src,
  120.                    i_x_offset, i_y_offset, i_width, i_height, i_alpha );
  121.         return;
  122.     }
  123.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
  124.         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') )
  125.     {
  126.         BlendYUY2( p_filter, p_dst, p_dst_orig, p_src,
  127.                    i_x_offset, i_y_offset, i_width, i_height, i_alpha );
  128.         return;
  129.     }
  130.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
  131.         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') )
  132.     {
  133.         BlendR16( p_filter, p_dst, p_dst_orig, p_src,
  134.                   i_x_offset, i_y_offset, i_width, i_height, i_alpha );
  135.         return;
  136.     }
  137.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
  138.         ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','2','4') ||
  139.           p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','3','2') ) )
  140.     {
  141.         BlendR24( p_filter, p_dst, p_dst_orig, p_src,
  142.                   i_x_offset, i_y_offset, i_width, i_height, i_alpha );
  143.         return;
  144.     }
  145.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','P') &&
  146.         ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('I','4','2','0') ||
  147.           p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','1','2') ) )
  148.     {
  149.         BlendPalI420( p_filter, p_dst, p_dst_orig, p_src,
  150.                       i_x_offset, i_y_offset, i_width, i_height, i_alpha );
  151.         return;
  152.     }
  153.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','P') &&
  154.         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') )
  155.     {
  156.         BlendPalYUY2( p_filter, p_dst, p_dst_orig, p_src,
  157.                       i_x_offset, i_y_offset, i_width, i_height, i_alpha );
  158.         return;
  159.     }
  160.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','P') &&
  161.         ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') ||
  162.           p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','2','4') ||
  163.           p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','3','2') ) )
  164.     {
  165.         BlendPalRV( p_filter, p_dst, p_dst_orig, p_src,
  166.                     i_x_offset, i_y_offset, i_width, i_height, i_alpha );
  167.         return;
  168.     }
  169.     msg_Dbg( p_filter, "no matching alpha blending routine" );
  170. }
  171. static void BlendI420( filter_t *p_filter, picture_t *p_dst,
  172.                        picture_t *p_dst_orig, picture_t *p_src,
  173.                        int i_x_offset, int i_y_offset,
  174.                        int i_width, int i_height, int i_alpha )
  175. {
  176.     int i_src1_pitch, i_src2_pitch, i_dst_pitch;
  177.     uint8_t *p_src1_y, *p_src2_y, *p_dst_y;
  178.     uint8_t *p_src1_u, *p_src2_u, *p_dst_u;
  179.     uint8_t *p_src1_v, *p_src2_v, *p_dst_v;
  180.     uint8_t *p_trans;
  181.     int i_x, i_y, i_trans;
  182.     vlc_bool_t b_even_scanline = i_y_offset % 2;
  183.     i_dst_pitch = p_dst->p[Y_PLANE].i_pitch;
  184.     p_dst_y = p_dst->p[Y_PLANE].p_pixels + i_x_offset +
  185.               p_filter->fmt_out.video.i_x_offset +
  186.               p_dst->p[Y_PLANE].i_pitch *
  187.               ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  188.     p_dst_u = p_dst->p[U_PLANE].p_pixels + i_x_offset/2 +
  189.               p_filter->fmt_out.video.i_x_offset/2 +
  190.               ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  191.               p_dst->p[U_PLANE].i_pitch;
  192.     p_dst_v = p_dst->p[V_PLANE].p_pixels + i_x_offset/2 +
  193.               p_filter->fmt_out.video.i_x_offset/2 +
  194.               ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  195.               p_dst->p[V_PLANE].i_pitch;
  196.     i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
  197.     p_src1_y = p_dst_orig->p[Y_PLANE].p_pixels + i_x_offset +
  198.                p_filter->fmt_out.video.i_x_offset +
  199.                p_dst_orig->p[Y_PLANE].i_pitch *
  200.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  201.     p_src1_u = p_dst_orig->p[U_PLANE].p_pixels + i_x_offset/2 +
  202.                p_filter->fmt_out.video.i_x_offset/2 +
  203.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  204.                p_dst_orig->p[U_PLANE].i_pitch;
  205.     p_src1_v = p_dst_orig->p[V_PLANE].p_pixels + i_x_offset/2 +
  206.                p_filter->fmt_out.video.i_x_offset/2 +
  207.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  208.                p_dst_orig->p[V_PLANE].i_pitch;
  209.     i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
  210.     p_src2_y = p_src->p[Y_PLANE].p_pixels +
  211.                p_filter->fmt_in.video.i_x_offset +
  212.                p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  213.     p_src2_u = p_src->p[U_PLANE].p_pixels +
  214.                p_filter->fmt_in.video.i_x_offset/2 +
  215.                p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  216.     p_src2_v = p_src->p[V_PLANE].p_pixels +
  217.                p_filter->fmt_in.video.i_x_offset/2 +
  218.                p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  219.     p_trans = p_src->p[A_PLANE].p_pixels +
  220.               p_filter->fmt_in.video.i_x_offset +
  221.               p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  222. #define MAX_TRANS 255
  223. #define TRANS_BITS  8
  224.     /* Draw until we reach the bottom of the subtitle */
  225.     for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
  226.          p_dst_y += i_dst_pitch, p_src1_y += i_src1_pitch,
  227.          p_src2_y += i_src2_pitch,
  228.          p_dst_u += b_even_scanline ? i_dst_pitch/2 : 0,
  229.          p_src1_u += b_even_scanline ? i_src1_pitch/2 : 0,
  230.          p_src2_u += i_src2_pitch,
  231.          p_dst_v += b_even_scanline ? i_dst_pitch/2 : 0,
  232.          p_src1_v += b_even_scanline ? i_src1_pitch/2 : 0,
  233.          p_src2_v += i_src2_pitch )
  234.     {
  235.         b_even_scanline = !b_even_scanline;
  236.         /* Draw until we reach the end of the line */
  237.         for( i_x = 0; i_x < i_width; i_x++ )
  238.         {
  239.             i_trans = ( p_trans[i_x] * i_alpha ) / 255;
  240.             if( !i_trans )
  241.             {
  242.                 /* Completely transparent. Don't change pixel */
  243.                 continue;
  244.             }
  245.             else if( i_trans == MAX_TRANS )
  246.             {
  247.                 /* Completely opaque. Completely overwrite underlying pixel */
  248.                 p_dst_y[i_x] = p_src2_y[i_x];
  249.                 if( b_even_scanline && i_x % 2 == 0 )
  250.                 {
  251.                     p_dst_u[i_x/2] = p_src2_u[i_x];
  252.                     p_dst_v[i_x/2] = p_src2_v[i_x];
  253.                 }
  254.                 continue;
  255.             }
  256.             /* Blending */
  257.             p_dst_y[i_x] = ( (uint16_t)p_src2_y[i_x] * i_trans +
  258.                 (uint16_t)p_src1_y[i_x] * (MAX_TRANS - i_trans) )
  259.                 >> TRANS_BITS;
  260.             if( b_even_scanline && i_x % 2 == 0 )
  261.             {
  262.                 p_dst_u[i_x/2] = ( (uint16_t)p_src2_u[i_x] * i_trans +
  263.                 (uint16_t)p_src1_u[i_x/2] * (MAX_TRANS - i_trans) )
  264.                 >> TRANS_BITS;
  265.                 p_dst_v[i_x/2] = ( (uint16_t)p_src2_v[i_x] * i_trans +
  266.                 (uint16_t)p_src1_v[i_x/2] * (MAX_TRANS - i_trans) )
  267.                 >> TRANS_BITS;
  268.             }
  269.         }
  270.     }
  271. #undef MAX_TRANS
  272. #undef TRANS_BITS
  273.     return;
  274. }
  275. static inline void yuv_to_rgb( int *r, int *g, int *b,
  276.                                uint8_t y1, uint8_t u1, uint8_t v1 )
  277. {
  278.     /* macros used for YUV pixel conversions */
  279. #   define SCALEBITS 10
  280. #   define ONE_HALF  (1 << (SCALEBITS - 1))
  281. #   define FIX(x)    ((int) ((x) * (1<<SCALEBITS) + 0.5))
  282. #   define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
  283.     int y, cb, cr, r_add, g_add, b_add;
  284.     cb = u1 - 128;
  285.     cr = v1 - 128;
  286.     r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
  287.     g_add = - FIX(0.34414*255.0/224.0) * cb
  288.             - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
  289.     b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
  290.     y = (y1 - 16) * FIX(255.0/219.0);
  291.     *r = CLAMP((y + r_add) >> SCALEBITS);
  292.     *g = CLAMP((y + g_add) >> SCALEBITS);
  293.     *b = CLAMP((y + b_add) >> SCALEBITS);
  294. }
  295. static void BlendR16( filter_t *p_filter, picture_t *p_dst_pic,
  296.                       picture_t *p_dst_orig, picture_t *p_src,
  297.                       int i_x_offset, int i_y_offset,
  298.                       int i_width, int i_height, int i_alpha )
  299. {
  300.     int i_src1_pitch, i_src2_pitch, i_dst_pitch;
  301.     uint8_t *p_dst, *p_src1, *p_src2_y;
  302.     uint8_t *p_src2_u, *p_src2_v;
  303.     uint8_t *p_trans;
  304.     int i_x, i_y, i_pix_pitch;
  305.     int r, g, b;
  306.     i_pix_pitch = p_dst_pic->p->i_pixel_pitch;
  307.     i_dst_pitch = p_dst_pic->p->i_pitch;
  308.     p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch +
  309.             p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
  310.             p_dst_pic->p->i_pitch *
  311.             ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  312.     i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
  313.     p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch +
  314.                p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
  315.                p_dst_orig->p->i_pitch *
  316.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  317.     i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
  318.     p_src2_y = p_src->p[Y_PLANE].p_pixels +
  319.                p_filter->fmt_in.video.i_x_offset +
  320.                p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  321.     p_src2_u = p_src->p[U_PLANE].p_pixels +
  322.                p_filter->fmt_in.video.i_x_offset/2 +
  323.                p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  324.     p_src2_v = p_src->p[V_PLANE].p_pixels +
  325.                p_filter->fmt_in.video.i_x_offset/2 +
  326.                p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  327.     p_trans = p_src->p[A_PLANE].p_pixels +
  328.               p_filter->fmt_in.video.i_x_offset +
  329.               p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  330. #define MAX_TRANS 255
  331. #define TRANS_BITS  8
  332.     /* Draw until we reach the bottom of the subtitle */
  333.     for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
  334.          p_dst += i_dst_pitch, p_src1 += i_src1_pitch,
  335.          p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch,
  336.          p_src2_v += i_src2_pitch )
  337.     {
  338.         /* Draw until we reach the end of the line */
  339.         for( i_x = 0; i_x < i_width; i_x++ )
  340.         {
  341.             if( !p_trans[i_x] )
  342.             {
  343.                 /* Completely transparent. Don't change pixel */
  344.                 continue;
  345.             }
  346.             else if( p_trans[i_x] == MAX_TRANS )
  347.             {
  348.                 /* Completely opaque. Completely overwrite underlying pixel */
  349.                 yuv_to_rgb( &r, &g, &b,
  350.                             p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
  351.     ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  352.                 continue;
  353.             }
  354.             /* Blending */
  355.             yuv_to_rgb( &r, &g, &b,
  356.                         p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
  357.     ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  358.         }
  359.     }
  360. #undef MAX_TRANS
  361. #undef TRANS_BITS
  362.     return;
  363. }
  364. static void BlendR24( filter_t *p_filter, picture_t *p_dst_pic,
  365.                       picture_t *p_dst_orig, picture_t *p_src,
  366.                       int i_x_offset, int i_y_offset,
  367.                       int i_width, int i_height, int i_alpha )
  368. {
  369.     int i_src1_pitch, i_src2_pitch, i_dst_pitch;
  370.     uint8_t *p_dst, *p_src1, *p_src2_y;
  371.     uint8_t *p_src2_u, *p_src2_v;
  372.     uint8_t *p_trans;
  373.     int i_x, i_y, i_pix_pitch, i_trans;
  374.     int r, g, b;
  375.     i_pix_pitch = p_dst_pic->p->i_pixel_pitch;
  376.     i_dst_pitch = p_dst_pic->p->i_pitch;
  377.     p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch +
  378.             p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
  379.             p_dst_pic->p->i_pitch *
  380.             ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  381.     i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
  382.     p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch +
  383.                p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
  384.                p_dst_orig->p->i_pitch *
  385.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  386.     i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
  387.     p_src2_y = p_src->p[Y_PLANE].p_pixels +
  388.                p_filter->fmt_in.video.i_x_offset +
  389.                p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  390.     p_src2_u = p_src->p[U_PLANE].p_pixels +
  391.                p_filter->fmt_in.video.i_x_offset/2 +
  392.                p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  393.     p_src2_v = p_src->p[V_PLANE].p_pixels +
  394.                p_filter->fmt_in.video.i_x_offset/2 +
  395.                p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  396.     p_trans = p_src->p[A_PLANE].p_pixels +
  397.               p_filter->fmt_in.video.i_x_offset +
  398.               p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  399. #define MAX_TRANS 255
  400. #define TRANS_BITS  8
  401.     /* Draw until we reach the bottom of the subtitle */
  402.     for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
  403.          p_dst += i_dst_pitch, p_src1 += i_src1_pitch,
  404.          p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch,
  405.          p_src2_v += i_src2_pitch )
  406.     {
  407.         /* Draw until we reach the end of the line */
  408.         for( i_x = 0; i_x < i_width; i_x++ )
  409.         {
  410.             i_trans = ( p_trans[i_x] * i_alpha ) / 255;
  411.             if( !i_trans )
  412.             {
  413.                 /* Completely transparent. Don't change pixel */
  414.                 continue;
  415.             }
  416.             else if( i_trans == MAX_TRANS )
  417.             {
  418.                 /* Completely opaque. Completely overwrite underlying pixel */
  419.                 yuv_to_rgb( &r, &g, &b,
  420.                             p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
  421.                 p_dst[i_x * i_pix_pitch]     = r;
  422.                 p_dst[i_x * i_pix_pitch + 1] = g;
  423.                 p_dst[i_x * i_pix_pitch + 2] = b;
  424.                 continue;
  425.             }
  426.             /* Blending */
  427.             yuv_to_rgb( &r, &g, &b,
  428.                         p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
  429.             p_dst[i_x * i_pix_pitch]     = ( r * i_trans +
  430.                 (uint16_t)p_src1[i_x * i_pix_pitch] *
  431.                 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  432.             p_dst[i_x * i_pix_pitch + 1] = ( g * i_trans +
  433.                 (uint16_t)p_src1[i_x * i_pix_pitch + 1] *
  434.                 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  435.             p_dst[i_x * i_pix_pitch + 2] = ( b * i_trans +
  436.                 (uint16_t)p_src1[i_x * i_pix_pitch + 2] *
  437.                 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  438.         }
  439.     }
  440. #undef MAX_TRANS
  441. #undef TRANS_BITS
  442.     return;
  443. }
  444. static void BlendYUY2( filter_t *p_filter, picture_t *p_dst_pic,
  445.                        picture_t *p_dst_orig, picture_t *p_src,
  446.                        int i_x_offset, int i_y_offset,
  447.                        int i_width, int i_height, int i_alpha )
  448. {
  449.     int i_src1_pitch, i_src2_pitch, i_dst_pitch;
  450.     uint8_t *p_dst, *p_src1, *p_src2_y;
  451.     uint8_t *p_src2_u, *p_src2_v;
  452.     uint8_t *p_trans;
  453.     int i_x, i_y, i_pix_pitch, i_trans;
  454.     i_pix_pitch = 2;
  455.     i_dst_pitch = p_dst_pic->p->i_pitch;
  456.     p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch +
  457.             p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
  458.             p_dst_pic->p->i_pitch *
  459.             ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  460.     i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
  461.     p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch +
  462.                p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
  463.                p_dst_orig->p->i_pitch *
  464.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  465.     i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
  466.     p_src2_y = p_src->p[Y_PLANE].p_pixels +
  467.                p_filter->fmt_in.video.i_x_offset +
  468.                p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  469.     p_src2_u = p_src->p[U_PLANE].p_pixels +
  470.                p_filter->fmt_in.video.i_x_offset/2 +
  471.                p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  472.     p_src2_v = p_src->p[V_PLANE].p_pixels +
  473.                p_filter->fmt_in.video.i_x_offset/2 +
  474.                p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
  475.     p_trans = p_src->p[A_PLANE].p_pixels +
  476.               p_filter->fmt_in.video.i_x_offset +
  477.               p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
  478. #define MAX_TRANS 255
  479. #define TRANS_BITS  8
  480.     /* Draw until we reach the bottom of the subtitle */
  481.     for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
  482.          p_dst += i_dst_pitch, p_src1 += i_src1_pitch,
  483.          p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch,
  484.          p_src2_v += i_src2_pitch )
  485.     {
  486.         /* Draw until we reach the end of the line */
  487.         for( i_x = 0; i_x < i_width; i_x += 2 )
  488.         {
  489.             i_trans = ( p_trans[i_x] * i_alpha ) / 255;
  490.             if( !i_trans )
  491.             {
  492.                 /* Completely transparent. Don't change pixel */
  493.             }
  494.             else if( i_trans == MAX_TRANS )
  495.             {
  496.                 /* Completely opaque. Completely overwrite underlying pixel */
  497.                 p_dst[i_x * 2]     = p_src2_y[i_x];
  498.                 p_dst[i_x * 2 + 1] = p_src2_u[i_x];
  499.                 p_dst[i_x * 2 + 3] = p_src2_v[i_x];
  500.             }
  501.             else
  502.             {
  503.                 /* Blending */
  504.                 p_dst[i_x * 2]     = ( (uint16_t)p_src2_y[i_x] * i_trans +
  505.                     (uint16_t)p_src1[i_x * 2] * (MAX_TRANS - i_trans) )
  506.                     >> TRANS_BITS;
  507.                 p_dst[i_x * 2 + 1] = ( (uint16_t)p_src2_u[i_x] * i_trans +
  508.                     (uint16_t)p_src1[i_x * 2 + 1] * (MAX_TRANS - i_trans) )
  509.                     >> TRANS_BITS;
  510.                 p_dst[i_x * 2 + 3] = ( (uint16_t)p_src2_v[i_x] * i_trans +
  511.                     (uint16_t)p_src1[i_x * 2 + 3] * (MAX_TRANS - i_trans) )
  512.                     >> TRANS_BITS;
  513.             }
  514.             i_trans = ( p_trans[i_x+1] * i_alpha ) / 255;
  515.             if( !i_trans )
  516.             {
  517.                 /* Completely transparent. Don't change pixel */
  518.             }
  519.             else if( i_trans == MAX_TRANS )
  520.             {
  521.                 /* Completely opaque. Completely overwrite underlying pixel */
  522.                 p_dst[i_x * 2 + 2] = p_src2_y[i_x + 1];
  523.             }
  524.             else
  525.             {
  526.                 /* Blending */
  527.                 p_dst[i_x * 2 + 2] = ( (uint16_t)p_src2_y[i_x+1] * i_trans +
  528.                     (uint16_t)p_src1[i_x * 2 + 2] * (MAX_TRANS - i_trans) )
  529.                     >> TRANS_BITS;
  530.             }
  531.         }
  532.     }
  533. #undef MAX_TRANS
  534. #undef TRANS_BITS
  535.     return;
  536. }
  537. static void BlendPalI420( filter_t *p_filter, picture_t *p_dst,
  538.                           picture_t *p_dst_orig, picture_t *p_src,
  539.                           int i_x_offset, int i_y_offset,
  540.                           int i_width, int i_height, int i_alpha )
  541. {
  542.     int i_src1_pitch, i_src2_pitch, i_dst_pitch;
  543.     uint8_t *p_src1_y, *p_src2, *p_dst_y;
  544.     uint8_t *p_src1_u, *p_dst_u;
  545.     uint8_t *p_src1_v, *p_dst_v;
  546.     int i_x, i_y, i_trans;
  547.     vlc_bool_t b_even_scanline = i_y_offset % 2;
  548.     i_dst_pitch = p_dst->p[Y_PLANE].i_pitch;
  549.     p_dst_y = p_dst->p[Y_PLANE].p_pixels + i_x_offset +
  550.               p_filter->fmt_out.video.i_x_offset +
  551.               p_dst->p[Y_PLANE].i_pitch *
  552.               ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  553.     p_dst_u = p_dst->p[U_PLANE].p_pixels + i_x_offset/2 +
  554.               p_filter->fmt_out.video.i_x_offset/2 +
  555.               ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  556.               p_dst->p[U_PLANE].i_pitch;
  557.     p_dst_v = p_dst->p[V_PLANE].p_pixels + i_x_offset/2 +
  558.               p_filter->fmt_out.video.i_x_offset/2 +
  559.               ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  560.               p_dst->p[V_PLANE].i_pitch;
  561.     i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
  562.     p_src1_y = p_dst_orig->p[Y_PLANE].p_pixels + i_x_offset +
  563.                p_filter->fmt_out.video.i_x_offset +
  564.                p_dst_orig->p[Y_PLANE].i_pitch *
  565.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  566.     p_src1_u = p_dst_orig->p[U_PLANE].p_pixels + i_x_offset/2 +
  567.                p_filter->fmt_out.video.i_x_offset/2 +
  568.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  569.                p_dst_orig->p[U_PLANE].i_pitch;
  570.     p_src1_v = p_dst_orig->p[V_PLANE].p_pixels + i_x_offset/2 +
  571.                p_filter->fmt_out.video.i_x_offset/2 +
  572.                ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
  573.                p_dst_orig->p[V_PLANE].i_pitch;
  574.     i_src2_pitch = p_src->p->i_pitch;
  575.     p_src2 = p_src->p->p_pixels + p_filter->fmt_in.video.i_x_offset +
  576.              i_src2_pitch * p_filter->fmt_in.video.i_y_offset;
  577. #define MAX_TRANS 255
  578. #define TRANS_BITS  8
  579. #define p_trans p_src2
  580. #define p_pal p_filter->fmt_in.video.p_palette->palette
  581.     /* Draw until we reach the bottom of the subtitle */
  582.     for( i_y = 0; i_y < i_height; i_y++,
  583.          p_dst_y += i_dst_pitch, p_src1_y += i_src1_pitch,
  584.          p_src2 += i_src2_pitch,
  585.          p_dst_u += b_even_scanline ? i_dst_pitch/2 : 0,
  586.          p_src1_u += b_even_scanline ? i_src1_pitch/2 : 0,
  587.          p_dst_v += b_even_scanline ? i_dst_pitch/2 : 0,
  588.          p_src1_v += b_even_scanline ? i_src1_pitch/2 : 0 )
  589.     {
  590.         b_even_scanline = !b_even_scanline;
  591.         /* Draw until we reach the end of the line */
  592.         for( i_x = 0; i_x < i_width; i_x++ )
  593.         {
  594.             i_trans = ( p_pal[p_trans[i_x]][3] * i_alpha ) / 255;
  595.             if( !i_trans )
  596.             {
  597.                 /* Completely transparent. Don't change pixel */
  598.                 continue;
  599.             }
  600.             else if( i_trans == MAX_TRANS )
  601.             {
  602.                 /* Completely opaque. Completely overwrite underlying pixel */
  603.                 p_dst_y[i_x] = p_pal[p_src2[i_x]][0];
  604.                 if( b_even_scanline && i_x % 2 == 0 )
  605.                 {
  606.                     p_dst_u[i_x/2] = p_pal[p_src2[i_x]][1];
  607.                     p_dst_v[i_x/2] = p_pal[p_src2[i_x]][2];
  608.                 }
  609.                 continue;
  610.             }
  611.             /* Blending */
  612.             p_dst_y[i_x] = ( (uint16_t)p_pal[p_src2[i_x]][0] * i_trans +
  613.                 (uint16_t)p_src1_y[i_x] * (MAX_TRANS - i_trans) )
  614.                 >> TRANS_BITS;
  615.             if( b_even_scanline && i_x % 2 == 0 )
  616.             {
  617.                 p_dst_u[i_x/2] = ( (uint16_t)p_pal[p_src2[i_x]][1] * i_trans +
  618.                     (uint16_t)p_src1_u[i_x/2] * (MAX_TRANS - i_trans) )
  619.                     >> TRANS_BITS;
  620.                 p_dst_v[i_x/2] = ( (uint16_t)p_pal[p_src2[i_x]][2] * i_trans +
  621.                     (uint16_t)p_src1_v[i_x/2] * (MAX_TRANS - i_trans) )
  622.                     >> TRANS_BITS;
  623.             }
  624.         }
  625.     }
  626. #undef MAX_TRANS
  627. #undef TRANS_BITS
  628. #undef p_trans
  629. #undef p_pal
  630.     return;
  631. }
  632. static void BlendPalYUY2( filter_t *p_filter, picture_t *p_dst_pic,
  633.                           picture_t *p_dst_orig, picture_t *p_src,
  634.                           int i_x_offset, int i_y_offset,
  635.                           int i_width, int i_height, int i_alpha )
  636. {
  637.     int i_src1_pitch, i_src2_pitch, i_dst_pitch;
  638.     uint8_t *p_src1, *p_src2, *p_dst;
  639.     int i_x, i_y, i_pix_pitch, i_trans;
  640.     i_pix_pitch = 2;
  641.     i_dst_pitch = p_dst_pic->p->i_pitch;
  642.     p_dst = p_dst_pic->p->p_pixels + i_pix_pitch * (i_x_offset +
  643.             p_filter->fmt_out.video.i_x_offset) + p_dst_pic->p->i_pitch *
  644.             ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  645.     i_src1_pitch = p_dst_orig->p->i_pitch;
  646.     p_src1 = p_dst_orig->p->p_pixels + i_pix_pitch * (i_x_offset +
  647.              p_filter->fmt_out.video.i_x_offset) + p_dst_orig->p->i_pitch *
  648.              ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  649.     i_src2_pitch = p_src->p->i_pitch;
  650.     p_src2 = p_src->p->p_pixels + p_filter->fmt_in.video.i_x_offset +
  651.              i_src2_pitch * p_filter->fmt_in.video.i_y_offset;
  652. #define MAX_TRANS 255
  653. #define TRANS_BITS  8
  654. #define p_trans p_src2
  655. #define p_pal p_filter->fmt_in.video.p_palette->palette
  656.     /* Draw until we reach the bottom of the subtitle */
  657.     for( i_y = 0; i_y < i_height; i_y++,
  658.          p_dst += i_dst_pitch, p_src1 += i_src1_pitch, p_src2 += i_src2_pitch )
  659.     {
  660.         /* Draw until we reach the end of the line */
  661.         for( i_x = 0; i_x < i_width; i_x += 2 )
  662.         {
  663.             i_trans = ( p_pal[p_trans[i_x]][3] * i_alpha ) / 255;
  664.             if( !i_trans )
  665.             {
  666.                 /* Completely transparent. Don't change pixel */
  667.             }
  668.             else if( i_trans == MAX_TRANS )
  669.             {
  670.                 /* Completely opaque. Completely overwrite underlying pixel */
  671.                 p_dst[i_x * 2]     = p_pal[p_src2[i_x]][0];
  672.                 p_dst[i_x * 2 + 1] = p_pal[p_src2[i_x]][1];
  673.                 p_dst[i_x * 2 + 3] = p_pal[p_src2[i_x]][2];
  674.             }
  675.             else
  676.             {
  677.                 /* Blending */
  678.                 p_dst[i_x * 2]     = ( (uint16_t)p_pal[p_src2[i_x]][0] *
  679.                     i_trans + (uint16_t)p_src1[i_x * 2] *
  680.                     (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  681.                 p_dst[i_x * 2 + 1] = ( (uint16_t)p_pal[p_src2[i_x]][1] *
  682.                     i_trans + (uint16_t)p_src1[i_x * 2 + 1] *
  683.                     (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  684.                 p_dst[i_x * 2 + 3] = ( (uint16_t)p_pal[p_src2[i_x]][2] *
  685.                     i_trans + (uint16_t)p_src1[i_x * 2 + 3] *
  686.                     (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  687.             }
  688.             i_trans = ( p_pal[p_trans[i_x+1]][3] * i_alpha ) / 255;
  689.             if( !i_trans )
  690.             {
  691.                 /* Completely transparent. Don't change pixel */
  692.             }
  693.             else if( i_trans == MAX_TRANS )
  694.             {
  695.                 /* Completely opaque. Completely overwrite underlying pixel */
  696.                 p_dst[i_x * 2 + 2] = p_pal[p_src2[i_x + 1]][0];
  697.             }
  698.             else
  699.             {
  700.                 /* Blending */
  701.                 p_dst[i_x * 2 + 2] = ( (uint16_t)p_pal[p_src2[i_x+1]][0] *
  702.                     i_trans + (uint16_t)p_src1[i_x * 2 + 2] *
  703.                     (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  704.             }
  705.         }
  706.     }
  707. #undef MAX_TRANS
  708. #undef TRANS_BITS
  709. #undef p_trans
  710. #undef p_pal
  711.     return;
  712. }
  713. static void BlendPalRV( filter_t *p_filter, picture_t *p_dst_pic,
  714.                         picture_t *p_dst_orig, picture_t *p_src,
  715.                         int i_x_offset, int i_y_offset,
  716.                         int i_width, int i_height, int i_alpha )
  717. {
  718.     int i_src1_pitch, i_src2_pitch, i_dst_pitch;
  719.     uint8_t *p_src1, *p_src2, *p_dst;
  720.     int i_x, i_y, i_pix_pitch, i_trans;
  721.     int r, g, b;
  722.     video_palette_t rgbpalette;
  723.     i_pix_pitch = p_dst_pic->p->i_pixel_pitch;
  724.     i_dst_pitch = p_dst_pic->p->i_pitch;
  725.     p_dst = p_dst_pic->p->p_pixels + i_pix_pitch * (i_x_offset +
  726.             p_filter->fmt_out.video.i_x_offset) + p_dst_pic->p->i_pitch *
  727.             ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  728.     i_src1_pitch = p_dst_orig->p->i_pitch;
  729.     p_src1 = p_dst_orig->p->p_pixels + i_pix_pitch * (i_x_offset +
  730.              p_filter->fmt_out.video.i_x_offset) + p_dst_orig->p->i_pitch *
  731.              ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
  732.     i_src2_pitch = p_src->p->i_pitch;
  733.     p_src2 = p_src->p->p_pixels + p_filter->fmt_in.video.i_x_offset +
  734.              i_src2_pitch * p_filter->fmt_in.video.i_y_offset;
  735. #define MAX_TRANS 255
  736. #define TRANS_BITS  8
  737. #define p_trans p_src2
  738. #define p_pal p_filter->fmt_in.video.p_palette->palette
  739. #define rgbpal rgbpalette.palette
  740.     /* Convert palette first */
  741.     for( i_y = 0; i_y < p_filter->fmt_in.video.p_palette->i_entries &&
  742.          i_y < 256; i_y++ )
  743.     {
  744.         yuv_to_rgb( &r, &g, &b, p_pal[i_y][0], p_pal[i_y][1], p_pal[i_y][2] );
  745.         if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') )
  746.         {
  747.             *(uint16_t *)rgbpal[i_y] =
  748.                 ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  749.         }
  750.         else
  751.         {
  752.             rgbpal[i_y][0] = r; rgbpal[i_y][1] = g; rgbpal[i_y][2] = b;
  753.         }
  754.     }
  755.     /* Draw until we reach the bottom of the subtitle */
  756.     for( i_y = 0; i_y < i_height; i_y++,
  757.          p_dst += i_dst_pitch, p_src1 += i_src1_pitch, p_src2 += i_src2_pitch )
  758.     {
  759.         /* Draw until we reach the end of the line */
  760.         for( i_x = 0; i_x < i_width; i_x++ )
  761.         {
  762.             i_trans = ( p_pal[p_trans[i_x]][3] * i_alpha ) / 255;
  763.             if( !i_trans )
  764.             {
  765.                 /* Completely transparent. Don't change pixel */
  766.                 continue;
  767.             }
  768.             else if( i_trans == MAX_TRANS ||
  769.                      p_filter->fmt_out.video.i_chroma ==
  770.                      VLC_FOURCC('R','V','1','6') )
  771.             {
  772.                 /* Completely opaque. Completely overwrite underlying pixel */
  773.                 p_dst[i_x * i_pix_pitch]     = rgbpal[p_src2[i_x]][0];
  774.                 p_dst[i_x * i_pix_pitch + 1] = rgbpal[p_src2[i_x]][1];
  775.                 if( p_filter->fmt_out.video.i_chroma !=
  776.                     VLC_FOURCC('R','V','1','6') )
  777.                 p_dst[i_x * i_pix_pitch + 2] = rgbpal[p_src2[i_x]][2];
  778.                 continue;
  779.             }
  780.             /* Blending */
  781.             p_dst[i_x * i_pix_pitch]     = ( (uint16_t)rgbpal[p_src2[i_x]][0] *
  782.                 i_trans + (uint16_t)p_src1[i_x * i_pix_pitch] *
  783.                 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  784.             p_dst[i_x * i_pix_pitch + 1] = ( (uint16_t)rgbpal[p_src2[i_x]][1] *
  785.                 i_trans + (uint16_t)p_src1[i_x * i_pix_pitch + 1] *
  786.                 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  787.             p_dst[i_x * i_pix_pitch + 2] = ( (uint16_t)rgbpal[p_src2[i_x]][2] *
  788.                 i_trans + (uint16_t)p_src1[i_x * i_pix_pitch + 2] *
  789.                 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
  790.         }
  791.     }
  792. #undef MAX_TRANS
  793. #undef TRANS_BITS
  794. #undef p_trans
  795. #undef p_pal
  796. #undef rgbpal
  797.     return;
  798. }
  799. /*****************************************************************************
  800.  * CloseFilter: clean up the filter
  801.  *****************************************************************************/
  802. static void CloseFilter( vlc_object_t *p_this )
  803. {
  804.     filter_t *p_filter = (filter_t*)p_this;
  805.     filter_sys_t *p_sys = p_filter->p_sys;
  806.     free( p_sys );
  807. }