⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 switcher.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * switcher.c: MPEG2 video switcher module ***************************************************************************** * Copyright (C) 2004 the VideoLAN team * $Id$ * * Authors: Christophe Massiot <massiot@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <math.h>#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_sout.h>#include <vlc_vout.h>#include <vlc_charset.h>#include <vlc_network.h>#define HAVE_MMX#ifdef HAVE_LIBAVCODEC_AVCODEC_H#   include <libavcodec/avcodec.h>#elif defined(HAVE_FFMPEG_AVCODEC_H)#   include <ffmpeg/avcodec.h>#else#   include <avcodec.h>#endif#ifdef HAVE_POSTPROC_POSTPROCESS_H#   include <postproc/postprocess.h>#else#   include <libpostproc/postprocess.h>#endif#define SOUT_CFG_PREFIX "sout-switcher-"#define MAX_PICTURES 10#define MAX_AUDIO 30#define MAX_THRESHOLD 99999999/***************************************************************************** * Local prototypes *****************************************************************************/static int      Open    ( vlc_object_t * );static void     Close   ( vlc_object_t * );static sout_stream_id_t *Add( sout_stream_t *, es_format_t * );static int Del( sout_stream_t *, sout_stream_id_t * );static int Send( sout_stream_t *, sout_stream_id_t *, block_t * );static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id,                        mtime_t i_max_dts );static int UnpackFromFile( sout_stream_t *p_stream, const char *psz_file,                           int i_width, int i_height,                           picture_t *p_pic );static void NetCommand( sout_stream_t *p_stream );static mtime_t VideoCommand( sout_stream_t *p_stream, sout_stream_id_t *id );static block_t *VideoGetBuffer( sout_stream_t *p_stream, sout_stream_id_t *id,                                block_t *p_buffer );static block_t *AudioGetBuffer( sout_stream_t *p_stream, sout_stream_id_t *id,                                block_t *p_buffer );/***************************************************************************** * Module descriptor *****************************************************************************/#define FILES_TEXT N_("Files")#define FILES_LONGTEXT N_( \    "Full paths of the files separated by colons." )#define SIZES_TEXT N_("Sizes")#define SIZES_LONGTEXT N_( \    "List of sizes separated by colons (720x576:480x576)." )#define RATIO_TEXT N_("Aspect ratio")#define RATIO_LONGTEXT N_( \    "Aspect ratio (4:3, 16:9)." )#define PORT_TEXT N_("Command UDP port")#define PORT_LONGTEXT N_( \    "UDP port to listen to for commands." )#define COMMAND_TEXT N_("Command")#define COMMAND_LONGTEXT N_( \    "Initial command to execute." )#define GOP_TEXT N_("GOP size")#define GOP_LONGTEXT N_( \    "Number of P frames between two I frames." )#define QSCALE_TEXT N_("Quantizer scale")#define QSCALE_LONGTEXT N_( \    "Fixed quantizer scale to use." )#define AUDIO_TEXT N_("Mute audio")#define AUDIO_LONGTEXT N_( \    "Mute audio when command is not 0." )vlc_module_begin();    set_description( N_("MPEG2 video switcher stream output") );    set_capability( "sout stream", 50 );    add_shortcut( "switcher" );    set_callbacks( Open, Close );    add_string( SOUT_CFG_PREFIX "files", "", NULL, FILES_TEXT,                FILES_LONGTEXT, false );    add_string( SOUT_CFG_PREFIX "sizes", "", NULL, SIZES_TEXT,                SIZES_LONGTEXT, false );    add_string( SOUT_CFG_PREFIX "aspect-ratio", "4:3", NULL, RATIO_TEXT,                RATIO_LONGTEXT, false );    add_integer( SOUT_CFG_PREFIX "port", 5001, NULL,                 PORT_TEXT, PORT_LONGTEXT, true );    add_integer( SOUT_CFG_PREFIX "command", 0, NULL,                 COMMAND_TEXT, COMMAND_LONGTEXT, true );    add_integer( SOUT_CFG_PREFIX "gop", 8, NULL,                 GOP_TEXT, GOP_LONGTEXT, true );    add_integer( SOUT_CFG_PREFIX "qscale", 5, NULL,                 QSCALE_TEXT, QSCALE_LONGTEXT, true );    add_bool( SOUT_CFG_PREFIX "mute-audio", 1, NULL,              AUDIO_TEXT, AUDIO_LONGTEXT, true );vlc_module_end();static const char *const ppsz_sout_options[] = {    "files", "sizes", "aspect-ratio", "port", "command", "gop", "qscale",    "mute-audio", NULL};struct sout_stream_sys_t{    sout_stream_t   *p_out;    int             i_gop;    int             i_qscale;    int             i_aspect;    sout_stream_id_t *pp_audio_ids[MAX_AUDIO];    bool      b_audio;    /* Pictures */    picture_t       p_pictures[MAX_PICTURES];    int             i_nb_pictures;    /* Command */    int             i_fd;    int             i_cmd, i_old_cmd;};struct sout_stream_id_t{    void            *id;    bool      b_switcher_video;    bool      b_switcher_audio;    es_format_t     f_src;    block_t         *p_queued;    /* ffmpeg part */    AVCodec         *ff_enc;    AVCodecContext  *ff_enc_c;    AVFrame         *p_frame;    uint8_t         *p_buffer_out;    int             i_nb_pred;    int16_t         *p_samples;};/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){    sout_stream_t     *p_stream = (sout_stream_t*)p_this;    sout_stream_sys_t *p_sys;    vlc_value_t       val;    char              *psz_files, *psz_sizes;    int               i_height = 0, i_width = 0;    p_sys = malloc( sizeof(sout_stream_sys_t) );    memset( p_sys, 0, sizeof(sout_stream_sys_t) );    p_sys->p_out = sout_StreamNew( p_stream->p_sout, p_stream->psz_next );    if( !p_sys->p_out )    {        msg_Err( p_stream, "cannot create chain" );        free( p_sys );        return VLC_EGENERIC;    }    config_ChainParse( p_stream, SOUT_CFG_PREFIX, ppsz_sout_options,                   p_stream->p_cfg );    var_Get( p_stream, SOUT_CFG_PREFIX "files", &val );    psz_files = val.psz_string;    var_Get( p_stream, SOUT_CFG_PREFIX "sizes", &val );    psz_sizes = val.psz_string;    p_sys->i_nb_pictures = 0;    while ( psz_files && *psz_files )    {        char * psz_file = psz_files;        char * psz_size = psz_sizes;        while ( *psz_files && *psz_files != ':' )            psz_files++;        if ( *psz_files == ':' )           *psz_files++ = '\0';        if ( *psz_sizes )        {            while ( *psz_sizes && *psz_sizes != ':' )                psz_sizes++;            if ( *psz_sizes == ':' )                *psz_sizes++ = '\0';            if ( sscanf( psz_size, "%dx%d", &i_width, &i_height ) != 2 )            {                msg_Err( p_stream, "bad size %s for file %s", psz_size,                         psz_file );                free( p_sys );                return VLC_EGENERIC;            }        }        if ( UnpackFromFile( p_stream, psz_file, i_width, i_height,                             &p_sys->p_pictures[p_sys->i_nb_pictures] ) < 0 )        {            free( p_sys );            return VLC_EGENERIC;        }        p_sys->i_nb_pictures++;    }    var_Get( p_stream, SOUT_CFG_PREFIX "aspect-ratio", &val );    if ( val.psz_string )    {        char *psz_parser = strchr( val.psz_string, ':' );        if( psz_parser )        {            *psz_parser++ = '\0';            p_sys->i_aspect = atoi( val.psz_string ) * VOUT_ASPECT_FACTOR                / atoi( psz_parser );        }        else        {            msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string );            p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;        }        free( val.psz_string );    }    else    {        p_sys->i_aspect = 4 * VOUT_ASPECT_FACTOR / 3;    }    var_Get( p_stream, SOUT_CFG_PREFIX "port", &val );    p_sys->i_fd = net_ListenUDP1( p_stream, NULL, val.i_int );    if ( p_sys->i_fd < 0 )    {        free( p_sys );        return VLC_EGENERIC;    }    var_Get( p_stream, SOUT_CFG_PREFIX "command", &val );    p_sys->i_cmd = val.i_int;    p_sys->i_old_cmd = 0;    var_Get( p_stream, SOUT_CFG_PREFIX "gop", &val );    p_sys->i_gop = val.i_int;    var_Get( p_stream, SOUT_CFG_PREFIX "qscale", &val );    p_sys->i_qscale = val.i_int;    var_Get( p_stream, SOUT_CFG_PREFIX "mute-audio", &val );    p_sys->b_audio = val.b_bool;    p_stream->pf_add    = Add;    p_stream->pf_del    = Del;    p_stream->pf_send   = Send;    p_stream->p_sys     = p_sys;    avcodec_init();    avcodec_register_all();    return VLC_SUCCESS;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t * p_this ){    sout_stream_t       *p_stream = (sout_stream_t *)p_this;    sout_stream_sys_t   *p_sys = p_stream->p_sys;    sout_StreamDelete( p_sys->p_out );    free( p_sys );}/***************************************************************************** * Add: Add an input elementary stream *****************************************************************************/static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ){    sout_stream_sys_t   *p_sys = p_stream->p_sys;    sout_stream_id_t    *id;    id = malloc( sizeof( sout_stream_id_t ) );    memset( id, 0, sizeof( sout_stream_id_t ) );    id->id = NULL;    if ( p_fmt->i_cat == VIDEO_ES            && (p_fmt->i_codec == VLC_FOURCC('m', 'p', 'g', 'v')                 || p_fmt->i_codec == VLC_FOURCC('f', 'a', 'k', 'e')) )    {        id->b_switcher_video = true;        p_fmt->i_codec = VLC_FOURCC('m', 'p', 'g', 'v');        msg_Dbg( p_stream,                 "creating video switcher for fcc=`%4.4s' cmd:%d",                 (char*)&p_fmt->i_codec, p_sys->i_cmd );    }    else if ( p_fmt->i_cat == AUDIO_ES               && p_fmt->i_codec == VLC_FOURCC('m', 'p', 'g', 'a')               && p_sys->b_audio )    {        int i_ff_codec = CODEC_ID_MP2;        int i;        id->b_switcher_audio = true;        msg_Dbg( p_stream,                 "creating audio switcher for fcc=`%4.4s' cmd:%d",                 (char*)&p_fmt->i_codec, p_sys->i_cmd );        /* Allocate the encoder right now. */        if( i_ff_codec == 0 )        {            msg_Err( p_stream, "cannot find encoder" );            return NULL;        }        id->ff_enc = avcodec_find_encoder( i_ff_codec );        if( !id->ff_enc )        {            msg_Err( p_stream, "cannot find encoder (avcodec)" );            return NULL;        }        id->ff_enc_c = avcodec_alloc_context();        /* Set CPU capabilities */        unsigned i_cpu = vlc_CPU();        id->ff_enc_c->dsp_mask = 0;        if( !(i_cpu & CPU_CAPABILITY_MMX) )        {            id->ff_enc_c->dsp_mask |= FF_MM_MMX;        }        if( !(i_cpu & CPU_CAPABILITY_MMXEXT) )        {            id->ff_enc_c->dsp_mask |= FF_MM_MMXEXT;        }        if( !(i_cpu & CPU_CAPABILITY_3DNOW) )        {            id->ff_enc_c->dsp_mask |= FF_MM_3DNOW;        }        if( !(i_cpu & CPU_CAPABILITY_SSE) )        {            id->ff_enc_c->dsp_mask |= FF_MM_SSE;            id->ff_enc_c->dsp_mask |= FF_MM_SSE2;        }        id->ff_enc_c->sample_rate = p_fmt->audio.i_rate;        id->ff_enc_c->channels    = p_fmt->audio.i_channels;        id->ff_enc_c->bit_rate    = p_fmt->i_bitrate;        if( avcodec_open( id->ff_enc_c, id->ff_enc ) )        {            msg_Err( p_stream, "cannot open encoder" );            return NULL;        }        id->p_buffer_out = malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE * 2 );        id->p_samples = malloc( id->ff_enc_c->frame_size                                 * p_fmt->audio.i_channels * sizeof(int16_t) );        memset( id->p_samples, 0,                id->ff_enc_c->frame_size * p_fmt->audio.i_channels                 * sizeof(int16_t) );        for ( i = 0; i < MAX_AUDIO; i++ )        {            if ( p_sys->pp_audio_ids[i] == NULL )            {                p_sys->pp_audio_ids[i] = id;                break;            }        }        if ( i == MAX_AUDIO )        {            msg_Err( p_stream, "too many audio streams!" );            free( id );            return NULL;        }    }    else    {        msg_Dbg( p_stream, "do not know what to do when switching (fcc=`%4.4s')",                 (char*)&p_fmt->i_codec );    }    /* src format */    memcpy( &id->f_src, p_fmt, sizeof( es_format_t ) );    /* open output stream */    id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt );    if ( id->id == NULL )    {        free( id );        return NULL;    }    return id;}/***************************************************************************** * Del: Del an elementary stream *****************************************************************************/static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ){    sout_stream_sys_t   *p_sys = p_stream->p_sys;    if ( id->b_switcher_audio )    {        int i;        for ( i = 0; i < MAX_AUDIO; i++ )        {            if ( p_sys->pp_audio_ids[i] == id )            {                p_sys->pp_audio_ids[i] = NULL;                break;            }        }    }    if ( id->ff_enc )    {        avcodec_close( id->ff_enc_c );        av_free( id->ff_enc_c );        av_free( id->p_frame );        free( id->p_buffer_out );    }    if ( id->id )    {        p_sys->p_out->pf_del( p_sys->p_out, id->id );    }    free( id );    return VLC_SUCCESS;}/***************************************************************************** * Send: Process an input packet *****************************************************************************/static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,                 block_t *p_buffer ){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -