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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * video filter: video filter doing chroma conversion and resizing
  3.  *               using the ffmpeg library
  4.  *****************************************************************************
  5.  * Copyright (C) 1999-2001 VideoLAN
  6.  * $Id: video_filter.c 8991 2004-10-14 22:14:09Z gbazin $
  7.  *
  8.  * Authors: 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <vlc/vlc.h>
  28. #include <vlc/decoder.h>
  29. #include "vlc_filter.h"
  30. /* ffmpeg header */
  31. #ifdef HAVE_FFMPEG_AVCODEC_H
  32. #   include <ffmpeg/avcodec.h>
  33. #else
  34. #   include <avcodec.h>
  35. #endif
  36. #include "ffmpeg.h"
  37. void E_(InitLibavcodec) ( vlc_object_t *p_object );
  38. static int CheckInit( filter_t *p_filter );
  39. static picture_t *Process( filter_t *p_filter, picture_t *p_pic );
  40. static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic );
  41. /*****************************************************************************
  42.  * filter_sys_t : filter descriptor
  43.  *****************************************************************************/
  44. struct filter_sys_t
  45. {
  46.     vlc_bool_t b_resize;
  47.     vlc_bool_t b_convert;
  48.     es_format_t fmt_in;
  49.     int i_src_ffmpeg_chroma;
  50.     es_format_t fmt_out;
  51.     int i_dst_ffmpeg_chroma;
  52.     AVPicture tmp_pic;
  53.     ImgReSampleContext *p_rsc;
  54. };
  55. /*****************************************************************************
  56.  * OpenFilter: probe the filter and return score
  57.  *****************************************************************************/
  58. int E_(OpenFilter)( vlc_object_t *p_this )
  59. {
  60.     filter_t *p_filter = (filter_t*)p_this;
  61.     filter_sys_t *p_sys;
  62.     vlc_bool_t b_convert, b_resize;
  63.     /* Check if we can handle that formats */
  64.     if( E_(GetFfmpegChroma)( p_filter->fmt_in.video.i_chroma ) < 0 ||
  65.         E_(GetFfmpegChroma)( p_filter->fmt_out.video.i_chroma ) < 0 )
  66.     {
  67.         return VLC_EGENERIC;
  68.     }
  69.     b_resize =
  70.         p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width ||
  71.         p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height;
  72.     b_convert =
  73.         p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma;
  74.     if( !b_resize && !b_convert )
  75.     {
  76.         /* Nothing to do */
  77.         return VLC_EGENERIC;
  78.     }
  79.     /* Allocate the memory needed to store the decoder's structure */
  80.     if( ( p_filter->p_sys = p_sys =
  81.           (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
  82.     {
  83.         msg_Err( p_filter, "out of memory" );
  84.         return VLC_EGENERIC;
  85.     }
  86.     /* Misc init */
  87.     p_sys->p_rsc = NULL;
  88.     p_sys->b_convert = b_convert;
  89.     p_sys->i_src_ffmpeg_chroma =
  90.         E_(GetFfmpegChroma)( p_filter->fmt_in.video.i_chroma );
  91.     p_sys->i_dst_ffmpeg_chroma =
  92.         E_(GetFfmpegChroma)( p_filter->fmt_out.video.i_chroma );
  93.     p_filter->pf_video_filter = Process;
  94.     es_format_Init( &p_sys->fmt_in, 0, 0 );
  95.     es_format_Init( &p_sys->fmt_out, 0, 0 );
  96.     if( CheckInit( p_filter ) != VLC_SUCCESS )
  97.     {
  98.         free( p_sys );
  99.         return VLC_EGENERIC;
  100.     }
  101.     avpicture_alloc( &p_sys->tmp_pic, p_sys->i_dst_ffmpeg_chroma,
  102.                      p_filter->fmt_in.video.i_width,
  103.                      p_filter->fmt_in.video.i_height );
  104.     msg_Dbg( p_filter, "input: %ix%i %4.4s -> %ix%i %4.4s",
  105.              p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height,
  106.              (char *)&p_filter->fmt_in.video.i_chroma,
  107.              p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height,
  108.              (char *)&p_filter->fmt_out.video.i_chroma );
  109.     /* libavcodec needs to be initialized for some chroma conversions */
  110.     E_(InitLibavcodec)(p_this);
  111.     return VLC_SUCCESS;
  112. }
  113. /*****************************************************************************
  114.  * CloseFilter: clean up the filter
  115.  *****************************************************************************/
  116. void E_(CloseFilter)( vlc_object_t *p_this )
  117. {
  118.     filter_t *p_filter = (filter_t*)p_this;
  119.     filter_sys_t *p_sys = p_filter->p_sys;
  120.     if( p_sys->p_rsc ) img_resample_close( p_sys->p_rsc );
  121.     avpicture_free( &p_sys->tmp_pic );
  122.     free( p_sys );
  123. }
  124. /*****************************************************************************
  125.  * CheckInit: Initialise filter when necessary
  126.  *****************************************************************************/
  127. static int CheckInit( filter_t *p_filter )
  128. {
  129.     filter_sys_t *p_sys = p_filter->p_sys;
  130.     if( p_filter->fmt_in.video.i_width != p_sys->fmt_in.video.i_width ||
  131.         p_filter->fmt_in.video.i_height != p_sys->fmt_in.video.i_height ||
  132.         p_filter->fmt_out.video.i_width != p_sys->fmt_out.video.i_width ||
  133.         p_filter->fmt_out.video.i_height != p_sys->fmt_out.video.i_height )
  134.     {
  135.         if( p_sys->p_rsc ) img_resample_close( p_sys->p_rsc );
  136.         p_sys->p_rsc = 0;
  137.         p_sys->b_resize =
  138.           p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width ||
  139.           p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height;
  140.         if( p_sys->b_resize )
  141.         {
  142.             p_sys->p_rsc = img_resample_init( p_filter->fmt_out.video.i_width,
  143.                                p_filter->fmt_out.video.i_height,
  144.                                p_filter->fmt_in.video.i_width,
  145.                                p_filter->fmt_in.video.i_height );
  146.             if( !p_sys->p_rsc )
  147.             {
  148.                 msg_Err( p_filter, "img_resample_init failed" );
  149.                 return VLC_EGENERIC;
  150.             }
  151.         }
  152.         p_sys->fmt_in = p_filter->fmt_in;
  153.         p_sys->fmt_out = p_filter->fmt_out;
  154.     }
  155.     return VLC_SUCCESS;
  156. }
  157. /*****************************************************************************
  158.  * Do the processing here
  159.  *****************************************************************************/
  160. static picture_t *Process( filter_t *p_filter, picture_t *p_pic )
  161. {
  162.     filter_sys_t *p_sys = p_filter->p_sys;
  163.     AVPicture src_pic, dest_pic, inter_pic;
  164.     picture_t *p_pic_dst;
  165.     vlc_bool_t b_resize = p_sys->b_resize;
  166.     int i;
  167.     /* Check if format properties changed */
  168.     if( CheckInit( p_filter ) != VLC_SUCCESS ) return 0;
  169.     /* Request output picture */
  170.     p_pic_dst = p_filter->pf_vout_buffer_new( p_filter );
  171.     if( !p_pic_dst )
  172.     {
  173.         msg_Warn( p_filter, "can't get output picture" );
  174.         p_pic->pf_release( p_pic );
  175.         return NULL;
  176.     }
  177.     /* Prepare the AVPictures for the conversion */
  178.     for( i = 0; i < p_pic->i_planes; i++ )
  179.     {
  180.         src_pic.data[i] = p_pic->p[i].p_pixels;
  181.         src_pic.linesize[i] = p_pic->p[i].i_pitch;
  182.     }
  183.     for( i = 0; i < p_pic_dst->i_planes; i++ )
  184.     {
  185.         dest_pic.data[i] = p_pic_dst->p[i].p_pixels;
  186.         dest_pic.linesize[i] = p_pic_dst->p[i].i_pitch;
  187.     }
  188.     /* Special cases */
  189.     if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','V','1','2') ||
  190.         p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','V','U','9') )
  191.     {
  192.         /* Invert U and V */
  193.         src_pic.data[1] = p_pic->p[2].p_pixels;
  194.         src_pic.data[2] = p_pic->p[1].p_pixels;
  195.     }
  196.     if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','1','2') ||
  197.         p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','U','9') )
  198.     {
  199.         /* Invert U and V */
  200.         dest_pic.data[1] = p_pic_dst->p[2].p_pixels;
  201.         dest_pic.data[2] = p_pic_dst->p[1].p_pixels;
  202.     }
  203.     if( p_sys->i_src_ffmpeg_chroma == PIX_FMT_RGB24 )
  204.         if( p_filter->fmt_in.video.i_bmask == 0x00ff0000 )
  205.             p_sys->i_src_ffmpeg_chroma = PIX_FMT_BGR24;
  206. #if 0
  207.     if( p_sys->b_resize &&
  208.         p_filter->fmt_in.video.i_width * p_filter->fmt_in.video.i_height >
  209.         p_filter->fmt_out.video.i_width * p_filter->fmt_out.video.i_height )
  210.     {
  211.         img_resample( p_sys->p_rsc, &dest_pic, &p_sys->tmp_pic );
  212.         b_resize = 0;
  213.     }
  214. #endif
  215.     if( p_sys->b_convert )
  216.     {
  217.         if( p_sys->b_resize ) inter_pic = p_sys->tmp_pic;
  218.         else inter_pic = dest_pic;
  219.         img_convert( &inter_pic, p_sys->i_dst_ffmpeg_chroma,
  220.                      &src_pic, p_sys->i_src_ffmpeg_chroma,
  221.                      p_filter->fmt_in.video.i_width,
  222.                      p_filter->fmt_in.video.i_height );
  223.         src_pic = inter_pic;
  224.     }
  225.     if( p_sys->b_resize && p_sys->p_rsc )
  226.     {
  227.         img_resample( p_sys->p_rsc, &dest_pic, &src_pic );
  228.     }
  229.     p_pic_dst->date = p_pic->date;
  230.     p_pic_dst->b_force = p_pic->b_force;
  231.     p_pic_dst->i_nb_fields = p_pic->i_nb_fields;
  232.     p_pic_dst->b_progressive = p_pic->b_progressive;
  233.     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
  234.     p_pic->pf_release( p_pic );
  235.     return p_pic_dst;
  236. }
  237. /*****************************************************************************
  238.  * OpenDeinterlace: probe the filter and return score
  239.  *****************************************************************************/
  240. int E_(OpenDeinterlace)( vlc_object_t *p_this )
  241. {
  242.     filter_t *p_filter = (filter_t*)p_this;
  243.     filter_sys_t *p_sys;
  244.     /* Check if we can handle that formats */
  245.     if( E_(GetFfmpegChroma)( p_filter->fmt_in.video.i_chroma ) < 0 )
  246.     {
  247.         return VLC_EGENERIC;
  248.     }
  249.     /* Allocate the memory needed to store the decoder's structure */
  250.     if( ( p_filter->p_sys = p_sys =
  251.           (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
  252.     {
  253.         msg_Err( p_filter, "out of memory" );
  254.         return VLC_EGENERIC;
  255.     }
  256.     /* Misc init */
  257.     p_sys->i_src_ffmpeg_chroma =
  258.         E_(GetFfmpegChroma)( p_filter->fmt_in.video.i_chroma );
  259.     p_filter->pf_video_filter = Deinterlace;
  260.     msg_Dbg( p_filter, "deinterlacing" );
  261.     /* libavcodec needs to be initialized for some chroma conversions */
  262.     E_(InitLibavcodec)(p_this);
  263.     return VLC_SUCCESS;
  264. }
  265. /*****************************************************************************
  266.  * CloseDeinterlace: clean up the filter
  267.  *****************************************************************************/
  268. void E_(CloseDeinterlace)( vlc_object_t *p_this )
  269. {
  270.     filter_t *p_filter = (filter_t*)p_this;
  271.     filter_sys_t *p_sys = p_filter->p_sys;
  272.     free( p_sys );
  273. }
  274. /*****************************************************************************
  275.  * Do the processing here
  276.  *****************************************************************************/
  277. static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
  278. {
  279.     filter_sys_t *p_sys = p_filter->p_sys;
  280.     AVPicture src_pic, dest_pic;
  281.     picture_t *p_pic_dst;
  282.     int i;
  283.     /* Request output picture */
  284.     p_pic_dst = p_filter->pf_vout_buffer_new( p_filter );
  285.     if( !p_pic_dst )
  286.     {
  287.         msg_Warn( p_filter, "can't get output picture" );
  288.         return NULL;
  289.     }
  290.     /* Prepare the AVPictures for the conversion */
  291.     for( i = 0; i < p_pic->i_planes; i++ )
  292.     {
  293.         src_pic.data[i] = p_pic->p[i].p_pixels;
  294.         src_pic.linesize[i] = p_pic->p[i].i_pitch;
  295.     }
  296.     for( i = 0; i < p_pic_dst->i_planes; i++ )
  297.     {
  298.         dest_pic.data[i] = p_pic_dst->p[i].p_pixels;
  299.         dest_pic.linesize[i] = p_pic_dst->p[i].i_pitch;
  300.     }
  301.     avpicture_deinterlace( &dest_pic, &src_pic, p_sys->i_src_ffmpeg_chroma,
  302.                            p_filter->fmt_in.video.i_width,
  303.                            p_filter->fmt_in.video.i_height );
  304.     p_pic_dst->date = p_pic->date;
  305.     p_pic_dst->b_force = p_pic->b_force;
  306.     p_pic_dst->i_nb_fields = p_pic->i_nb_fields;
  307.     p_pic_dst->b_progressive = VLC_TRUE;
  308.     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
  309.     p_pic->pf_release( p_pic );
  310.     return p_pic_dst;
  311. }