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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * switcher.c: MPEG2 video switcher module
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: 9faf03eff2a2f97518feb9d561f1148c43da6558 $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  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.  * Preamble
  25.  *****************************************************************************/
  26. #include <math.h>
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_sout.h>
  33. #include <vlc_vout.h>
  34. #include <vlc_avcodec.h>
  35. #include <vlc_block.h>
  36. #include <vlc_charset.h>
  37. #include <vlc_network.h>
  38. #define HAVE_MMX
  39. #ifdef HAVE_LIBAVCODEC_AVCODEC_H
  40. #   include <libavcodec/avcodec.h>
  41. #elif defined(HAVE_FFMPEG_AVCODEC_H)
  42. #   include <ffmpeg/avcodec.h>
  43. #else
  44. #   include <avcodec.h>
  45. #endif
  46. #ifdef HAVE_POSTPROC_POSTPROCESS_H
  47. #   include <postproc/postprocess.h>
  48. #else
  49. #   include <libpostproc/postprocess.h>
  50. #endif
  51. #define SOUT_CFG_PREFIX "sout-switcher-"
  52. #define MAX_PICTURES 10
  53. #define MAX_AUDIO 30
  54. #define MAX_THRESHOLD 99999999
  55. /*****************************************************************************
  56.  * Local prototypes
  57.  *****************************************************************************/
  58. static int      Open    ( vlc_object_t * );
  59. static void     Close   ( vlc_object_t * );
  60. static sout_stream_id_t *Add( sout_stream_t *, es_format_t * );
  61. static int Del( sout_stream_t *, sout_stream_id_t * );
  62. static int Send( sout_stream_t *, sout_stream_id_t *, block_t * );
  63. static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id,
  64.                         mtime_t i_max_dts );
  65. static int UnpackFromFile( sout_stream_t *p_stream, const char *psz_file,
  66.                            int i_width, int i_height,
  67.                            picture_t *p_pic );
  68. static void NetCommand( sout_stream_t *p_stream );
  69. static mtime_t VideoCommand( sout_stream_t *p_stream, sout_stream_id_t *id );
  70. static block_t *VideoGetBuffer( sout_stream_t *p_stream, sout_stream_id_t *id,
  71.                                 block_t *p_buffer );
  72. static block_t *AudioGetBuffer( sout_stream_t *p_stream, sout_stream_id_t *id,
  73.                                 block_t *p_buffer );
  74. /*****************************************************************************
  75.  * Module descriptor
  76.  *****************************************************************************/
  77. #define FILES_TEXT N_("Files")
  78. #define FILES_LONGTEXT N_( 
  79.     "Full paths of the files separated by colons." )
  80. #define SIZES_TEXT N_("Sizes")
  81. #define SIZES_LONGTEXT N_( 
  82.     "List of sizes separated by colons (720x576:480x576)." )
  83. #define RATIO_TEXT N_("Aspect ratio")
  84. #define RATIO_LONGTEXT N_( 
  85.     "Aspect ratio (4:3, 16:9)." )
  86. #define PORT_TEXT N_("Command UDP port")
  87. #define PORT_LONGTEXT N_( 
  88.     "UDP port to listen to for commands." )
  89. #define COMMAND_TEXT N_("Command")
  90. #define COMMAND_LONGTEXT N_( 
  91.     "Initial command to execute." )
  92. #define GOP_TEXT N_("GOP size")
  93. #define GOP_LONGTEXT N_( 
  94.     "Number of P frames between two I frames." )
  95. #define QSCALE_TEXT N_("Quantizer scale")
  96. #define QSCALE_LONGTEXT N_( 
  97.     "Fixed quantizer scale to use." )
  98. #define AUDIO_TEXT N_("Mute audio")
  99. #define AUDIO_LONGTEXT N_( 
  100.     "Mute audio when command is not 0." )
  101. vlc_module_begin ()
  102.     set_description( N_("MPEG2 video switcher stream output") )
  103.     set_capability( "sout stream", 50 )
  104.     add_shortcut( "switcher" )
  105.     set_callbacks( Open, Close )
  106.     add_string( SOUT_CFG_PREFIX "files", "", NULL, FILES_TEXT,
  107.                 FILES_LONGTEXT, false )
  108.     add_string( SOUT_CFG_PREFIX "sizes", "", NULL, SIZES_TEXT,
  109.                 SIZES_LONGTEXT, false )
  110.     add_string( SOUT_CFG_PREFIX "aspect-ratio", "4:3", NULL, RATIO_TEXT,
  111.                 RATIO_LONGTEXT, false )
  112.     add_integer( SOUT_CFG_PREFIX "port", 5001, NULL,
  113.                  PORT_TEXT, PORT_LONGTEXT, true )
  114.     add_integer( SOUT_CFG_PREFIX "command", 0, NULL,
  115.                  COMMAND_TEXT, COMMAND_LONGTEXT, true )
  116.     add_integer( SOUT_CFG_PREFIX "gop", 8, NULL,
  117.                  GOP_TEXT, GOP_LONGTEXT, true )
  118.     add_integer( SOUT_CFG_PREFIX "qscale", 5, NULL,
  119.                  QSCALE_TEXT, QSCALE_LONGTEXT, true )
  120.     add_bool( SOUT_CFG_PREFIX "mute-audio", 1, NULL,
  121.               AUDIO_TEXT, AUDIO_LONGTEXT, true )
  122. vlc_module_end ()
  123. static const char *const ppsz_sout_options[] = {
  124.     "files", "sizes", "aspect-ratio", "port", "command", "gop", "qscale",
  125.     "mute-audio", NULL
  126. };
  127. struct sout_stream_sys_t
  128. {
  129.     sout_stream_t   *p_out;
  130.     int             i_gop;
  131.     int             i_qscale;
  132.     int             i_aspect;
  133.     sout_stream_id_t *pp_audio_ids[MAX_AUDIO];
  134.     bool      b_audio;
  135.     /* Pictures */
  136.     picture_t       p_pictures[MAX_PICTURES];
  137.     int             i_nb_pictures;
  138.     /* Command */
  139.     int             i_fd;
  140.     int             i_cmd, i_old_cmd;
  141. };
  142. struct sout_stream_id_t
  143. {
  144.     void            *id;
  145.     bool      b_switcher_video;
  146.     bool      b_switcher_audio;
  147.     es_format_t     f_src;
  148.     block_t         *p_queued;
  149.     /* ffmpeg part */
  150.     AVCodec         *ff_enc;
  151.     AVCodecContext  *ff_enc_c;
  152.     AVFrame         *p_frame;
  153.     uint8_t         *p_buffer_out;
  154.     int             i_nb_pred;
  155.     int16_t         *p_samples;
  156. };
  157. /*****************************************************************************
  158.  * Open:
  159.  *****************************************************************************/
  160. static int Open( vlc_object_t *p_this )
  161. {
  162.     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
  163.     sout_stream_sys_t *p_sys;
  164.     vlc_value_t       val;
  165.     char              *psz_files, *psz_sizes;
  166.     int               i_height = 0, i_width = 0;
  167.     p_sys = calloc( 1, sizeof(sout_stream_sys_t) );
  168.     if( !p_sys )
  169.         return VLC_ENOMEM;
  170.     p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );
  171.     if( !p_sys->p_out )
  172.     {
  173.         msg_Err( p_stream, "cannot create chain" );
  174.         free( p_sys );
  175.         return VLC_EGENERIC;
  176.     }
  177.     config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,
  178.                    p_stream->p_cfg );
  179.     var_Get( p_stream, SOUT_CFG_PREFIX "files", &val );
  180.     psz_files = val.psz_string;
  181.     var_Get( p_stream, SOUT_CFG_PREFIX "sizes", &val );
  182.     psz_sizes = val.psz_string;
  183.     p_sys->i_nb_pictures = 0;
  184.     while ( psz_files && *psz_files )
  185.     {
  186.         char * psz_file = psz_files;
  187.         char * psz_size = psz_sizes;
  188.         while ( *psz_files && *psz_files != ':' )
  189.             psz_files++;
  190.         if ( *psz_files == ':' )
  191.            *psz_files++ = '';
  192.         if ( *psz_sizes )
  193.         {
  194.             while ( *psz_sizes && *psz_sizes != ':' )
  195.                 psz_sizes++;
  196.             if ( *psz_sizes == ':' )
  197.                 *psz_sizes++ = '';
  198.             if ( sscanf( psz_size, "%dx%d", &i_width, &i_height ) != 2 )
  199.             {
  200.                 msg_Err( p_stream, "bad size %s for file %s", psz_size,
  201.                          psz_file );
  202.                 free( p_sys );
  203.                 return VLC_EGENERIC;
  204.             }
  205.         }
  206.         if ( UnpackFromFile( p_stream, psz_file, i_width, i_height,
  207.                              &p_sys->p_pictures[p_sys->i_nb_pictures] ) < 0 )
  208.         {
  209.             free( p_sys );
  210.             return VLC_EGENERIC;
  211.         }
  212.         p_sys->i_nb_pictures++;
  213.     }
  214.     var_Get( p_stream, SOUT_CFG_PREFIX "aspect-ratio", &val );
  215.     if ( val.psz_string )
  216.     {
  217.         char *psz_parser = strchr( val.psz_string, ':' );
  218.         if( psz_parser )
  219.         {
  220.             *psz_parser++ = '';
  221.             p_sys->i_aspect = atoi( val.psz_string ) * VOUT_ASPECT_FACTOR
  222.                 / atoi( psz_parser );
  223.         }
  224.         else
  225.         {
  226.             msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );
  227.             p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
  228.         }
  229.         free( val.psz_string );
  230.     }
  231.     else
  232.     {
  233.         p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;
  234.     }
  235.     var_Get( p_stream, SOUT_CFG_PREFIX "port", &val );
  236.     p_sys->i_fd = net_ListenUDP1( p_stream, NULL, val.i_int );
  237.     if ( p_sys->i_fd < 0 )
  238.     {
  239.         free( p_sys );
  240.         return VLC_EGENERIC;
  241.     }
  242.     var_Get( p_stream, SOUT_CFG_PREFIX "command", &val );
  243.     p_sys->i_cmd = val.i_int;
  244.     p_sys->i_old_cmd = 0;
  245.     var_Get( p_stream, SOUT_CFG_PREFIX "gop", &val );
  246.     p_sys->i_gop = val.i_int;
  247.     var_Get( p_stream, SOUT_CFG_PREFIX "qscale", &val );
  248.     p_sys->i_qscale = val.i_int;
  249.     var_Get( p_stream, SOUT_CFG_PREFIX "mute-audio", &val );
  250.     p_sys->b_audio = val.b_bool;
  251.     p_stream->pf_add    = Add;
  252.     p_stream->pf_del    = Del;
  253.     p_stream->pf_send   = Send;
  254.     p_stream->p_sys     = p_sys;
  255.     avcodec_init();
  256.     avcodec_register_all();
  257.     return VLC_SUCCESS;
  258. }
  259. /*****************************************************************************
  260.  * Close:
  261.  *****************************************************************************/
  262. static void Close( vlc_object_t * p_this )
  263. {
  264.     sout_stream_t       *p_stream = (sout_stream_t *)p_this;
  265.     sout_stream_sys_t   *p_sys = p_stream->p_sys;
  266.     sout_StreamDelete( p_sys->p_out );
  267.     free( p_sys );
  268. }
  269. /*****************************************************************************
  270.  * Add: Add an input elementary stream
  271.  *****************************************************************************/
  272. static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
  273. {
  274.     sout_stream_sys_t   *p_sys = p_stream->p_sys;
  275.     sout_stream_id_t    *id;
  276.     id = calloc( 1, sizeof( sout_stream_id_t ) );
  277.     if( !id )
  278.         return NULL;
  279.     if( p_fmt->i_cat == VIDEO_ES &&
  280.         ( p_fmt->i_codec == VLC_FOURCC('m', 'p', 'g', 'v') ||
  281.           p_fmt->i_codec == VLC_FOURCC('f', 'a', 'k', 'e') ) )
  282.     {
  283.         id->b_switcher_video = true;
  284.         p_fmt->i_codec = VLC_FOURCC('m', 'p', 'g', 'v');
  285.         msg_Dbg( p_stream, "creating video switcher for fcc=`%4.4s' cmd:%d",
  286.                  (char*)&p_fmt->i_codec, p_sys->i_cmd );
  287.     }
  288.     else if ( p_fmt->i_cat == AUDIO_ES &&
  289.               p_fmt->i_codec == VLC_FOURCC('m', 'p', 'g', 'a') &&
  290.               p_sys->b_audio )
  291.     {
  292.         int i_ff_codec = CODEC_ID_MP2;
  293.         int i;
  294.         id->b_switcher_audio = true;
  295.         msg_Dbg( p_stream, "creating audio switcher for fcc=`%4.4s' cmd:%d",
  296.                  (char*)&p_fmt->i_codec, p_sys->i_cmd );
  297.         /* Allocate the encoder right now. */
  298.         if( i_ff_codec == 0 )
  299.         {
  300.             msg_Err( p_stream, "cannot find encoder" );
  301.             free( id );
  302.             return NULL;
  303.         }
  304.         id->ff_enc = avcodec_find_encoder( i_ff_codec );
  305.         if( !id->ff_enc )
  306.         {
  307.             msg_Err( p_stream, "cannot find encoder (avcodec)" );
  308.             free( id );
  309.             return NULL;
  310.         }
  311.         id->ff_enc_c = avcodec_alloc_context();
  312.         /* Set CPU capabilities */
  313.         unsigned i_cpu = vlc_CPU();
  314.         id->ff_enc_c->dsp_mask = 0;
  315.         if( !(i_cpu & CPU_CAPABILITY_MMX) )
  316.         {
  317.             id->ff_enc_c->dsp_mask |= FF_MM_MMX;
  318.         }
  319.         if( !(i_cpu & CPU_CAPABILITY_MMXEXT) )
  320.         {
  321.             id->ff_enc_c->dsp_mask |= FF_MM_MMXEXT;
  322.         }
  323.         if( !(i_cpu & CPU_CAPABILITY_3DNOW) )
  324.         {
  325.             id->ff_enc_c->dsp_mask |= FF_MM_3DNOW;
  326.         }
  327.         if( !(i_cpu & CPU_CAPABILITY_SSE) )
  328.         {
  329.             id->ff_enc_c->dsp_mask |= FF_MM_SSE;
  330.             id->ff_enc_c->dsp_mask |= FF_MM_SSE2;
  331.         }
  332.         id->ff_enc_c->sample_rate = p_fmt->audio.i_rate;
  333.         id->ff_enc_c->channels    = p_fmt->audio.i_channels;
  334.         id->ff_enc_c->bit_rate    = p_fmt->i_bitrate;
  335.         vlc_avcodec_lock();
  336.         if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
  337.         {
  338.             avcodec_unlock();
  339.             msg_Err( p_stream, "cannot open encoder" );
  340.             av_free( id->ff_enc_c );
  341.             free( id );
  342.             return NULL;
  343.         }
  344.         avcodec_unlock();
  345.         id->p_buffer_out = malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * 2 );
  346.         id->p_samples = calloc( id->ff_enc_c->frame_size * p_fmt->audio.i_channels,
  347.                                 sizeof(int16_t) );
  348.         if( !id->p_buffer_out || !id->p_samples )
  349.             goto error;
  350.         for( i = 0; i < MAX_AUDIO; i++ )
  351.         {
  352.             if( p_sys->pp_audio_ids[i] == NULL )
  353.             {
  354.                 p_sys->pp_audio_ids[i] = id;
  355.                 break;
  356.             }
  357.         }
  358.         if( i == MAX_AUDIO )
  359.         {
  360.             msg_Err( p_stream, "too many audio streams!" );
  361.             goto error;
  362.         }
  363.     }
  364.     else
  365.     {
  366.         msg_Dbg( p_stream, "do not know what to do when switching (fcc=`%4.4s')",
  367.                  (char*)&p_fmt->i_codec );
  368.     }
  369.     /* src format */
  370.     memcpy( &id->f_src, p_fmt, sizeof( es_format_t ) );
  371.     /* open output stream */
  372.     id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );
  373.     if( id->id != NULL )
  374.         return id;
  375. error:
  376.     vlc_avcodec_lock();
  377.     avcodec_close( id->ff_enc_c );
  378.     vlc_avcodec_unlock();
  379.     free( id->p_samples );
  380.     free( id->p_buffer_out );
  381.     av_free( id->ff_enc_c );
  382.     free( id );
  383.     return NULL;
  384. }
  385. /*****************************************************************************
  386.  * Del: Del an elementary stream
  387.  *****************************************************************************/
  388. static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
  389. {
  390.     sout_stream_sys_t   *p_sys = p_stream->p_sys;
  391.     if ( id->b_switcher_audio )
  392.     {
  393.         int i;
  394.         for ( i = 0; i < MAX_AUDIO; i++ )
  395.         {
  396.             if ( p_sys->pp_audio_ids[i] == id )
  397.             {
  398.                 p_sys->pp_audio_ids[i] = NULL;
  399.                 break;
  400.             }
  401.         }
  402.     }
  403.     if ( id->ff_enc )
  404.     {
  405.         vlc_avcodec_lock();
  406.         avcodec_close( id->ff_enc_c );
  407.         vlc_avcodec_unlock();
  408.         av_free( id->ff_enc_c );
  409.         av_free( id->p_frame );
  410.         free( id->p_buffer_out );
  411.     }
  412.     if ( id->id )
  413.     {
  414.         p_sys->p_out->pf_del( p_sys->p_out, id->id );
  415.     }
  416.     free( id );
  417.     return VLC_SUCCESS;
  418. }
  419. /*****************************************************************************
  420.  * Send: Process an input packet
  421.  *****************************************************************************/
  422. static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
  423.                  block_t *p_buffer )
  424. {
  425.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  426.     if ( !id->id )
  427.     {
  428.         block_Release( p_buffer );
  429.         return VLC_EGENERIC;
  430.     }
  431.     if ( !id->b_switcher_video && !id->b_switcher_audio )
  432.     {
  433.         return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
  434.     }
  435.     block_ChainAppend( &id->p_queued, p_buffer );
  436.     if ( id->b_switcher_video )
  437.     {
  438.         /* Check for commands for every video frame. */
  439.         NetCommand( p_stream );
  440.         while ( id->p_queued != NULL )
  441.         {
  442.             mtime_t i_dts = 0;
  443.             int i;
  444.             if ( p_sys->i_old_cmd != p_sys->i_cmd )
  445.             {
  446.                 i_dts = VideoCommand( p_stream, id );
  447.             }
  448.             i_dts = Process( p_stream, id, i_dts );
  449.             for ( i = 0; i < MAX_AUDIO; i++ )
  450.             {
  451.                 if ( p_sys->pp_audio_ids[i] != NULL )
  452.                     Process( p_stream, p_sys->pp_audio_ids[i], i_dts );
  453.             }
  454.         }
  455.     }
  456.     return VLC_SUCCESS;
  457. }
  458. /*****************************************************************************
  459.  * Process: Process and dispatch buffers
  460.  *****************************************************************************/
  461. static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id,
  462.                         mtime_t i_max_dts )
  463. {
  464.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  465.     mtime_t i_dts = 0;
  466.     block_t *p_blocks = NULL;
  467.     block_t *p_blocks_out = NULL;
  468.     /* Find out the blocks we need. */
  469.     while ( id->p_queued != NULL
  470.              && (!i_max_dts || id->p_queued->i_dts <= i_max_dts) )
  471.     {
  472.         block_t *p_next = id->p_queued->p_next;
  473.         id->p_queued->p_next = NULL;
  474.         i_dts = id->p_queued->i_dts;
  475.         block_ChainAppend( &p_blocks, id->p_queued );
  476.         id->p_queued = p_next;
  477.     }
  478.     if ( p_sys->i_old_cmd == 0 )
  479.     {
  480.         /* Full forward */
  481.         if ( p_blocks != NULL )
  482.             p_sys->p_out->pf_send( p_sys->p_out, id->id, p_blocks );
  483.         return i_dts;
  484.     }
  485.     if ( p_sys->i_old_cmd == -1 )
  486.     {
  487.         /* No output at all */
  488.         while ( p_blocks != NULL )
  489.         {
  490.             block_t * p_next = p_blocks->p_next;
  491.             block_Release( p_blocks );
  492.             p_blocks = p_next;
  493.         }
  494.         return i_dts;
  495.     }
  496.     while ( p_blocks != NULL )
  497.     {
  498.         block_t * p_next = p_blocks->p_next;
  499.         block_t * p_out;
  500.         if ( id->b_switcher_video )
  501.         {
  502.             p_out = VideoGetBuffer( p_stream, id, p_blocks );
  503.         }
  504.         else
  505.         {
  506.             p_out = AudioGetBuffer( p_stream, id, p_blocks );
  507.         }
  508.         p_blocks = p_next;
  509.         if ( p_out != NULL )
  510.         {
  511.             block_ChainAppend( &p_blocks_out, p_out );
  512.         }
  513.     }
  514.     if ( p_blocks_out != NULL )
  515.         p_sys->p_out->pf_send( p_sys->p_out, id->id, p_blocks_out );
  516.     return i_dts;
  517. }
  518. /*****************************************************************************
  519.  * UnpackFromFile: Read a YUV picture and store it in our format
  520.  *****************************************************************************/
  521. static int UnpackFromFile( sout_stream_t *p_stream, const char *psz_file,
  522.                            int i_width, int i_height,
  523.                            picture_t *p_pic )
  524. {
  525.     int i, j;
  526.     FILE *p_file = utf8_fopen( psz_file, "r" );
  527.     if ( p_file == NULL )
  528.     {
  529.         msg_Err( p_stream, "file %s not found", psz_file );
  530.         return -1;
  531.     }
  532.     vout_InitPicture( VLC_OBJECT(p_stream), p_pic, VLC_FOURCC('I','4','2','0'),
  533.                       i_width, i_height,
  534.                       i_width * VOUT_ASPECT_FACTOR / i_height );
  535.     for ( i = 0; i < p_pic->i_planes; i++ )
  536.     {
  537.         p_pic->p[i].p_pixels = malloc( p_pic->p[i].i_lines *
  538.                                            p_pic->p[i].i_pitch );
  539.         memset( p_pic->p[i].p_pixels, 0, p_pic->p[i].i_lines *
  540.                     p_pic->p[i].i_pitch );
  541.     }
  542.     for ( i = 0; i < i_height; i++ )
  543.     {
  544.         int i_chroma;
  545.         uint8_t p_buffer[i_width * 2];
  546.         uint8_t *p_char = p_buffer;
  547.         uint8_t *p_y = &p_pic->p[0].p_pixels[i * p_pic->p[0].i_pitch];
  548.         uint8_t *p_u = &p_pic->p[1].p_pixels[i/2 * p_pic->p[1].i_pitch];
  549.         uint8_t *p_v = &p_pic->p[2].p_pixels[i/2 * p_pic->p[2].i_pitch];
  550.         if ( fread( p_buffer, 2, i_width, p_file ) != (size_t)i_width )
  551.         {
  552.             msg_Err( p_stream, "premature end of file %s", psz_file );
  553.             fclose( p_file );
  554.             for ( i = 0; i < p_pic->i_planes; i++ )
  555.             {
  556.                 free( p_pic->p[i].p_pixels );
  557.             }
  558.             return -1;
  559.         }
  560.         i_chroma = 0;
  561.         for ( j = 0; j < i_width; j++ )
  562.         {
  563.             uint8_t **pp_chroma = i_chroma ? &p_v : &p_u;
  564.             i_chroma = !i_chroma;
  565.             if ( i & 1 )
  566.                 **pp_chroma = (**pp_chroma + *p_char + 1) / 2;
  567.             else
  568.                 **pp_chroma = *p_char;
  569.             (*pp_chroma)++;
  570.             p_char++;
  571.             *p_y++ = *p_char++;
  572.         }
  573.     }
  574.     fclose( p_file );
  575.     return 0;
  576. }
  577. /*****************************************************************************
  578.  * NetCommand: Get a command from the network
  579.  *****************************************************************************/
  580. static void NetCommand( sout_stream_t *p_stream )
  581. {
  582.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  583.     char psz_buffer[11];
  584.     int i_len = recv( p_sys->i_fd, psz_buffer, sizeof( psz_buffer ) - 1, 0 );
  585.     if ( i_len > 0 )
  586.     {
  587.         psz_buffer[i_len] = '';
  588.         int i_cmd = strtol( psz_buffer, NULL, 0 );
  589.         if ( i_cmd < -1 || i_cmd > p_sys->i_nb_pictures )
  590.         {
  591.             msg_Err( p_stream, "got a wrong command (%d)", i_cmd );
  592.             return;
  593.         }
  594.         p_sys->i_cmd = i_cmd;
  595.         msg_Dbg( p_stream, "new command: %d old:%d", p_sys->i_cmd,
  596.                  p_sys->i_old_cmd );
  597.     }
  598. }
  599. /*****************************************************************************
  600.  * VideoCommand: Create/Delete a video encoder
  601.  *****************************************************************************/
  602. static mtime_t VideoCommand( sout_stream_t *p_stream, sout_stream_id_t *id )
  603. {
  604.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  605.     if ( p_sys->i_cmd == 0 && !(id->p_queued->i_flags & BLOCK_FLAG_TYPE_I) )
  606.     {
  607.         mtime_t i_dts = id->p_queued->i_dts;
  608.         block_t *p_block = id->p_queued->p_next;
  609.         while ( p_block != NULL )
  610.         {
  611.             if ( p_block->i_flags & BLOCK_FLAG_TYPE_I )
  612.                 return i_dts;
  613.             i_dts = p_block->i_dts;
  614.             p_block = p_block->p_next;
  615.         }
  616.         return 0;
  617.     }
  618.     p_sys->i_old_cmd = p_sys->i_cmd;
  619.     if ( id->ff_enc )
  620.     {
  621.         vlc_avcodec_lock();
  622.         avcodec_close( id->ff_enc_c );
  623.         vlc_avcodec_unlock();
  624.         av_free( id->ff_enc_c );
  625.         av_free( id->p_frame );
  626.         free( id->p_buffer_out );
  627.         id->ff_enc = NULL;
  628.     }
  629.     if ( p_sys->i_cmd > 0 )
  630.     {
  631.         /* Create a new encoder. */
  632.         int i_ff_codec = CODEC_ID_MPEG2VIDEO;
  633.         int i_aspect_num, i_aspect_den;
  634.         if( i_ff_codec == 0 )
  635.         {
  636.             msg_Err( p_stream, "cannot find encoder" );
  637.             return 0;
  638.         }
  639.         id->ff_enc = avcodec_find_encoder( i_ff_codec );
  640.         if( !id->ff_enc )
  641.         {
  642.             msg_Err( p_stream, "cannot find encoder (avcodec)" );
  643.             return 0;
  644.         }
  645.         id->ff_enc_c = avcodec_alloc_context();
  646.         /* Set CPU capabilities */
  647.         unsigned i_cpu = vlc_CPU();
  648.         id->ff_enc_c->dsp_mask = 0;
  649.         if( !(i_cpu & CPU_CAPABILITY_MMX) )
  650.         {
  651.             id->ff_enc_c->dsp_mask |= FF_MM_MMX;
  652.         }
  653.         if( !(i_cpu & CPU_CAPABILITY_MMXEXT) )
  654.         {
  655.             id->ff_enc_c->dsp_mask |= FF_MM_MMXEXT;
  656.         }
  657.         if( !(i_cpu & CPU_CAPABILITY_3DNOW) )
  658.         {
  659.             id->ff_enc_c->dsp_mask |= FF_MM_3DNOW;
  660.         }
  661.         if( !(i_cpu & CPU_CAPABILITY_SSE) )
  662.         {
  663.             id->ff_enc_c->dsp_mask |= FF_MM_SSE;
  664.             id->ff_enc_c->dsp_mask |= FF_MM_SSE2;
  665.         }
  666.         id->ff_enc_c->width = p_sys->p_pictures[p_sys->i_cmd-1].format.i_width;
  667.         id->ff_enc_c->height = p_sys->p_pictures[p_sys->i_cmd-1].format.i_height;
  668.         av_reduce( &i_aspect_num, &i_aspect_den,
  669.                    p_sys->i_aspect,
  670.                    VOUT_ASPECT_FACTOR, 1 << 30 /* something big */ );
  671.         av_reduce( &id->ff_enc_c->sample_aspect_ratio.num,
  672.                    &id->ff_enc_c->sample_aspect_ratio.den,
  673.                    i_aspect_num * (int64_t)id->ff_enc_c->height,
  674.                    i_aspect_den * (int64_t)id->ff_enc_c->width, 1 << 30 );
  675. #if LIBAVCODEC_BUILD >= 4754
  676.         id->ff_enc_c->time_base.num = 1;
  677.         id->ff_enc_c->time_base.den = 25; /* FIXME */
  678. #else
  679.         id->ff_enc_c->frame_rate    = 25; /* FIXME */
  680.         id->ff_enc_c->frame_rate_base = 1;
  681. #endif
  682.         id->ff_enc_c->gop_size = 200;
  683.         id->ff_enc_c->max_b_frames = 0;
  684.         id->ff_enc_c->flags |= CODEC_FLAG_QSCALE
  685.                             | CODEC_FLAG_INPUT_PRESERVED
  686.                             | CODEC_FLAG_LOW_DELAY;
  687.         id->ff_enc_c->mb_decision = FF_MB_DECISION_SIMPLE;
  688.         id->ff_enc_c->pix_fmt = PIX_FMT_YUV420P;
  689.         avcodec_lock();
  690.         if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
  691.         {
  692.             avcodec_unlock();
  693.             msg_Err( p_stream, "cannot open encoder" );
  694.             return 0;
  695.         }
  696.         avcodec_unlock();
  697.         id->p_buffer_out = malloc( id->ff_enc_c->width * id->ff_enc_c->height * 3 );
  698.         id->p_frame = avcodec_alloc_frame();
  699.         id->p_frame->linesize[0] = p_sys->p_pictures[p_sys->i_cmd-1].p[0].i_pitch;
  700.         id->p_frame->linesize[1] = p_sys->p_pictures[p_sys->i_cmd-1].p[1].i_pitch;
  701.         id->p_frame->linesize[2] = p_sys->p_pictures[p_sys->i_cmd-1].p[2].i_pitch;
  702.         id->p_frame->data[0] = p_sys->p_pictures[p_sys->i_cmd-1].p[0].p_pixels;
  703.         id->p_frame->data[1] = p_sys->p_pictures[p_sys->i_cmd-1].p[1].p_pixels;
  704.         id->p_frame->data[2] = p_sys->p_pictures[p_sys->i_cmd-1].p[2].p_pixels;
  705.         id->i_nb_pred = p_sys->i_gop;
  706.     }
  707.     return 0;
  708. }
  709. /*****************************************************************************
  710.  * VideoGetBuffer: Build an alternate video buffer
  711.  *****************************************************************************/
  712. static block_t *VideoGetBuffer( sout_stream_t *p_stream, sout_stream_id_t *id,
  713.                                 block_t *p_buffer )
  714. {
  715.     sout_stream_sys_t *p_sys = p_stream->p_sys;
  716.     int i_out;
  717.     block_t *p_out;
  718.     id->p_frame->quality = p_sys->i_qscale * powf(2.0, FF_LAMBDA_SHIFT + 7.0)
  719.                             / 139.0;
  720.     id->p_frame->interlaced_frame = 0;
  721.     id->p_frame->top_field_first = 1;
  722.     id->p_frame->pts = p_buffer->i_dts;
  723.     if ( id->i_nb_pred >= p_sys->i_gop )
  724.     {
  725.         id->p_frame->pict_type = FF_I_TYPE;
  726. #if 0
  727.         id->p_frame->me_threshold = 0;
  728.         id->p_frame->mb_threshold = 0;
  729. #endif
  730.         id->i_nb_pred = 0;
  731.     }
  732.     else
  733.     {
  734.         id->p_frame->pict_type = FF_P_TYPE;
  735. #if 0
  736.         if ( id->p_frame->mb_type != NULL )
  737.         {
  738.             id->p_frame->me_threshold = MAX_THRESHOLD;
  739.             id->p_frame->mb_threshold = MAX_THRESHOLD;
  740.         }
  741. #endif
  742.         id->i_nb_pred++;
  743.     }
  744.     i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer_out,
  745.                                   id->ff_enc_c->width * id->ff_enc_c->height * 3,
  746.                                   id->p_frame );
  747.     if ( i_out <= 0 )
  748.         return NULL;
  749. #if 0
  750.     if ( id->p_frame->mb_type == NULL
  751.           && id->ff_enc_c->coded_frame->pict_type != FF_I_TYPE )
  752.     {
  753.         int mb_width = (id->ff_enc_c->width + 15) / 16;
  754.         int mb_height = (id->ff_enc_c->height + 15) / 16;
  755.         int h_chroma_shift, v_chroma_shift;
  756.         int i;
  757.         avcodec_get_chroma_sub_sample( id->ff_enc_c->pix_fmt, &h_chroma_shift,
  758.                                        &v_chroma_shift );
  759.         id->p_frame->motion_subsample_log2
  760.             = id->ff_enc_c->coded_frame->motion_subsample_log2;
  761.         id->p_frame->mb_type = malloc( ((mb_width + 1) * (mb_height + 1) + 1)
  762.                                     * sizeof(uint32_t) );
  763.         vlc_memcpy( id->p_frame->mb_type, id->ff_enc_c->coded_frame->mb_type,
  764.                     (mb_width + 1) * mb_height * sizeof(id->p_frame->mb_type[0]));
  765.         for ( i = 0; i < 2; i++ )
  766.         {
  767.             int stride = ((16 * mb_width )
  768.                     >> id->ff_enc_c->coded_frame->motion_subsample_log2) + 1;
  769.             int height = ((16 * mb_height)
  770.                     >> id->ff_enc_c->coded_frame->motion_subsample_log2);
  771.             int b8_stride = mb_width * 2 + 1;
  772.             if ( id->ff_enc_c->coded_frame->motion_val[i] )
  773.             {
  774.                 id->p_frame->motion_val[i] = malloc( 2 * stride * height
  775.                                                 * sizeof(int16_t) );
  776.                 vlc_memcpy( id->p_frame->motion_val[i],
  777.                             id->ff_enc_c->coded_frame->motion_val[i],
  778.                             2 * stride * height * sizeof(int16_t) );
  779.             }
  780.             if ( id->ff_enc_c->coded_frame->ref_index[i] )
  781.             {
  782.                 id->p_frame->ref_index[i] = malloc( b8_stride * 2 * mb_height
  783.                                                * sizeof(int8_t) );
  784.                 vlc_memcpy( id->p_frame->ref_index[i],
  785.                             id->ff_enc_c->coded_frame->ref_index[i],
  786.                             b8_stride * 2 * mb_height * sizeof(int8_t));
  787.             }
  788.         }
  789.     }
  790. #endif
  791.     p_out = block_New( p_stream, i_out );
  792.     vlc_memcpy( p_out->p_buffer, id->p_buffer_out, i_out );
  793.     p_out->i_length = p_buffer->i_length;
  794.     p_out->i_pts = p_buffer->i_dts;
  795.     p_out->i_dts = p_buffer->i_dts;
  796.     p_out->i_rate = p_buffer->i_rate;
  797.     switch ( id->ff_enc_c->coded_frame->pict_type )
  798.     {
  799.     case FF_I_TYPE:
  800.         p_out->i_flags |= BLOCK_FLAG_TYPE_I;
  801.         break;
  802.     case FF_P_TYPE:
  803.         p_out->i_flags |= BLOCK_FLAG_TYPE_P;
  804.         break;
  805.     case FF_B_TYPE:
  806.         p_out->i_flags |= BLOCK_FLAG_TYPE_B;
  807.         break;
  808.     default:
  809.         break;
  810.     }
  811.     block_Release( p_buffer );
  812.     return p_out;
  813. }
  814. /*****************************************************************************
  815.  * AudioGetBuffer: Build an alternate audio buffer
  816.  *****************************************************************************/
  817. static block_t *AudioGetBuffer( sout_stream_t *p_stream, sout_stream_id_t *id,
  818.                                 block_t *p_buffer )
  819. {
  820.     int i_out;
  821.     block_t *p_out;
  822.     i_out = avcodec_encode_audio( id->ff_enc_c, id->p_buffer_out,
  823.                                   2 * AVCODEC_MAX_AUDIO_FRAME_SIZE,
  824.                                   id->p_samples );
  825.     if ( i_out <= 0 )
  826.         return NULL;
  827.     p_out = block_New( p_stream, i_out );
  828.     vlc_memcpy( p_out->p_buffer, id->p_buffer_out, i_out );
  829.     p_out->i_length = p_buffer->i_length;
  830.     p_out->i_pts = p_buffer->i_dts;
  831.     p_out->i_dts = p_buffer->i_dts;
  832.     p_out->i_rate = p_buffer->i_rate;
  833.     block_Release( p_buffer );
  834.     return p_out;
  835. }