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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * image.c : wrapper for image reading/writing facilities
  3.  *****************************************************************************
  4.  * Copyright (C) 2004-2007 the VideoLAN team
  5.  * $Id: b0a808f82de35fa62dc996f15bfc905d42a5aaeb $
  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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /**
  24.  * file
  25.  * This file contains the functions to handle the image_handler_t type
  26.  */
  27. /*****************************************************************************
  28.  * Preamble
  29.  *****************************************************************************/
  30. #ifdef HAVE_CONFIG_H
  31. # include "config.h"
  32. #endif
  33. #include <ctype.h>
  34. #include <errno.h>
  35. #include <vlc_common.h>
  36. #include <vlc_codec.h>
  37. #include <vlc_meta.h>
  38. #include <vlc_filter.h>
  39. #include <vlc_es.h>
  40. #include <vlc_image.h>
  41. #include <vlc_stream.h>
  42. #include <vlc_charset.h>
  43. #include <vlc_sout.h>
  44. #include <libvlc.h>
  45. static picture_t *ImageRead( image_handler_t *, block_t *,
  46.                              video_format_t *, video_format_t * );
  47. static picture_t *ImageReadUrl( image_handler_t *, const char *,
  48.                                 video_format_t *, video_format_t * );
  49. static block_t *ImageWrite( image_handler_t *, picture_t *,
  50.                             video_format_t *, video_format_t * );
  51. static int ImageWriteUrl( image_handler_t *, picture_t *,
  52.                           video_format_t *, video_format_t *, const char * );
  53. static picture_t *ImageConvert( image_handler_t *, picture_t *,
  54.                                 video_format_t *, video_format_t * );
  55. static picture_t *ImageFilter( image_handler_t *, picture_t *,
  56.                                video_format_t *, const char *psz_module );
  57. static decoder_t *CreateDecoder( vlc_object_t *, video_format_t * );
  58. static void DeleteDecoder( decoder_t * );
  59. static encoder_t *CreateEncoder( vlc_object_t *, video_format_t *,
  60.                                  video_format_t * );
  61. static void DeleteEncoder( encoder_t * );
  62. static filter_t *CreateFilter( vlc_object_t *, es_format_t *,
  63.                                video_format_t *, const char * );
  64. static void DeleteFilter( filter_t * );
  65. vlc_fourcc_t image_Type2Fourcc( const char * );
  66. vlc_fourcc_t image_Ext2Fourcc( const char * );
  67. /*static const char *Fourcc2Ext( vlc_fourcc_t );*/
  68. /**
  69.  * Create an image_handler_t instance
  70.  *
  71.  */
  72. image_handler_t *__image_HandlerCreate( vlc_object_t *p_this )
  73. {
  74.     image_handler_t *p_image = calloc( 1, sizeof(image_handler_t) );
  75.     if( !p_image )
  76.         return NULL;
  77.     p_image->p_parent = p_this;
  78.     p_image->pf_read = ImageRead;
  79.     p_image->pf_read_url = ImageReadUrl;
  80.     p_image->pf_write = ImageWrite;
  81.     p_image->pf_write_url = ImageWriteUrl;
  82.     p_image->pf_convert = ImageConvert;
  83.     p_image->pf_filter = ImageFilter;
  84.     return p_image;
  85. }
  86. /**
  87.  * Delete the image_handler_t instance
  88.  *
  89.  */
  90. void image_HandlerDelete( image_handler_t *p_image )
  91. {
  92.     if( !p_image ) return;
  93.     if( p_image->p_dec ) DeleteDecoder( p_image->p_dec );
  94.     if( p_image->p_enc ) DeleteEncoder( p_image->p_enc );
  95.     if( p_image->p_filter ) DeleteFilter( p_image->p_filter );
  96.     free( p_image );
  97.     p_image = NULL;
  98. }
  99. /**
  100.  * Read an image
  101.  *
  102.  */
  103. static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
  104.                              video_format_t *p_fmt_in,
  105.                              video_format_t *p_fmt_out )
  106. {
  107.     picture_t *p_pic = NULL, *p_tmp;
  108.     /* Check if we can reuse the current decoder */
  109.     if( p_image->p_dec &&
  110.         p_image->p_dec->fmt_in.i_codec != p_fmt_in->i_chroma )
  111.     {
  112.         DeleteDecoder( p_image->p_dec );
  113.         p_image->p_dec = 0;
  114.     }
  115.     /* Start a decoder */
  116.     if( !p_image->p_dec )
  117.     {
  118.         p_image->p_dec = CreateDecoder( p_image->p_parent, p_fmt_in );
  119.         if( !p_image->p_dec ) return NULL;
  120.     }
  121.     p_block->i_pts = p_block->i_dts = mdate();
  122.     while( (p_tmp = p_image->p_dec->pf_decode_video( p_image->p_dec, &p_block ))
  123.              != NULL )
  124.     {
  125.         if( p_pic != NULL )
  126.             picture_Release( p_pic );
  127.         p_pic = p_tmp;
  128.     }
  129.     if( p_pic == NULL )
  130.     {
  131.         msg_Warn( p_image->p_parent, "no image decoded" );
  132.         return 0;
  133.     }
  134.     if( !p_fmt_out->i_chroma )
  135.         p_fmt_out->i_chroma = p_image->p_dec->fmt_out.video.i_chroma;
  136.     if( !p_fmt_out->i_width && p_fmt_out->i_height )
  137.         p_fmt_out->i_width = p_fmt_out->i_height
  138.                               * p_image->p_dec->fmt_out.video.i_aspect
  139.                               / VOUT_ASPECT_FACTOR;
  140.     if( !p_fmt_out->i_height && p_fmt_out->i_width )
  141.         p_fmt_out->i_height = p_fmt_out->i_width * VOUT_ASPECT_FACTOR
  142.                                / p_image->p_dec->fmt_out.video.i_aspect;
  143.     if( !p_fmt_out->i_width )
  144.         p_fmt_out->i_width = p_image->p_dec->fmt_out.video.i_width;
  145.     if( !p_fmt_out->i_height )
  146.         p_fmt_out->i_height = p_image->p_dec->fmt_out.video.i_height;
  147.     /* Check if we need chroma conversion or resizing */
  148.     if( p_image->p_dec->fmt_out.video.i_chroma != p_fmt_out->i_chroma ||
  149.         p_image->p_dec->fmt_out.video.i_width != p_fmt_out->i_width ||
  150.         p_image->p_dec->fmt_out.video.i_height != p_fmt_out->i_height )
  151.     {
  152.         if( p_image->p_filter )
  153.         if( p_image->p_filter->fmt_in.video.i_chroma !=
  154.             p_image->p_dec->fmt_out.video.i_chroma ||
  155.             p_image->p_filter->fmt_out.video.i_chroma != p_fmt_out->i_chroma )
  156.         {
  157.             /* We need to restart a new filter */
  158.             DeleteFilter( p_image->p_filter );
  159.             p_image->p_filter = 0;
  160.         }
  161.         /* Start a filter */
  162.         if( !p_image->p_filter )
  163.         {
  164.             p_image->p_filter =
  165.                 CreateFilter( p_image->p_parent, &p_image->p_dec->fmt_out,
  166.                               p_fmt_out, NULL );
  167.             if( !p_image->p_filter )
  168.             {
  169.                 picture_Release( p_pic );
  170.                 return NULL;
  171.             }
  172.         }
  173.         else
  174.         {
  175.             /* Filters should handle on-the-fly size changes */
  176.             p_image->p_filter->fmt_in = p_image->p_dec->fmt_out;
  177.             p_image->p_filter->fmt_out = p_image->p_dec->fmt_out;
  178.             p_image->p_filter->fmt_out.i_codec = p_fmt_out->i_chroma;
  179.             p_image->p_filter->fmt_out.video = *p_fmt_out;
  180.         }
  181.         p_pic = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
  182.         *p_fmt_out = p_image->p_filter->fmt_out.video;
  183.     }
  184.     else *p_fmt_out = p_image->p_dec->fmt_out.video;
  185.     return p_pic;
  186. }
  187. static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
  188.                                 video_format_t *p_fmt_in,
  189.                                 video_format_t *p_fmt_out )
  190. {
  191.     block_t *p_block;
  192.     picture_t *p_pic;
  193.     stream_t *p_stream = NULL;
  194.     int i_size;
  195.     p_stream = stream_UrlNew( p_image->p_parent, psz_url );
  196.     if( !p_stream )
  197.     {
  198.         msg_Dbg( p_image->p_parent, "could not open %s for reading",
  199.                  psz_url );
  200.         return NULL;
  201.     }
  202.     i_size = stream_Size( p_stream );
  203.     p_block = block_New( p_image->p_parent, i_size );
  204.     stream_Read( p_stream, p_block->p_buffer, i_size );
  205.     if( !p_fmt_in->i_chroma )
  206.     {
  207.         char *psz_mime = NULL;
  208.         stream_Control( p_stream, STREAM_GET_CONTENT_TYPE, &psz_mime );
  209.         if( psz_mime )
  210.             p_fmt_in->i_chroma = image_Mime2Fourcc( psz_mime );
  211.         free( psz_mime );
  212.     }
  213.     stream_Delete( p_stream );
  214.     if( !p_fmt_in->i_chroma )
  215.     {
  216.         /* Try to guess format from file name */
  217.         p_fmt_in->i_chroma = image_Ext2Fourcc( psz_url );
  218.     }
  219.     p_pic = ImageRead( p_image, p_block, p_fmt_in, p_fmt_out );
  220.     return p_pic;
  221. }
  222. /**
  223.  * Write an image
  224.  *
  225.  */
  226. static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
  227.                             video_format_t *p_fmt_in,
  228.                             video_format_t *p_fmt_out )
  229. {
  230.     block_t *p_block;
  231.     /* Check if we can reuse the current encoder */
  232.     if( p_image->p_enc &&
  233.         ( p_image->p_enc->fmt_out.i_codec != p_fmt_out->i_chroma ||
  234.           p_image->p_enc->fmt_out.video.i_width != p_fmt_out->i_width ||
  235.           p_image->p_enc->fmt_out.video.i_height != p_fmt_out->i_height ) )
  236.     {
  237.         DeleteEncoder( p_image->p_enc );
  238.         p_image->p_enc = 0;
  239.     }
  240.     /* Start an encoder */
  241.     if( !p_image->p_enc )
  242.     {
  243.         p_image->p_enc = CreateEncoder( p_image->p_parent,
  244.                                         p_fmt_in, p_fmt_out );
  245.         if( !p_image->p_enc ) return NULL;
  246.     }
  247.     /* Check if we need chroma conversion or resizing */
  248.     if( p_image->p_enc->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
  249.         p_image->p_enc->fmt_in.video.i_width != p_fmt_in->i_width ||
  250.         p_image->p_enc->fmt_in.video.i_height != p_fmt_in->i_height )
  251.     {
  252.         picture_t *p_tmp_pic;
  253.         if( p_image->p_filter )
  254.         if( p_image->p_filter->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
  255.             p_image->p_filter->fmt_out.video.i_chroma !=
  256.             p_image->p_enc->fmt_in.video.i_chroma )
  257.         {
  258.             /* We need to restart a new filter */
  259.             DeleteFilter( p_image->p_filter );
  260.             p_image->p_filter = 0;
  261.         }
  262.         /* Start a filter */
  263.         if( !p_image->p_filter )
  264.         {
  265.             es_format_t fmt_in;
  266.             es_format_Init( &fmt_in, VIDEO_ES, p_fmt_in->i_chroma );
  267.             fmt_in.video = *p_fmt_in;
  268.             p_image->p_filter =
  269.                 CreateFilter( p_image->p_parent, &fmt_in,
  270.                               &p_image->p_enc->fmt_in.video, NULL );
  271.             if( !p_image->p_filter )
  272.             {
  273.                 return NULL;
  274.             }
  275.         }
  276.         else
  277.         {
  278.             /* Filters should handle on-the-fly size changes */
  279.             p_image->p_filter->fmt_in.i_codec = p_fmt_in->i_chroma;
  280.             p_image->p_filter->fmt_out.video = *p_fmt_in;
  281.             p_image->p_filter->fmt_out.i_codec =p_image->p_enc->fmt_in.i_codec;
  282.             p_image->p_filter->fmt_out.video = p_image->p_enc->fmt_in.video;
  283.         }
  284.         picture_Hold( p_pic );
  285.         p_tmp_pic =
  286.             p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
  287.         p_block = p_image->p_enc->pf_encode_video( p_image->p_enc, p_tmp_pic );
  288.         p_image->p_filter->pf_vout_buffer_del( p_image->p_filter, p_tmp_pic );
  289.     }
  290.     else
  291.     {
  292.         p_block = p_image->p_enc->pf_encode_video( p_image->p_enc, p_pic );
  293.     }
  294.     if( !p_block )
  295.     {
  296.         msg_Dbg( p_image->p_parent, "no image encoded" );
  297.         return 0;
  298.     }
  299.     return p_block;
  300. }
  301. static int ImageWriteUrl( image_handler_t *p_image, picture_t *p_pic,
  302.                           video_format_t *p_fmt_in, video_format_t *p_fmt_out,
  303.                           const char *psz_url )
  304. {
  305.     block_t *p_block;
  306.     FILE *file;
  307.     if( !p_fmt_out->i_chroma )
  308.     {
  309.         /* Try to guess format from file name */
  310.         p_fmt_out->i_chroma = image_Ext2Fourcc( psz_url );
  311.     }
  312.     file = utf8_fopen( psz_url, "wb" );
  313.     if( !file )
  314.     {
  315.         msg_Err( p_image->p_parent, "%s: %m", psz_url );
  316.         return VLC_EGENERIC;
  317.     }
  318.     p_block = ImageWrite( p_image, p_pic, p_fmt_in, p_fmt_out );
  319.     int err = 0;
  320.     if( p_block )
  321.     {
  322.         if( fwrite( p_block->p_buffer, p_block->i_buffer, 1, file ) != 1 )
  323.             err = errno;
  324.         block_Release( p_block );
  325.     }
  326.     if( fclose( file ) && !err )
  327.         err = errno;
  328.     if( err )
  329.     {
  330.        errno = err;
  331.        msg_Err( p_image->p_parent, "%s: %m", psz_url );
  332.     }
  333.     return err ? VLC_EGENERIC : VLC_SUCCESS;
  334. }
  335. /**
  336.  * Convert an image to a different format
  337.  *
  338.  */
  339. static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
  340.                                 video_format_t *p_fmt_in,
  341.                                 video_format_t *p_fmt_out )
  342. {
  343.     picture_t *p_pif;
  344.     if( !p_fmt_out->i_width && !p_fmt_out->i_height &&
  345.         p_fmt_out->i_sar_num && p_fmt_out->i_sar_den &&
  346.         p_fmt_out->i_sar_num * p_fmt_in->i_sar_den !=
  347.         p_fmt_out->i_sar_den * p_fmt_in->i_sar_num )
  348.     {
  349.         p_fmt_out->i_width =
  350.             p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
  351.             p_fmt_in->i_width / p_fmt_in->i_sar_den / p_fmt_out->i_sar_num;
  352.         p_fmt_out->i_visible_width =
  353.             p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
  354.             p_fmt_in->i_visible_width / p_fmt_in->i_sar_den /
  355.             p_fmt_out->i_sar_num;
  356.     }
  357.     if( !p_fmt_out->i_chroma ) p_fmt_out->i_chroma = p_fmt_in->i_chroma;
  358.     if( !p_fmt_out->i_width )
  359.         p_fmt_out->i_width = p_fmt_out->i_visible_width = p_fmt_in->i_width;
  360.     if( !p_fmt_out->i_height )
  361.         p_fmt_out->i_height = p_fmt_out->i_visible_height = p_fmt_in->i_height;
  362.     if( !p_fmt_out->i_sar_num ) p_fmt_out->i_sar_num = p_fmt_in->i_sar_num;
  363.     if( !p_fmt_out->i_sar_den ) p_fmt_out->i_sar_den = p_fmt_in->i_sar_den;
  364.     if( !p_fmt_out->i_aspect ) p_fmt_out->i_aspect = p_fmt_in->i_aspect;
  365.     if( p_image->p_filter )
  366.     if( p_image->p_filter->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
  367.         p_image->p_filter->fmt_out.video.i_chroma != p_fmt_out->i_chroma )
  368.     {
  369.         /* We need to restart a new filter */
  370.         DeleteFilter( p_image->p_filter );
  371.         p_image->p_filter = NULL;
  372.     }
  373.     /* Start a filter */
  374.     if( !p_image->p_filter )
  375.     {
  376.         es_format_t fmt_in;
  377.         es_format_Init( &fmt_in, VIDEO_ES, p_fmt_in->i_chroma );
  378.         fmt_in.video = *p_fmt_in;
  379.         p_image->p_filter =
  380.             CreateFilter( p_image->p_parent, &fmt_in, p_fmt_out, NULL );
  381.         if( !p_image->p_filter )
  382.         {
  383.             return NULL;
  384.         }
  385.     }
  386.     else
  387.     {
  388.         /* Filters should handle on-the-fly size changes */
  389.         p_image->p_filter->fmt_in.video = *p_fmt_in;
  390.         p_image->p_filter->fmt_out.video = *p_fmt_out;
  391.     }
  392.     picture_Hold( p_pic );
  393.     p_pif = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
  394.     if( p_fmt_in->i_chroma == p_fmt_out->i_chroma &&
  395.         p_fmt_in->i_width == p_fmt_out->i_width &&
  396.         p_fmt_in->i_height == p_fmt_out->i_height )
  397.     {
  398.         /* Duplicate image */
  399.         picture_Release( p_pif ); /* XXX: Better fix must be possible */
  400.         p_pif = p_image->p_filter->pf_vout_buffer_new( p_image->p_filter );
  401.         if( p_pif )
  402.             picture_Copy( p_pif, p_pic );
  403.     }
  404.     return p_pif;
  405. }
  406. /**
  407.  * Filter an image with a psz_module filter
  408.  *
  409.  */
  410. static picture_t *ImageFilter( image_handler_t *p_image, picture_t *p_pic,
  411.                                video_format_t *p_fmt, const char *psz_module )
  412. {
  413.     /* Start a filter */
  414.     if( !p_image->p_filter )
  415.     {
  416.         es_format_t fmt;
  417.         es_format_Init( &fmt, VIDEO_ES, p_fmt->i_chroma );
  418.         fmt.video = *p_fmt;
  419.         p_image->p_filter =
  420.             CreateFilter( p_image->p_parent, &fmt, &fmt.video, psz_module );
  421.         if( !p_image->p_filter )
  422.         {
  423.             return NULL;
  424.         }
  425.     }
  426.     else
  427.     {
  428.         /* Filters should handle on-the-fly size changes */
  429.         p_image->p_filter->fmt_in.video = *p_fmt;
  430.         p_image->p_filter->fmt_out.video = *p_fmt;
  431.     }
  432.     picture_Hold( p_pic );
  433.     return p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
  434. }
  435. /**
  436.  * Misc functions
  437.  *
  438.  */
  439. static const struct
  440. {
  441.     vlc_fourcc_t i_codec;
  442.     const char *psz_ext;
  443. } ext_table[] =
  444. {
  445.     { VLC_FOURCC('j','p','e','g'), "jpeg" },
  446.     { VLC_FOURCC('j','p','e','g'), "jpg"  },
  447.     { VLC_FOURCC('l','j','p','g'), "ljpg" },
  448.     { VLC_FOURCC('p','n','g',' '), "png" },
  449.     { VLC_FOURCC('p','g','m',' '), "pgm" },
  450.     { VLC_FOURCC('p','g','m','y'), "pgmyuv" },
  451.     { VLC_FOURCC('p','b','m',' '), "pbm" },
  452.     { VLC_FOURCC('p','a','m',' '), "pam" },
  453.     { VLC_FOURCC('t','g','a',' '), "tga" },
  454.     { VLC_FOURCC('b','m','p',' '), "bmp" },
  455.     { VLC_FOURCC('p','n','m',' '), "pnm" },
  456.     { VLC_FOURCC('x','p','m',' '), "xpm" },
  457.     { VLC_FOURCC('x','c','f',' '), "xcf" },
  458.     { VLC_FOURCC('p','c','x',' '), "pcx" },
  459.     { VLC_FOURCC('g','i','f',' '), "gif" },
  460.     { VLC_FOURCC('t','i','f','f'), "tif" },
  461.     { VLC_FOURCC('t','i','f','f'), "tiff" },
  462.     { VLC_FOURCC('l','b','m',' '), "lbm" },
  463.     { 0, NULL }
  464. };
  465. vlc_fourcc_t image_Type2Fourcc( const char *psz_type )
  466. {
  467.     int i;
  468.     for( i = 0; ext_table[i].i_codec; i++ )
  469.         if( !strcasecmp( ext_table[i].psz_ext, psz_type ) )
  470.             return ext_table[i].i_codec;
  471.     return 0;
  472. }
  473. vlc_fourcc_t image_Ext2Fourcc( const char *psz_name )
  474. {
  475.     psz_name = strrchr( psz_name, '.' );
  476.     if( !psz_name ) return 0;
  477.     psz_name++;
  478.     return image_Type2Fourcc( psz_name );
  479. }
  480. /*
  481. static const char *Fourcc2Ext( vlc_fourcc_t i_codec )
  482. {
  483.     int i;
  484.     for( i = 0; ext_table[i].i_codec != 0; i++ )
  485.     {
  486.         if( ext_table[i].i_codec == i_codec ) return ext_table[i].psz_ext;
  487.     }
  488.     return NULL;
  489. }
  490. */
  491. static const struct
  492. {
  493.     vlc_fourcc_t i_codec;
  494.     const char *psz_mime;
  495. } mime_table[] =
  496. {
  497.     { VLC_FOURCC('b','m','p',' '), "image/bmp" },
  498.     { VLC_FOURCC('b','m','p',' '), "image/x-bmp" },
  499.     { VLC_FOURCC('b','m','p',' '), "image/x-bitmap" },
  500.     { VLC_FOURCC('b','m','p',' '), "image/x-ms-bmp" },
  501.     { VLC_FOURCC('p','n','m',' '), "image/x-portable-anymap" },
  502.     { VLC_FOURCC('p','n','m',' '), "image/x-portable-bitmap" },
  503.     { VLC_FOURCC('p','n','m',' '), "image/x-portable-graymap" },
  504.     { VLC_FOURCC('p','n','m',' '), "image/x-portable-pixmap" },
  505.     { VLC_FOURCC('g','i','f',' '), "image/gif" },
  506.     { VLC_FOURCC('j','p','e','g'), "image/jpeg" },
  507.     { VLC_FOURCC('p','c','x',' '), "image/pcx" },
  508.     { VLC_FOURCC('p','n','g',' '), "image/png" },
  509.     { VLC_FOURCC('t','i','f','f'), "image/tiff" },
  510.     { VLC_FOURCC('t','g','a',' '), "iamge/x-tga" },
  511.     { VLC_FOURCC('x','p','m',' '), "image/x-xpixmap" },
  512.     { 0, NULL }
  513. };
  514. vlc_fourcc_t image_Mime2Fourcc( const char *psz_mime )
  515. {
  516.     int i;
  517.     for( i = 0; mime_table[i].i_codec; i++ )
  518.         if( !strcmp( psz_mime, mime_table[i].psz_mime ) )
  519.             return mime_table[i].i_codec;
  520.     return 0;
  521. }
  522. static picture_t *video_new_buffer( decoder_t *p_dec )
  523. {
  524.     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
  525.     return picture_New( p_dec->fmt_out.video.i_chroma,
  526.                         p_dec->fmt_out.video.i_width,
  527.                         p_dec->fmt_out.video.i_height,
  528.                         p_dec->fmt_out.video.i_aspect );
  529. }
  530. static void video_del_buffer( decoder_t *p_dec, picture_t *p_pic )
  531. {
  532.     if( p_pic->i_refcount != 1 )
  533.         msg_Err( p_dec, "invalid picture reference count" );
  534.     p_pic->i_refcount = 0;
  535.     picture_Delete( p_pic );
  536. }
  537. static void video_link_picture( decoder_t *p_dec, picture_t *p_pic )
  538. {
  539.     (void)p_dec;
  540.     picture_Hold( p_pic );
  541. }
  542. static void video_unlink_picture( decoder_t *p_dec, picture_t *p_pic )
  543. {
  544.     (void)p_dec;
  545.     picture_Release( p_pic );
  546. }
  547. static decoder_t *CreateDecoder( vlc_object_t *p_this, video_format_t *fmt )
  548. {
  549.     decoder_t *p_dec;
  550.     p_dec = vlc_object_create( p_this, VLC_OBJECT_DECODER );
  551.     if( p_dec == NULL )
  552.         return NULL;
  553.     p_dec->p_module = NULL;
  554.     es_format_Init( &p_dec->fmt_in, VIDEO_ES, fmt->i_chroma );
  555.     es_format_Init( &p_dec->fmt_out, VIDEO_ES, 0 );
  556.     p_dec->fmt_in.video = *fmt;
  557.     p_dec->b_pace_control = true;
  558.     p_dec->pf_vout_buffer_new = video_new_buffer;
  559.     p_dec->pf_vout_buffer_del = video_del_buffer;
  560.     p_dec->pf_picture_link    = video_link_picture;
  561.     p_dec->pf_picture_unlink  = video_unlink_picture;
  562.     vlc_object_attach( p_dec, p_this );
  563.     /* Find a suitable decoder module */
  564.     p_dec->p_module = module_need( p_dec, "decoder", "$codec", false );
  565.     if( !p_dec->p_module )
  566.     {
  567.         msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.n"
  568.                  "VLC probably does not support this image format.",
  569.                  (char*)&p_dec->fmt_in.i_codec );
  570.         DeleteDecoder( p_dec );
  571.         return NULL;
  572.     }
  573.     return p_dec;
  574. }
  575. static void DeleteDecoder( decoder_t * p_dec )
  576. {
  577.     vlc_object_detach( p_dec );
  578.     if( p_dec->p_module ) module_unneed( p_dec, p_dec->p_module );
  579.     es_format_Clean( &p_dec->fmt_in );
  580.     es_format_Clean( &p_dec->fmt_out );
  581.     if( p_dec->p_description )
  582.         vlc_meta_Delete( p_dec->p_description );
  583.     vlc_object_release( p_dec );
  584.     p_dec = NULL;
  585. }
  586. static encoder_t *CreateEncoder( vlc_object_t *p_this, video_format_t *fmt_in,
  587.                                  video_format_t *fmt_out )
  588. {
  589.     encoder_t *p_enc;
  590.     p_enc = sout_EncoderCreate( p_this );
  591.     if( p_enc == NULL )
  592.         return NULL;
  593.     p_enc->p_module = NULL;
  594.     es_format_Init( &p_enc->fmt_in, VIDEO_ES, fmt_in->i_chroma );
  595.     p_enc->fmt_in.video = *fmt_in;
  596.     if( fmt_out->i_width > 0 && fmt_out->i_height > 0 )
  597.     {
  598.         p_enc->fmt_in.video.i_width = fmt_out->i_width;
  599.         p_enc->fmt_in.video.i_height = fmt_out->i_height;
  600.         if( fmt_out->i_visible_width > 0 &&
  601.             fmt_out->i_visible_height > 0 )
  602.         {
  603.             p_enc->fmt_in.video.i_visible_width = fmt_out->i_visible_width;
  604.             p_enc->fmt_in.video.i_visible_height = fmt_out->i_visible_height;
  605.         }
  606.         else
  607.         {
  608.             p_enc->fmt_in.video.i_visible_width = fmt_out->i_width;
  609.             p_enc->fmt_in.video.i_visible_height = fmt_out->i_height;
  610.         }
  611.     }
  612.     else if( fmt_out->i_sar_num && fmt_out->i_sar_den &&
  613.              fmt_out->i_sar_num * fmt_in->i_sar_den !=
  614.              fmt_out->i_sar_den * fmt_in->i_sar_num )
  615.     {
  616.         p_enc->fmt_in.video.i_width =
  617.             fmt_in->i_sar_num * (int64_t)fmt_out->i_sar_den * fmt_in->i_width /
  618.             fmt_in->i_sar_den / fmt_out->i_sar_num;
  619.         p_enc->fmt_in.video.i_visible_width =
  620.             fmt_in->i_sar_num * (int64_t)fmt_out->i_sar_den *
  621.             fmt_in->i_visible_width / fmt_in->i_sar_den / fmt_out->i_sar_num;
  622.     }
  623.     p_enc->fmt_in.video.i_frame_rate = 25;
  624.     p_enc->fmt_in.video.i_frame_rate_base = 1;
  625.     es_format_Init( &p_enc->fmt_out, VIDEO_ES, fmt_out->i_chroma );
  626.     p_enc->fmt_out.video = *fmt_out;
  627.     p_enc->fmt_out.video.i_width = p_enc->fmt_in.video.i_width;
  628.     p_enc->fmt_out.video.i_height = p_enc->fmt_in.video.i_height;
  629.     vlc_object_attach( p_enc, p_this );
  630.     /* Find a suitable decoder module */
  631.     p_enc->p_module = module_need( p_enc, "encoder", NULL, false );
  632.     if( !p_enc->p_module )
  633.     {
  634.         msg_Err( p_enc, "no suitable encoder module for fourcc `%4.4s'.n"
  635.                  "VLC probably does not support this image format.",
  636.                  (char*)&p_enc->fmt_out.i_codec );
  637.         DeleteEncoder( p_enc );
  638.         return NULL;
  639.     }
  640.     p_enc->fmt_in.video.i_chroma = p_enc->fmt_in.i_codec;
  641.     return p_enc;
  642. }
  643. static void DeleteEncoder( encoder_t * p_enc )
  644. {
  645.     vlc_object_detach( p_enc );
  646.     if( p_enc->p_module ) module_unneed( p_enc, p_enc->p_module );
  647.     es_format_Clean( &p_enc->fmt_in );
  648.     es_format_Clean( &p_enc->fmt_out );
  649.     vlc_object_release( p_enc );
  650.     p_enc = NULL;
  651. }
  652. static filter_t *CreateFilter( vlc_object_t *p_this, es_format_t *p_fmt_in,
  653.                                video_format_t *p_fmt_out,
  654.                                const char *psz_module )
  655. {
  656.     static const char typename[] = "filter";
  657.     filter_t *p_filter;
  658.     p_filter = vlc_custom_create( p_this, sizeof(filter_t),
  659.                                   VLC_OBJECT_GENERIC, typename );
  660.     vlc_object_attach( p_filter, p_this );
  661.     p_filter->pf_vout_buffer_new =
  662.         (picture_t *(*)(filter_t *))video_new_buffer;
  663.     p_filter->pf_vout_buffer_del =
  664.         (void (*)(filter_t *, picture_t *))video_del_buffer;
  665.     p_filter->fmt_in = *p_fmt_in;
  666.     p_filter->fmt_out = *p_fmt_in;
  667.     p_filter->fmt_out.i_codec = p_fmt_out->i_chroma;
  668.     p_filter->fmt_out.video = *p_fmt_out;
  669.     p_filter->p_module = module_need( p_filter, "video filter2",
  670.                                       psz_module, false );
  671.     if( !p_filter->p_module )
  672.     {
  673.         msg_Dbg( p_filter, "no video filter found" );
  674.         DeleteFilter( p_filter );
  675.         return NULL;
  676.     }
  677.     return p_filter;
  678. }
  679. static void DeleteFilter( filter_t * p_filter )
  680. {
  681.     vlc_object_detach( p_filter );
  682.     if( p_filter->p_module ) module_unneed( p_filter, p_filter->p_module );
  683.     es_format_Clean( &p_filter->fmt_in );
  684.     es_format_Clean( &p_filter->fmt_out );
  685.     vlc_object_release( p_filter );
  686. }