swscale.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:20k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * swscale.c: scaling and chroma conversion using libswscale
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2008 the VideoLAN team
  5.  * $Id: 432fe8a8020f2458264bf6a244e512021a32994c $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_vout.h>
  33. #include <vlc_filter.h>
  34. #ifdef HAVE_LIBSWSCALE_SWSCALE_H
  35. #   include <libswscale/swscale.h>
  36. #   include <libavcodec/avcodec.h>
  37. #elif defined(HAVE_FFMPEG_SWSCALE_H)
  38. #   include <ffmpeg/swscale.h>
  39. #   include <ffmpeg/avcodec.h>
  40. #endif
  41. /* Gruikkkkkkkkkk!!!!! */
  42. #include "../codec/avcodec/avcodec.h"
  43. #undef AVPALETTE_SIZE
  44. #define AVPALETTE_SIZE (256 * sizeof(uint32_t))
  45. /*****************************************************************************
  46.  * Module descriptor
  47.  *****************************************************************************/
  48. static int  OpenScaler( vlc_object_t * );
  49. static void CloseScaler( vlc_object_t * );
  50. #define SCALEMODE_TEXT N_("Scaling mode")
  51. #define SCALEMODE_LONGTEXT N_("Scaling mode to use.")
  52. static const int pi_mode_values[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  53. const char *const ppsz_mode_descriptions[] =
  54. { N_("Fast bilinear"), N_("Bilinear"), N_("Bicubic (good quality)"),
  55.   N_("Experimental"), N_("Nearest neighbour (bad quality)"),
  56.   N_("Area"), N_("Luma bicubic / chroma bilinear"), N_("Gauss"),
  57.   N_("SincR"), N_("Lanczos"), N_("Bicubic spline") };
  58. vlc_module_begin ()
  59.     set_description( N_("Video scaling filter") )
  60.     set_shortname( N_("Swscale" ) )
  61.     set_capability( "video filter2", 150 )
  62.     set_category( CAT_VIDEO )
  63.     set_subcategory( SUBCAT_VIDEO_VFILTER )
  64.     set_callbacks( OpenScaler, CloseScaler )
  65.     add_integer( "swscale-mode", 2, NULL, SCALEMODE_TEXT, SCALEMODE_LONGTEXT, true )
  66.         change_integer_list( pi_mode_values, ppsz_mode_descriptions, NULL )
  67. vlc_module_end ()
  68. /* Version checking */
  69. #if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0)
  70. /****************************************************************************
  71.  * Local prototypes
  72.  ****************************************************************************/
  73. void *( *swscale_fast_memcpy )( void *, const void *, size_t );
  74. /**
  75.  * Internal swscale filter structure.
  76.  */
  77. struct filter_sys_t
  78. {
  79.     SwsFilter *p_src_filter;
  80.     SwsFilter *p_dst_filter;
  81.     int i_cpu_mask, i_sws_flags;
  82.     video_format_t fmt_in;
  83.     video_format_t fmt_out;
  84.     struct SwsContext *ctx;
  85.     struct SwsContext *ctxA;
  86.     picture_t *p_src_a;
  87.     picture_t *p_dst_a;
  88.     int i_extend_factor;
  89.     picture_t *p_src_e;
  90.     picture_t *p_dst_e;
  91.     bool b_add_a;
  92.     bool b_copy;
  93. };
  94. static picture_t *Filter( filter_t *, picture_t * );
  95. static int  Init( filter_t * );
  96. static void Clean( filter_t * );
  97. typedef struct
  98. {
  99.     int  i_fmti;
  100.     int  i_fmto;
  101.     bool b_has_a;
  102.     bool b_add_a;
  103.     int  i_sws_flags;
  104.     bool b_copy;
  105. } ScalerConfiguration;
  106. static int GetParameters( ScalerConfiguration *,
  107.                           const video_format_t *p_fmti,
  108.                           const video_format_t *p_fmto,
  109.                           int i_sws_flags_default );
  110. static int GetSwsCpuMask(void);
  111. /* SwScaler point resize quality seems really bad, let our scale module do it
  112.  * (change it to true to try) */
  113. #define ALLOW_YUVP (false)
  114. /* SwScaler does not like too small picture */
  115. #define MINIMUM_WIDTH (32)
  116. /* XXX is it always 3 even for BIG_ENDIAN (blend.c seems to think so) ? */
  117. #define OFFSET_A (3)
  118. /*****************************************************************************
  119.  * OpenScaler: probe the filter and return score
  120.  *****************************************************************************/
  121. static int OpenScaler( vlc_object_t *p_this )
  122. {
  123.     filter_t *p_filter = (filter_t*)p_this;
  124.     filter_sys_t *p_sys;
  125.     int i_sws_mode;
  126.     if( GetParameters( NULL,
  127.                        &p_filter->fmt_in.video,
  128.                        &p_filter->fmt_out.video, 0 ) )
  129.         return VLC_EGENERIC;
  130.     /* */
  131.     p_filter->pf_video_filter = Filter;
  132.     /* Allocate the memory needed to store the decoder's structure */
  133.     if( ( p_filter->p_sys = p_sys = malloc(sizeof(filter_sys_t)) ) == NULL )
  134.         return VLC_ENOMEM;
  135.     /* FIXME pointer assignment may not be atomic */
  136.     swscale_fast_memcpy = vlc_memcpy;
  137.     /* Set CPU capabilities */
  138.     p_sys->i_cpu_mask = GetSwsCpuMask();
  139.     /* */
  140.     i_sws_mode = var_CreateGetInteger( p_filter, "swscale-mode" );
  141.     switch( i_sws_mode )
  142.     {
  143.     case 0:  p_sys->i_sws_flags = SWS_FAST_BILINEAR; break;
  144.     case 1:  p_sys->i_sws_flags = SWS_BILINEAR; break;
  145.     case 2:  p_sys->i_sws_flags = SWS_BICUBIC; break;
  146.     case 3:  p_sys->i_sws_flags = SWS_X; break;
  147.     case 4:  p_sys->i_sws_flags = SWS_POINT; break;
  148.     case 5:  p_sys->i_sws_flags = SWS_AREA; break;
  149.     case 6:  p_sys->i_sws_flags = SWS_BICUBLIN; break;
  150.     case 7:  p_sys->i_sws_flags = SWS_GAUSS; break;
  151.     case 8:  p_sys->i_sws_flags = SWS_SINC; break;
  152.     case 9:  p_sys->i_sws_flags = SWS_LANCZOS; break;
  153.     case 10: p_sys->i_sws_flags = SWS_SPLINE; break;
  154.     default: p_sys->i_sws_flags = SWS_BICUBIC; i_sws_mode = 2; break;
  155.     }
  156.     p_sys->p_src_filter = NULL;
  157.     p_sys->p_dst_filter = NULL;
  158.     /* Misc init */
  159.     p_sys->ctx = NULL;
  160.     p_sys->ctxA = NULL;
  161.     p_sys->p_src_a = NULL;
  162.     p_sys->p_dst_a = NULL;
  163.     p_sys->p_src_e = NULL;
  164.     p_sys->p_dst_e = NULL;
  165.     memset( &p_sys->fmt_in,  0, sizeof(p_sys->fmt_in) );
  166.     memset( &p_sys->fmt_out, 0, sizeof(p_sys->fmt_out) );
  167.     if( Init( p_filter ) )
  168.     {
  169.         if( p_sys->p_src_filter )
  170.             sws_freeFilter( p_sys->p_src_filter );
  171.         free( p_sys );
  172.         return VLC_EGENERIC;
  173.     }
  174.     msg_Dbg( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s with scaling using %s",
  175.              p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height,
  176.              (char *)&p_filter->fmt_in.video.i_chroma,
  177.              p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height,
  178.              (char *)&p_filter->fmt_out.video.i_chroma,
  179.              ppsz_mode_descriptions[i_sws_mode] );
  180.     return VLC_SUCCESS;
  181. }
  182. /*****************************************************************************
  183.  * CloseFilter: clean up the filter
  184.  *****************************************************************************/
  185. static void CloseScaler( vlc_object_t *p_this )
  186. {
  187.     filter_t *p_filter = (filter_t*)p_this;
  188.     filter_sys_t *p_sys = p_filter->p_sys;
  189.     Clean( p_filter );
  190.     if( p_sys->p_src_filter )
  191.         sws_freeFilter( p_sys->p_src_filter );
  192.     free( p_sys );
  193. }
  194. /*****************************************************************************
  195.  * Helpers
  196.  *****************************************************************************/
  197. static int GetSwsCpuMask(void)
  198. {
  199.     const unsigned int i_cpu = vlc_CPU();
  200.     int i_sws_cpu = 0;
  201.     if( i_cpu & CPU_CAPABILITY_MMX )
  202.         i_sws_cpu |= SWS_CPU_CAPS_MMX;
  203. #if (LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0))
  204.     if( i_cpu & CPU_CAPABILITY_MMXEXT )
  205.         i_sws_cpu |= SWS_CPU_CAPS_MMX2;
  206. #endif
  207.     if( i_cpu & CPU_CAPABILITY_3DNOW )
  208.         i_sws_cpu |= SWS_CPU_CAPS_3DNOW;
  209.     if( i_cpu & CPU_CAPABILITY_ALTIVEC )
  210.         i_sws_cpu |= SWS_CPU_CAPS_ALTIVEC;
  211.     return i_sws_cpu;
  212. }
  213. static bool IsFmtSimilar( const video_format_t *p_fmt1, const video_format_t *p_fmt2 )
  214. {
  215.     return p_fmt1->i_chroma == p_fmt2->i_chroma &&
  216.            p_fmt1->i_width  == p_fmt2->i_width &&
  217.            p_fmt1->i_height == p_fmt2->i_height;
  218. }
  219. static int GetParameters( ScalerConfiguration *p_cfg,
  220.                           const video_format_t *p_fmti,
  221.                           const video_format_t *p_fmto,
  222.                           int i_sws_flags_default )
  223. {
  224.     int i_fmti = -1;
  225.     int i_fmto = -1;
  226.     bool b_has_ai = false;
  227.     bool b_has_ao = false;
  228.     int i_sws_flags = i_sws_flags_default;
  229.     GetFfmpegChroma( &i_fmti, *p_fmti );
  230.     GetFfmpegChroma( &i_fmto, *p_fmto );
  231.     if( p_fmti->i_chroma == p_fmto->i_chroma )
  232.     {
  233.         if( p_fmti->i_chroma == VLC_FOURCC( 'Y', 'U', 'V', 'P' ) && ALLOW_YUVP )
  234.         {
  235.             i_fmti = i_fmto = PIX_FMT_GRAY8;
  236.             i_sws_flags = SWS_POINT;
  237.         }
  238.     }
  239.     if( p_fmti->i_chroma == VLC_FOURCC( 'Y', 'U', 'V', 'A' ) )
  240.     {
  241.         i_fmti = PIX_FMT_YUV444P;
  242.         b_has_ai = true;
  243.     }
  244.     else if( p_fmti->i_chroma == VLC_FOURCC( 'R', 'G', 'B', 'A' ) )
  245.     {
  246.         i_fmti = PIX_FMT_BGR32;
  247.         b_has_ai = true;
  248.     }
  249.     if( p_fmto->i_chroma == VLC_FOURCC( 'Y', 'U', 'V', 'A' ) )
  250.     {
  251.         i_fmto = PIX_FMT_YUV444P;
  252.         b_has_ao = true;
  253.     }
  254.     else if( p_fmto->i_chroma == VLC_FOURCC( 'R', 'G', 'B', 'A' ) )
  255.     {
  256.         i_fmto = PIX_FMT_BGR32;
  257.         b_has_ao = true;
  258.     }
  259.     /* FIXME TODO removed when ffmpeg is fixed
  260.      * Without SWS_ACCURATE_RND the quality is really bad for some conversions */
  261.     switch( i_fmto )
  262.     {
  263.     case PIX_FMT_ARGB:
  264.     case PIX_FMT_RGBA:
  265.     case PIX_FMT_ABGR:
  266.         i_sws_flags |= SWS_ACCURATE_RND;
  267.         break;
  268.     }
  269.     if( p_cfg )
  270.     {
  271.         p_cfg->i_fmti = i_fmti;
  272.         p_cfg->i_fmto = i_fmto;
  273.         p_cfg->b_has_a = b_has_ai && b_has_ao;
  274.         p_cfg->b_add_a = (!b_has_ai) && b_has_ao;
  275.         p_cfg->b_copy = i_fmti == i_fmto && p_fmti->i_width == p_fmto->i_width && p_fmti->i_height == p_fmto->i_height;
  276.         p_cfg->i_sws_flags = i_sws_flags;
  277.     }
  278.     if( i_fmti < 0 || i_fmto < 0 )
  279.         return VLC_EGENERIC;
  280.     return VLC_SUCCESS;
  281. }
  282. static int Init( filter_t *p_filter )
  283. {
  284.     filter_sys_t *p_sys = p_filter->p_sys;
  285.     const video_format_t *p_fmti = &p_filter->fmt_in.video;
  286.     const video_format_t *p_fmto = &p_filter->fmt_out.video;
  287.     if( IsFmtSimilar( p_fmti, &p_sys->fmt_in ) &&
  288.         IsFmtSimilar( p_fmto, &p_sys->fmt_out ) &&
  289.         p_sys->ctx )
  290.     {
  291.         return VLC_SUCCESS;
  292.     }
  293.     Clean( p_filter );
  294.     /* Init with new parameters */
  295.     ScalerConfiguration cfg;
  296.     if( GetParameters( &cfg, p_fmti, p_fmto, p_sys->i_sws_flags ) )
  297.     {
  298.         msg_Err( p_filter, "format not supported" );
  299.         return VLC_EGENERIC;
  300.     }
  301.     if( p_fmti->i_width <= 0 || p_fmto->i_width <= 0 )
  302.     {
  303.         msg_Err( p_filter, "0 width not supported" );
  304.         return VLC_EGENERIC;
  305.     }
  306.     /* swscale does not like too small width */
  307.     p_sys->i_extend_factor = 1;
  308.     while( __MIN( p_fmti->i_width, p_fmto->i_width ) * p_sys->i_extend_factor < MINIMUM_WIDTH)
  309.         p_sys->i_extend_factor++;
  310.     const unsigned i_fmti_width = p_fmti->i_width * p_sys->i_extend_factor;
  311.     const unsigned i_fmto_width = p_fmto->i_width * p_sys->i_extend_factor;
  312.     for( int n = 0; n < (cfg.b_has_a ? 2 : 1); n++ )
  313.     {
  314.         const int i_fmti = n == 0 ? cfg.i_fmti : PIX_FMT_GRAY8;
  315.         const int i_fmto = n == 0 ? cfg.i_fmto : PIX_FMT_GRAY8;
  316.         struct SwsContext *ctx;
  317.         ctx = sws_getContext( i_fmti_width, p_fmti->i_height, i_fmti,
  318.                               i_fmto_width, p_fmto->i_height, i_fmto,
  319.                               cfg.i_sws_flags | p_sys->i_cpu_mask,
  320.                               p_sys->p_src_filter, p_sys->p_dst_filter, 0 );
  321.         if( n == 0 )
  322.             p_sys->ctx = ctx;
  323.         else
  324.             p_sys->ctxA = ctx;
  325.     }
  326.     if( p_sys->ctxA )
  327.     {
  328.         p_sys->p_src_a = picture_New( VLC_FOURCC( 'G', 'R', 'E', 'Y' ), i_fmti_width, p_fmti->i_height, 0 );
  329.         p_sys->p_dst_a = picture_New( VLC_FOURCC( 'G', 'R', 'E', 'Y' ), i_fmto_width, p_fmto->i_height, 0 );
  330.     }
  331.     if( p_sys->i_extend_factor != 1 )
  332.     {
  333.         p_sys->p_src_e = picture_New( p_fmti->i_chroma, i_fmti_width, p_fmti->i_height, 0 );
  334.         p_sys->p_dst_e = picture_New( p_fmto->i_chroma, i_fmto_width, p_fmto->i_height, 0 );
  335.         memset( p_sys->p_src_e->p[0].p_pixels, 0, p_sys->p_src_e->p[0].i_pitch * p_sys->p_src_e->p[0].i_lines );
  336.         memset( p_sys->p_dst_e->p[0].p_pixels, 0, p_sys->p_dst_e->p[0].i_pitch * p_sys->p_dst_e->p[0].i_lines );
  337.     }
  338.     if( !p_sys->ctx ||
  339.         ( cfg.b_has_a && ( !p_sys->ctxA || !p_sys->p_src_a || !p_sys->p_dst_a ) ) ||
  340.         ( p_sys->i_extend_factor != 1 && ( !p_sys->p_src_e || !p_sys->p_dst_e ) ) )
  341.     {
  342.         msg_Err( p_filter, "could not init SwScaler and/or allocate memory" );
  343.         Clean( p_filter );
  344.         return VLC_EGENERIC;
  345.     }
  346.     p_sys->b_add_a = cfg.b_add_a;
  347.     p_sys->b_copy = cfg.b_copy;
  348.     p_sys->fmt_in  = *p_fmti;
  349.     p_sys->fmt_out = *p_fmto;
  350. #if 0
  351.     msg_Dbg( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s extend by %d",
  352.              p_fmti->i_width, p_fmti->i_height, (char *)&p_fmti->i_chroma,
  353.              p_fmto->i_width, p_fmto->i_height, (char *)&p_fmto->i_chroma,
  354.              p_sys->i_extend_factor );
  355. #endif
  356.     return VLC_SUCCESS;
  357. }
  358. static void Clean( filter_t *p_filter )
  359. {
  360.     filter_sys_t *p_sys = p_filter->p_sys;
  361.     if( p_sys->p_src_e )
  362.         picture_Release( p_sys->p_src_e );
  363.     if( p_sys->p_dst_e )
  364.         picture_Release( p_sys->p_dst_e );
  365.     if( p_sys->p_src_a )
  366.         picture_Release( p_sys->p_src_a );
  367.     if( p_sys->p_dst_a )
  368.         picture_Release( p_sys->p_dst_a );
  369.     if( p_sys->ctxA )
  370.         sws_freeContext( p_sys->ctxA );
  371.     if( p_sys->ctx )
  372.         sws_freeContext( p_sys->ctx );
  373.     /* We have to set it to null has we call be called again :( */
  374.     p_sys->ctx = NULL;
  375.     p_sys->ctxA = NULL;
  376.     p_sys->p_src_a = NULL;
  377.     p_sys->p_dst_a = NULL;
  378.     p_sys->p_src_e = NULL;
  379.     p_sys->p_dst_e = NULL;
  380. }
  381. static void GetPixels( uint8_t *pp_pixel[4], int pi_pitch[4],
  382.                        const picture_t *p_picture,
  383.                        int i_plane_start, int i_plane_count )
  384. {
  385.     int n;
  386.     for( n = 0; n < __MIN(i_plane_count, p_picture->i_planes-i_plane_start ); n++ )
  387.     {
  388.         pp_pixel[n] = p_picture->p[i_plane_start+n].p_pixels;
  389.         pi_pitch[n] = p_picture->p[i_plane_start+n].i_pitch;
  390.     }
  391.     for( ; n < 4; n++ )
  392.     {
  393.         pp_pixel[n] = NULL;
  394.         pi_pitch[n] = 0;
  395.     }
  396. }
  397. static void ExtractA( picture_t *p_dst, const picture_t *p_src, unsigned i_width, unsigned i_height )
  398. {
  399.     plane_t *d = &p_dst->p[0];
  400.     const plane_t *s = &p_src->p[0];
  401.     for( unsigned y = 0; y < i_height; y++ )
  402.         for( unsigned x = 0; x < i_width; x++ )
  403.             d->p_pixels[y*d->i_pitch+x] = s->p_pixels[y*s->i_pitch+4*x+OFFSET_A];
  404. }
  405. static void InjectA( picture_t *p_dst, const picture_t *p_src, unsigned i_width, unsigned i_height )
  406. {
  407.     plane_t *d = &p_dst->p[0];
  408.     const plane_t *s = &p_src->p[0];
  409.     for( unsigned y = 0; y < i_height; y++ )
  410.         for( unsigned x = 0; x < i_width; x++ )
  411.             d->p_pixels[y*d->i_pitch+4*x+OFFSET_A] = s->p_pixels[y*s->i_pitch+x];
  412. }
  413. static void FillA( plane_t *d, int i_offset )
  414. {
  415.     for( int y = 0; y < d->i_visible_lines; y++ )
  416.         for( int x = 0; x < d->i_visible_pitch; x += d->i_pixel_pitch )
  417.             d->p_pixels[y*d->i_pitch+x+i_offset] = 0xff;
  418. }
  419. static void CopyPad( picture_t *p_dst, const picture_t *p_src )
  420. {
  421.     picture_Copy( p_dst, p_src );
  422.     for( int n = 0; n < p_dst->i_planes; n++ )
  423.     {
  424.         const plane_t *s = &p_src->p[n];
  425.         plane_t *d = &p_dst->p[n];
  426.         for( int y = 0; y < s->i_lines; y++ )
  427.         {
  428.             for( int x = s->i_visible_pitch; x < d->i_visible_pitch; x += s->i_pixel_pitch )
  429.                 memcpy( &d->p_pixels[y*d->i_pitch + x], &d->p_pixels[y*d->i_pitch + s->i_visible_pitch - s->i_pixel_pitch], s->i_pixel_pitch );
  430.         }
  431.     }
  432. }
  433. static void Convert( filter_t *p_filter, struct SwsContext *ctx,
  434.                      picture_t *p_dst, picture_t *p_src, int i_height, int i_plane_start, int i_plane_count )
  435. {
  436.     uint8_t palette[AVPALETTE_SIZE];
  437.     uint8_t *src[4]; int src_stride[4];
  438.     uint8_t *dst[4]; int dst_stride[4];
  439.     GetPixels( src, src_stride, p_src, i_plane_start, i_plane_count );
  440.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC( 'R', 'G', 'B', 'P' ) )
  441.     {
  442.         memset( palette, 0, sizeof(palette) );
  443.         if( p_filter->fmt_in.video.p_palette )
  444.             memcpy( palette, p_filter->fmt_in.video.p_palette->palette,
  445.                     __MIN( sizeof(video_palette_t), AVPALETTE_SIZE ) );
  446.         src[1] = palette;
  447.         src_stride[1] = 4;
  448.     }
  449.     GetPixels( dst, dst_stride, p_dst, i_plane_start, i_plane_count );
  450. #if LIBSWSCALE_VERSION_INT  >= ((0<<16)+(5<<8)+0)
  451.     sws_scale( ctx, src, src_stride, 0, i_height,
  452.                dst, dst_stride );
  453. #else
  454.     sws_scale_ordered( ctx, src, src_stride, 0, i_height,
  455.                        dst, dst_stride );
  456. #endif
  457. }
  458. /****************************************************************************
  459.  * Filter: the whole thing
  460.  ****************************************************************************
  461.  * This function is called just after the thread is launched.
  462.  ****************************************************************************/
  463. static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
  464. {
  465.     filter_sys_t *p_sys = p_filter->p_sys;
  466.     const video_format_t *p_fmti = &p_filter->fmt_in.video;
  467.     const video_format_t *p_fmto = &p_filter->fmt_out.video;
  468.     picture_t *p_pic_dst;
  469.     /* Check if format properties changed */
  470.     if( Init( p_filter ) )
  471.     {
  472.         picture_Release( p_pic );
  473.         return NULL;
  474.     }
  475.     /* Request output picture */
  476.     p_pic_dst = filter_NewPicture( p_filter );
  477.     if( !p_pic_dst )
  478.     {
  479.         picture_Release( p_pic );
  480.         return NULL;
  481.     }
  482.     /* */
  483.     picture_t *p_src = p_pic;
  484.     picture_t *p_dst = p_pic_dst;
  485.     if( p_sys->i_extend_factor != 1 )
  486.     {
  487.         p_src = p_sys->p_src_e;
  488.         p_dst = p_sys->p_dst_e;
  489.         CopyPad( p_src, p_pic );
  490.     }
  491.     if( p_sys->b_copy )
  492.         picture_CopyPixels( p_dst, p_src );
  493.     else
  494.         Convert( p_filter, p_sys->ctx, p_dst, p_src, p_fmti->i_height, 0, 3 );
  495.     if( p_sys->ctxA )
  496.     {
  497.         /* We extract the A plane to rescale it, and then we reinject it. */
  498.         if( p_fmti->i_chroma == VLC_FOURCC( 'R', 'G', 'B', 'A' ) )
  499.             ExtractA( p_sys->p_src_a, p_src, p_fmti->i_width * p_sys->i_extend_factor, p_fmti->i_height );
  500.         else
  501.             plane_CopyPixels( p_sys->p_src_a->p, p_src->p+A_PLANE );
  502.         Convert( p_filter, p_sys->ctxA, p_sys->p_dst_a, p_sys->p_src_a, p_fmti->i_height, 0, 1 );
  503.         if( p_fmto->i_chroma == VLC_FOURCC( 'R', 'G', 'B', 'A' ) )
  504.             InjectA( p_dst, p_sys->p_dst_a, p_fmto->i_width * p_sys->i_extend_factor, p_fmto->i_height );
  505.         else
  506.             plane_CopyPixels( p_dst->p+A_PLANE, p_sys->p_dst_a->p );
  507.     }
  508.     else if( p_sys->b_add_a )
  509.     {
  510.         /* We inject a complete opaque alpha plane */
  511.         if( p_fmto->i_chroma == VLC_FOURCC( 'R', 'G', 'B', 'A' ) )
  512.             FillA( &p_dst->p[0], OFFSET_A );
  513.         else
  514.             FillA( &p_dst->p[A_PLANE], 0 );
  515.     }
  516.     if( p_sys->i_extend_factor != 1 )
  517.     {
  518.         picture_CopyPixels( p_pic_dst, p_dst );
  519.     }
  520.     picture_CopyProperties( p_pic_dst, p_pic );
  521.     picture_Release( p_pic );
  522.     return p_pic_dst;
  523. }
  524. #else /* LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) */
  525. int OpenScaler( vlc_object_t *p_this )
  526. {
  527.     return VLC_EGENERIC;
  528. }
  529. void CloseScaler( vlc_object_t *p_this )
  530. {
  531. }
  532. #endif /* LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) */