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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * fake.c: decoder reading from a fake stream, outputting a fixed image
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  * $Id: 773dd9242a70e5d8c1ffdb7012d97c6c7b78486c $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *          Jean-Paul Saman <jpsaman at m2x dot nl>
  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_codec.h>
  33. #include <vlc_image.h>
  34. #include <vlc_filter.h>
  35. #include <vlc_charset.h>
  36. /*****************************************************************************
  37.  * Local prototypes
  38.  *****************************************************************************/
  39. static int  OpenDecoder   ( vlc_object_t * );
  40. static void CloseDecoder  ( vlc_object_t * );
  41. static picture_t *DecodeBlock  ( decoder_t *, block_t ** );
  42. static int FakeCallback( vlc_object_t *, char const *,
  43.                          vlc_value_t, vlc_value_t, void * );
  44. /*****************************************************************************
  45.  * Module descriptor
  46.  *****************************************************************************/
  47. #define FILE_TEXT N_("Image file")
  48. #define FILE_LONGTEXT N_( 
  49.     "Path of the image file for fake input." )
  50. #define RELOAD_TEXT N_("Reload image file")
  51. #define RELOAD_LONGTEXT N_( 
  52.     "Reload image file every n seconds." )
  53. #define WIDTH_TEXT N_("Video width")
  54. #define WIDTH_LONGTEXT N_( 
  55.     "Output video width." )
  56. #define HEIGHT_TEXT N_("Video height")
  57. #define HEIGHT_LONGTEXT N_( 
  58.     "Output video height." )
  59. #define KEEP_AR_TEXT N_("Keep aspect ratio")
  60. #define KEEP_AR_LONGTEXT N_( 
  61.     "Consider width and height as maximum values." )
  62. #define ASPECT_RATIO_TEXT N_("Background aspect ratio")
  63. #define ASPECT_RATIO_LONGTEXT N_( 
  64.     "Aspect ratio of the image file (4:3, 16:9). Default is square pixels." )
  65. #define DEINTERLACE_TEXT N_("Deinterlace video")
  66. #define DEINTERLACE_LONGTEXT N_( 
  67.     "Deinterlace the image after loading it." )
  68. #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
  69. #define DEINTERLACE_MODULE_LONGTEXT N_( 
  70.     "Deinterlace module to use." )
  71. #define CHROMA_TEXT N_("Chroma used.")
  72. #define CHROMA_LONGTEXT N_( 
  73.     "Force use of a specific chroma for output. Default is I420." )
  74. static const char *const ppsz_deinterlace_type[] =
  75. {
  76.     "deinterlace", "ffmpeg-deinterlace"
  77. };
  78. vlc_module_begin ()
  79.     set_category( CAT_INPUT )
  80.     set_subcategory( SUBCAT_INPUT_VCODEC )
  81.     set_shortname( N_("Fake") )
  82.     set_description( N_("Fake video decoder") )
  83.     set_capability( "decoder", 1000 )
  84.     set_callbacks( OpenDecoder, CloseDecoder )
  85.     add_shortcut( "fake" )
  86.     add_file( "fake-file", "", NULL, FILE_TEXT,
  87.                 FILE_LONGTEXT, false )
  88.     add_integer( "fake-file-reload", 0, NULL, RELOAD_TEXT,
  89.                 RELOAD_LONGTEXT, false )
  90.     add_integer( "fake-width", 0, NULL, WIDTH_TEXT,
  91.                  WIDTH_LONGTEXT, true )
  92.     add_integer( "fake-height", 0, NULL, HEIGHT_TEXT,
  93.                  HEIGHT_LONGTEXT, true )
  94.     add_bool( "fake-keep-ar", 0, NULL, KEEP_AR_TEXT, KEEP_AR_LONGTEXT,
  95.               true )
  96.     add_string( "fake-aspect-ratio", "", NULL,
  97.                 ASPECT_RATIO_TEXT, ASPECT_RATIO_LONGTEXT, true )
  98.     add_bool( "fake-deinterlace", 0, NULL, DEINTERLACE_TEXT,
  99.               DEINTERLACE_LONGTEXT, false )
  100.     add_string( "fake-deinterlace-module", "deinterlace", NULL,
  101.                 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
  102.                 false )
  103.         change_string_list( ppsz_deinterlace_type, 0, 0 )
  104.     add_string( "fake-chroma", "I420", NULL, CHROMA_TEXT, CHROMA_LONGTEXT,
  105.                 true )
  106. vlc_module_end ()
  107. struct decoder_sys_t
  108. {
  109.     picture_t *p_image;
  110.     vlc_mutex_t lock;
  111.     bool  b_reload;
  112.     mtime_t     i_reload;
  113.     mtime_t     i_next;
  114. };
  115. /*****************************************************************************
  116.  * OpenDecoder: probe the decoder and return score
  117.  *****************************************************************************/
  118. static int OpenDecoder( vlc_object_t *p_this )
  119. {
  120.     decoder_t *p_dec = (decoder_t*)p_this;
  121.     vlc_value_t val;
  122.     image_handler_t *p_handler;
  123.     video_format_t fmt_in, fmt_out;
  124.     picture_t *p_image;
  125.     char *psz_file, *psz_chroma;
  126.     bool b_keep_ar;
  127.     int i_aspect = 0;
  128.     if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','a','k','e') )
  129.     {
  130.         return VLC_EGENERIC;
  131.     }
  132.     p_dec->p_sys = calloc( 1, sizeof( *p_dec->p_sys ) );
  133.     if( !p_dec->p_sys )
  134.         return VLC_ENOMEM;
  135.     psz_file = var_CreateGetNonEmptyStringCommand( p_dec, "fake-file" );
  136.     if( !psz_file )
  137.     {
  138.         msg_Err( p_dec, "specify a file with --fake-file=..." );
  139.         free( p_dec->p_sys );
  140.         return VLC_EGENERIC;
  141.     }
  142.     memset( &fmt_in, 0, sizeof(fmt_in) );
  143.     memset( &fmt_out, 0, sizeof(fmt_out) );
  144.     val.i_int = var_CreateGetIntegerCommand( p_dec, "fake-file-reload" );
  145.     if( val.i_int > 0)
  146.     {
  147.         p_dec->p_sys->b_reload = true;
  148.         p_dec->p_sys->i_reload = (mtime_t)(val.i_int * 1000000);
  149.         p_dec->p_sys->i_next   = (mtime_t)(p_dec->p_sys->i_reload + mdate());
  150.     }
  151.     psz_chroma = var_CreateGetString( p_dec, "fake-chroma" );
  152.     if( strlen( psz_chroma ) != 4 )
  153.     {
  154.         msg_Warn( p_dec, "Invalid chroma (%s). Using I420.", psz_chroma );
  155.         fmt_out.i_chroma = VLC_FOURCC('I','4','2','0');
  156.     }
  157.     else
  158.     {
  159.         fmt_out.i_chroma = VLC_FOURCC( psz_chroma[0],
  160.                                        psz_chroma[1],
  161.                                        psz_chroma[2],
  162.                                        psz_chroma[3] );
  163.     }
  164.     free( psz_chroma );
  165.     var_Create( p_dec, "fake-keep-ar", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  166.     var_Get( p_dec, "fake-keep-ar", &val );
  167.     b_keep_ar = val.b_bool;
  168.     var_Create( p_dec, "fake-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  169.     var_Create( p_dec, "fake-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  170.     var_Create( p_dec, "fake-aspect-ratio",
  171.                 VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  172.     var_Get( p_dec, "fake-aspect-ratio", &val );
  173.     if ( val.psz_string )
  174.     {
  175.         char *psz_parser = strchr( val.psz_string, ':' );
  176.         if( psz_parser )
  177.         {
  178.             *psz_parser++ = '';
  179.             i_aspect = atoi( val.psz_string )
  180.                                    * VOUT_ASPECT_FACTOR / atoi( psz_parser );
  181.         }
  182.         free( val.psz_string );
  183.     }
  184.     if ( !b_keep_ar )
  185.     {
  186.         var_Get( p_dec, "fake-width", &val );
  187.         fmt_out.i_width = val.i_int;
  188.         var_Get( p_dec, "fake-height", &val );
  189.         fmt_out.i_height = val.i_int;
  190.     }
  191.     p_handler = image_HandlerCreate( p_dec );
  192.     p_image = image_ReadUrl( p_handler, psz_file, &fmt_in, &fmt_out );
  193.     image_HandlerDelete( p_handler );
  194.     if ( p_image == NULL )
  195.     {
  196.         msg_Err( p_dec, "unable to read image file %s", psz_file );
  197.         free( psz_file );
  198.         free( p_dec->p_sys );
  199.         return VLC_EGENERIC;
  200.     }
  201.     msg_Dbg( p_dec, "file %s loaded successfully", psz_file );
  202.     free( psz_file );
  203.     if ( b_keep_ar )
  204.     {
  205.         picture_t *p_old = p_image;
  206.         int i_width, i_height;
  207.         var_Get( p_dec, "fake-width", &val );
  208.         i_width = val.i_int;
  209.         var_Get( p_dec, "fake-height", &val );
  210.         i_height = val.i_int;
  211.         if ( i_width && i_height )
  212.         {
  213.             int i_image_ar = fmt_out.i_width * VOUT_ASPECT_FACTOR
  214.                               / fmt_out.i_height;
  215.             int i_region_ar = i_width * VOUT_ASPECT_FACTOR / i_height;
  216.             fmt_in = fmt_out;
  217.             if ( i_aspect == i_image_ar )
  218.             {
  219.                 fmt_out.i_width = i_width;
  220.                 fmt_out.i_height = i_height;
  221.             }
  222.             else if ( i_image_ar > i_region_ar )
  223.             {
  224.                 fmt_out.i_width = i_width;
  225.                 fmt_out.i_height = i_width * VOUT_ASPECT_FACTOR
  226.                                     / i_image_ar;
  227.                 i_aspect = i_image_ar;
  228.             }
  229.             else
  230.             {
  231.                 fmt_out.i_height = i_height;
  232.                 fmt_out.i_width = i_height * i_image_ar
  233.                                     / VOUT_ASPECT_FACTOR;
  234.                 i_aspect = i_image_ar;
  235.             }
  236.             p_handler = image_HandlerCreate( p_dec );
  237.             p_image = image_Convert( p_handler, p_old, &fmt_in, &fmt_out );
  238.             image_HandlerDelete( p_handler );
  239.             if ( p_image == NULL )
  240.             {
  241.                 msg_Warn( p_dec, "couldn't load resizing module" );
  242.                 p_image = p_old;
  243.                 fmt_out = fmt_in;
  244.             }
  245.             else
  246.             {
  247.                 picture_Release( p_old );
  248.             }
  249.         }
  250.     }
  251.     if ( i_aspect )
  252.     {
  253.         fmt_out.i_aspect = i_aspect;
  254.     }
  255.     else
  256.     {
  257.         fmt_out.i_aspect = fmt_out.i_width
  258.                             * VOUT_ASPECT_FACTOR / fmt_out.i_height;
  259.     }
  260.     var_Create( p_dec, "fake-deinterlace", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  261.     var_Get( p_dec, "fake-deinterlace", &val );
  262.     if ( val.b_bool )
  263.     {
  264.         picture_t *p_old = p_image;
  265.         var_Create( p_dec, "fake-deinterlace-module",
  266.                     VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  267.         var_Get( p_dec, "fake-deinterlace-module", &val );
  268.         p_handler = image_HandlerCreate( p_dec );
  269.         p_image = image_Filter( p_handler, p_old, &fmt_out, val.psz_string );
  270.         image_HandlerDelete( p_handler );
  271.         free( val.psz_string );
  272.         if ( p_image == NULL )
  273.         {
  274.             msg_Warn( p_dec, "couldn't load deinterlace module" );
  275.             p_image = p_old;
  276.         }
  277.         else
  278.         {
  279.             picture_Release( p_old );
  280.         }
  281.     }
  282.     /* Set output properties */
  283.     p_dec->fmt_out.i_cat = VIDEO_ES;
  284.     p_dec->fmt_out.i_codec = fmt_out.i_chroma;
  285.     p_dec->fmt_out.video = fmt_out;
  286.     /* Set callbacks */
  287.     p_dec->pf_decode_video = DecodeBlock;
  288.     p_dec->p_sys->p_image = p_image;
  289.     vlc_mutex_init( &p_dec->p_sys->lock );
  290.     /* Add the callback when every variables are available */
  291.     var_AddCallback( p_dec, "fake-file", FakeCallback, p_dec );
  292.     var_AddCallback( p_dec, "fake-file-reload", FakeCallback , p_dec );
  293.     return VLC_SUCCESS;
  294. }
  295. /****************************************************************************
  296.  * DecodeBlock: the whole thing
  297.  ****************************************************************************/
  298. static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
  299. {
  300.     decoder_sys_t *p_sys = (decoder_sys_t*) p_dec->p_sys;
  301.     picture_t *p_pic;
  302.     if( pp_block == NULL || !*pp_block ) return NULL;
  303.     p_pic = decoder_NewPicture( p_dec );
  304.     if( p_pic == NULL )
  305.     {
  306.         msg_Err( p_dec, "cannot get picture" );
  307.         goto error;
  308.     }
  309.     if( p_sys->b_reload && (mdate() >= p_sys->i_next) )
  310.     {
  311.         var_TriggerCallback( p_dec, "fake-file" );
  312.         /* next period */
  313.         p_sys->i_next = (mtime_t)(p_sys->i_reload + mdate());
  314.     }
  315.     vlc_mutex_lock( &p_dec->p_sys->lock );
  316.     picture_Copy( p_pic, p_dec->p_sys->p_image );
  317.     vlc_mutex_unlock( &p_dec->p_sys->lock );
  318.     p_pic->date = (*pp_block)->i_pts;
  319. error:
  320.     block_Release( *pp_block );
  321.     *pp_block = NULL;
  322.     return p_pic;
  323. }
  324. /*****************************************************************************
  325.  * CloseDecoder: fake decoder destruction
  326.  *****************************************************************************/
  327. static void CloseDecoder( vlc_object_t *p_this )
  328. {
  329.     decoder_t *p_dec = (decoder_t *)p_this;
  330.     picture_t *p_image = p_dec->p_sys->p_image;
  331.     var_DelCallback( p_dec, "fake-file", FakeCallback, p_dec );
  332.     var_DelCallback( p_dec, "fake-file-reload", FakeCallback , p_dec );
  333.     if( p_image != NULL )
  334.         picture_Release( p_image );
  335.     vlc_mutex_destroy( &p_dec->p_sys->lock );
  336.     free( p_dec->p_sys );
  337. }
  338. /*****************************************************************************
  339.  * FakeCallback: Image source change callback.
  340.  *****************************************************************************/
  341. static int FakeCallback( vlc_object_t *p_this, char const *psz_var,
  342.                          vlc_value_t oldval, vlc_value_t newval,
  343.                          void *p_data )
  344. {
  345.     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
  346.     decoder_t *p_dec = (decoder_t *)p_data;
  347.     if( !strcmp( psz_var, "fake-file" ) )
  348.     {
  349.         image_handler_t *p_handler;
  350.         picture_t *p_new_image;
  351.         video_format_t fmt_in, fmt_out;
  352.         char *psz_file = newval.psz_string;
  353.         picture_t *p_image;
  354.         vlc_mutex_lock( &p_dec->p_sys->lock );
  355.         p_image = p_dec->p_sys->p_image;
  356.         if( !psz_file || !*psz_file )
  357.         {
  358.             msg_Err( p_dec, "fake-file value must be non empty." );
  359.             vlc_mutex_unlock( &p_dec->p_sys->lock );
  360.             return VLC_EGENERIC;
  361.         }
  362.         msg_Dbg( p_dec, "Changing fake-file to %s.", psz_file );
  363.         memset( &fmt_in, 0, sizeof(fmt_in) );
  364.         fmt_out = p_dec->fmt_out.video;
  365.         p_handler = image_HandlerCreate( p_dec );
  366.         p_new_image = image_ReadUrl( p_handler, psz_file, &fmt_in, &fmt_out );
  367.         image_HandlerDelete( p_handler );
  368.         if( !p_new_image )
  369.         {
  370.             msg_Err( p_dec, "error while reading image (%s)", psz_file );
  371.             vlc_mutex_unlock( &p_dec->p_sys->lock );
  372.             return VLC_EGENERIC;
  373.         }
  374.         p_dec->p_sys->p_image = p_new_image;
  375.         picture_Release( p_image );
  376.         vlc_mutex_unlock( &p_dec->p_sys->lock );
  377.     }
  378.     else if( !strcmp( psz_var, "fake-file-reload" ) )
  379.     {
  380.         if( newval.i_int > 0)
  381.         {
  382.             p_dec->p_sys->b_reload = true;
  383.             p_dec->p_sys->i_reload = (mtime_t)(newval.i_int * 1000000);
  384.             p_dec->p_sys->i_next   = (mtime_t)(p_dec->p_sys->i_reload + mdate());
  385.         }
  386.         else
  387.         {
  388.             p_dec->p_sys->b_reload = false;
  389.         }
  390.     }
  391.     return VLC_SUCCESS;
  392. }