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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * filter.c: video scaling module using the swscale library
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: filter.c 8848 2004-09-29 14:21:31Z fkuehne $
  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. #include "common.h"
  30. #include "swscale.h"
  31. void *( *swscale_fast_memcpy )( void *, const void *, size_t );
  32. /*****************************************************************************
  33.  * filter_sys_t : filter descriptor
  34.  *****************************************************************************/
  35. struct filter_sys_t
  36. {
  37.     struct SwsContext *ctx;
  38.     SwsFilter *p_src_filter;
  39.     SwsFilter *p_dst_filter;
  40.     int i_cpu_mask, i_sws_flags;
  41.     es_format_t fmt_in;
  42.     es_format_t fmt_out;
  43. };
  44. /****************************************************************************
  45.  * Local prototypes
  46.  ****************************************************************************/
  47. static int  OpenFilter ( vlc_object_t * );
  48. static void CloseFilter( vlc_object_t * );
  49. static picture_t *Filter( filter_t *, picture_t * );
  50. static int CheckInit( filter_t * );
  51. static int GetSwscaleChroma( vlc_fourcc_t );
  52. /*****************************************************************************
  53.  * Module descriptor
  54.  *****************************************************************************/
  55. #define MODE_TEXT N_("Scaling mode")
  56. #define MODE_LONGTEXT N_("You can choose the default scaling mode.")
  57. static int pi_mode_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
  58. static char *ppsz_mode_descriptions[] =
  59. { N_("Fast bilinear"), N_("Bilinear"), N_("Bicubic (good quality)"),
  60.   N_("Experimental"), N_("Nearest neighbour (bad quality)"),
  61.   N_("Area"), N_("Luma bicubic / chroma bilinear"), N_("Gauss"),
  62.   N_("SincR"), N_("Lanczos"), N_("Bicubic spline") };
  63. vlc_module_begin();
  64.     set_description( _("Video scaling filter") );
  65.     set_capability( "video filter2", 1000 );
  66.     set_callbacks( OpenFilter, CloseFilter );
  67.     add_integer( "swscale-mode", 0, NULL, MODE_TEXT, MODE_LONGTEXT, VLC_TRUE );
  68.         change_integer_list( pi_mode_values, ppsz_mode_descriptions, 0 );
  69. vlc_module_end();
  70. /*****************************************************************************
  71.  * OpenFilter: probe the filter and return score
  72.  *****************************************************************************/
  73. static int OpenFilter( vlc_object_t *p_this )
  74. {
  75.     filter_t *p_filter = (filter_t*)p_this;
  76.     filter_sys_t *p_sys;
  77.     vlc_value_t val;
  78.     unsigned int i_fmt_in, i_fmt_out;
  79.     int i_sws_mode;
  80.     float sws_lum_gblur = 0.0, sws_chr_gblur = 0.0;
  81.     int sws_chr_vshift = 0, sws_chr_hshift = 0;
  82.     float sws_chr_sharpen = 0.0, sws_lum_sharpen = 0.0;
  83.     /* Supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR24,
  84.      * BGR16, BGR15, RGB32, RGB24, Y8/Y800, YVU9/IF09 */
  85.     if( !(i_fmt_in = GetSwscaleChroma(p_filter->fmt_in.video.i_chroma)) )
  86.     {
  87.         return VLC_EGENERIC;
  88.     }
  89.     /* Supported output formats: YV12, I420/IYUV, YUY2, UYVY,
  90.      * {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09 */
  91.     if( !(i_fmt_out = GetSwscaleChroma(p_filter->fmt_out.video.i_chroma)) )
  92.     {
  93.         return VLC_EGENERIC;
  94.     }
  95.     /* Allocate the memory needed to store the decoder's structure */
  96.     if( ( p_filter->p_sys = p_sys =
  97.           (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
  98.     {
  99.         msg_Err( p_filter, "out of memory" );
  100.         return VLC_EGENERIC;
  101.     }
  102.     swscale_fast_memcpy = p_filter->p_vlc->pf_memcpy;
  103.     /* Set CPU capabilities */
  104.     p_sys->i_cpu_mask = 0;
  105.     if( p_filter->p_libvlc->i_cpu & CPU_CAPABILITY_MMX )
  106.     {
  107.         p_sys->i_cpu_mask |= SWS_CPU_CAPS_MMX;
  108.     }
  109.     if( p_filter->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT )
  110.     {
  111.         p_sys->i_cpu_mask |= SWS_CPU_CAPS_MMX2;
  112.     }
  113.     if( p_filter->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW )
  114.     {
  115.         p_sys->i_cpu_mask |= SWS_CPU_CAPS_3DNOW;
  116.     }
  117.     if( p_filter->p_libvlc->i_cpu & CPU_CAPABILITY_ALTIVEC )
  118.     {
  119.         p_sys->i_cpu_mask |= SWS_CPU_CAPS_ALTIVEC;
  120.     }
  121.     var_Create( p_filter, "swscale-mode", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
  122.     var_Get( p_filter, "swscale-mode", &val );
  123.     i_sws_mode = val.i_int;
  124.     switch( i_sws_mode )
  125.     {
  126.     case 0:  p_sys->i_sws_flags = SWS_FAST_BILINEAR; break;
  127.     case 1:  p_sys->i_sws_flags = SWS_BILINEAR; break;
  128.     case 2:  p_sys->i_sws_flags = SWS_BICUBIC; break;
  129.     case 3:  p_sys->i_sws_flags = SWS_X; break;
  130.     case 4:  p_sys->i_sws_flags = SWS_POINT; break;
  131.     case 5:  p_sys->i_sws_flags = SWS_AREA; break;
  132.     case 6:  p_sys->i_sws_flags = SWS_BICUBLIN; break;
  133.     case 7:  p_sys->i_sws_flags = SWS_GAUSS; break;
  134.     case 8:  p_sys->i_sws_flags = SWS_SINC; break;
  135.     case 9:  p_sys->i_sws_flags = SWS_LANCZOS; break;
  136.     case 10: p_sys->i_sws_flags = SWS_SPLINE; break;
  137.     default: p_sys->i_sws_flags = SWS_FAST_BILINEAR; i_sws_mode = 0; break;
  138.     }
  139.     p_sys->p_src_filter = 0; p_sys->p_dst_filter = 0;
  140.     p_sys->p_src_filter =
  141.         sws_getDefaultFilter( sws_lum_gblur, sws_chr_gblur,
  142.                               sws_lum_sharpen, sws_chr_sharpen,
  143.                               sws_chr_hshift, sws_chr_vshift, 0 );
  144.     /* Misc init */
  145.     p_sys->ctx = NULL;
  146.     p_filter->pf_video_filter = Filter;
  147.     es_format_Init( &p_sys->fmt_in, 0, 0 );
  148.     es_format_Init( &p_sys->fmt_out, 0, 0 );
  149.     if( CheckInit( p_filter ) != VLC_SUCCESS )
  150.     {
  151.         if( p_sys->p_src_filter ) sws_freeFilter( p_sys->p_src_filter );
  152.         free( p_sys );
  153.         return VLC_EGENERIC;
  154.     }
  155.     msg_Dbg( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s",
  156.              p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height,
  157.              (char *)&p_filter->fmt_in.video.i_chroma,
  158.              p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height,
  159.              (char *)&p_filter->fmt_out.video.i_chroma );
  160.     if( p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width ||
  161.         p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height )
  162.     {
  163.         msg_Dbg( p_filter, "scaling mode: %s",
  164.                  ppsz_mode_descriptions[i_sws_mode] );
  165.     }
  166.     return VLC_SUCCESS;
  167. }
  168. /*****************************************************************************
  169.  * CloseFilter: clean up the filter
  170.  *****************************************************************************/
  171. static void CloseFilter( vlc_object_t *p_this )
  172. {
  173.     filter_t *p_filter = (filter_t*)p_this;
  174.     filter_sys_t *p_sys = p_filter->p_sys;
  175.     if( p_sys->ctx ) sws_freeContext( p_sys->ctx );
  176.     if( p_sys->p_src_filter ) sws_freeFilter( p_sys->p_src_filter );
  177.     free( p_sys );
  178. }
  179. /*****************************************************************************
  180.  * CheckInit: Initialise filter when necessary
  181.  *****************************************************************************/
  182. static int CheckInit( filter_t *p_filter )
  183. {
  184.     filter_sys_t *p_sys = p_filter->p_sys;
  185.     if( p_filter->fmt_in.video.i_width != p_sys->fmt_in.video.i_width ||
  186.         p_filter->fmt_in.video.i_height != p_sys->fmt_in.video.i_height ||
  187.         p_filter->fmt_out.video.i_width != p_sys->fmt_out.video.i_width ||
  188.         p_filter->fmt_out.video.i_height != p_sys->fmt_out.video.i_height )
  189.     {
  190.         unsigned int i_fmt_in, i_fmt_out;
  191.         if( !(i_fmt_in = GetSwscaleChroma(p_filter->fmt_in.video.i_chroma)) ||
  192.             !(i_fmt_out = GetSwscaleChroma(p_filter->fmt_out.video.i_chroma)) )
  193.         {
  194.             msg_Err( p_filter, "format not supported" );
  195.             return VLC_EGENERIC;
  196.         }
  197.         if( p_sys->ctx ) sws_freeContext( p_sys->ctx );
  198.         p_sys->ctx =
  199.             sws_getContext( p_filter->fmt_in.video.i_width,
  200.                             p_filter->fmt_in.video.i_height, i_fmt_in,
  201.                             p_filter->fmt_out.video.i_width,
  202.                             p_filter->fmt_out.video.i_height, i_fmt_out,
  203.                             p_sys->i_sws_flags | p_sys->i_cpu_mask,
  204.                             p_sys->p_src_filter, p_sys->p_dst_filter );
  205.         if( !p_sys->ctx )
  206.         {
  207.             msg_Err( p_filter, "could not init SwScaler" );
  208.             return VLC_EGENERIC;
  209.         }
  210.         p_sys->fmt_in = p_filter->fmt_in;
  211.         p_sys->fmt_out = p_filter->fmt_out;
  212.     }
  213.     return VLC_SUCCESS;
  214. }
  215. /****************************************************************************
  216.  * Filter: the whole thing
  217.  ****************************************************************************
  218.  * This function is called just after the thread is launched.
  219.  ****************************************************************************/
  220. static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
  221. {
  222.     filter_sys_t *p_sys = p_filter->p_sys;
  223.     uint8_t *src[3]; int src_stride[3];
  224.     uint8_t *dst[3]; int dst_stride[3];
  225.     picture_t *p_pic_dst;
  226.     int i_plane;
  227.     /* Check if format properties changed */
  228.     if( CheckInit( p_filter ) != VLC_SUCCESS ) return 0;
  229.     /* Request output picture */
  230.     p_pic_dst = p_filter->pf_vout_buffer_new( p_filter );
  231.     if( !p_pic_dst )
  232.     {
  233.         msg_Warn( p_filter, "can't get output picture" );
  234.         return NULL;
  235.     }
  236.     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
  237.     {
  238.         src[i_plane] = p_pic->p[i_plane].p_pixels;
  239.         src_stride[i_plane] = p_pic->p[i_plane].i_pitch;
  240.     }
  241.     for( i_plane = 0; i_plane < p_pic_dst->i_planes; i_plane++ )
  242.     {
  243.         dst[i_plane] = p_pic_dst->p[i_plane].p_pixels;
  244.         dst_stride[i_plane] = p_pic_dst->p[i_plane].i_pitch;
  245.     }
  246.     sws_scale_ordered( p_sys->ctx, src, src_stride,
  247.                        0, p_filter->fmt_in.video.i_height,
  248.                        dst, dst_stride );
  249.     p_pic_dst->date = p_pic->date;
  250.     p_pic_dst->b_force = p_pic->b_force;
  251.     p_pic_dst->i_nb_fields = p_pic->i_nb_fields;
  252.     p_pic_dst->b_progressive = p_pic->b_progressive;
  253.     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
  254.     p_pic->pf_release( p_pic );
  255.     return p_pic_dst;
  256. }
  257. /*****************************************************************************
  258.  * Chroma fourcc -> ffmpeg_id mapping
  259.  *****************************************************************************/
  260. static struct
  261. {
  262.     vlc_fourcc_t  i_chroma;
  263.     unsigned int  i_swscale_chroma;
  264. } chroma_table[] =
  265. {
  266.     /* Planar YUV formats */
  267.     { VLC_FOURCC('Y','V','1','2'), IMGFMT_YV12 },
  268.     { VLC_FOURCC('I','4','2','0'), IMGFMT_I420 },
  269.     { VLC_FOURCC('I','Y','U','V'), IMGFMT_IYUV },
  270.     { VLC_FOURCC('I','4','4','4'), IMGFMT_444P },
  271.     { VLC_FOURCC('I','4','2','2'), IMGFMT_422P },
  272.     { VLC_FOURCC('I','4','1','1'), IMGFMT_411P },
  273. #if 0
  274.     { VLC_FOURCC('Y','U','V','P'), IMGFMT_Y800 },
  275. #endif
  276.     /* Packed YUV formats */
  277.     { VLC_FOURCC('U','Y','V','Y'), IMGFMT_UYVY },
  278.     { VLC_FOURCC('Y','U','Y','2'), IMGFMT_YUY2 },
  279.     /* Packed RGB formats */
  280.     { VLC_FOURCC('R','V','1','5'), IMGFMT_RGB15 },
  281.     { VLC_FOURCC('R','V','1','6'), IMGFMT_RGB16 },
  282.     { VLC_FOURCC('R','V','2','4'), IMGFMT_RGB24 },
  283.     { VLC_FOURCC('R','V','3','2'), IMGFMT_RGB32 },
  284.     { VLC_FOURCC('G','R','E','Y'), IMGFMT_RGB8 },
  285.     {0}
  286. };
  287. static int GetSwscaleChroma( vlc_fourcc_t i_chroma )
  288. {
  289.     int i;
  290.     for( i = 0; chroma_table[i].i_chroma != 0; i++ )
  291.     {
  292.         if( chroma_table[i].i_chroma == i_chroma )
  293.             return chroma_table[i].i_swscale_chroma;
  294.     }
  295.     return 0;
  296. }