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

📄 ts.c

📁 这不是一个完整的工程
💻 C
📖 第 1 页 / 共 4 页
字号:
        default:            return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );   }}/***************************************************************************** * AddStream: called for each stream addition *****************************************************************************/static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ){    sout_mux_sys_t      *p_sys = p_mux->p_sys;    ts_stream_t         *p_stream;    msg_Dbg( p_mux, "adding input codec=%4.4s", (char*)&p_input->p_fmt->i_fourcc );    p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );    /* Init this new stream */    p_stream->i_pid = AllocatePID( p_sys );    p_stream->i_continuity_counter    = 0;    p_stream->i_decoder_specific_info = 0;    p_stream->p_decoder_specific_info = NULL;    /* All others fields depand on codec */    switch( p_input->p_fmt->i_cat )    {        case VIDEO_ES:            switch( p_input->p_fmt->i_fourcc )            {                case VLC_FOURCC( 'm', 'p','g', 'v' ):                    /* TODO: do we need to check MPEG-I/II ? */                    p_stream->i_stream_type = 0x02;                    p_stream->i_stream_id = p_sys->i_stream_id_mpgv;                    p_sys->i_stream_id_mpgv++;                    break;                case VLC_FOURCC( 'm', 'p','4', 'v' ):                    p_stream->i_stream_type = 0x10;                    p_stream->i_stream_id = 0xfa;                    p_sys->i_mpeg4_streams++;                    p_stream->i_es_id = p_stream->i_pid;                    break;                /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */                /* I didn't want to do that :P */                case VLC_FOURCC( 'H', '2', '6', '3' ):                case VLC_FOURCC( 'I', '2', '6', '3' ):                case VLC_FOURCC( 'W', 'M', 'V', '2' ):                case VLC_FOURCC( 'W', 'M', 'V', '1' ):                case VLC_FOURCC( 'D', 'I', 'V', '3' ):                case VLC_FOURCC( 'D', 'I', 'V', '2' ):                case VLC_FOURCC( 'D', 'I', 'V', '1' ):                case VLC_FOURCC( 'M', 'J', 'P', 'G' ):                    p_stream->i_stream_type = 0xa0; // private                    p_stream->i_stream_id = 0xa0;   // beurk                    p_stream->i_bih_codec  = p_input->p_fmt->i_fourcc;                    p_stream->i_bih_width  = p_input->p_fmt->i_width;                    p_stream->i_bih_height = p_input->p_fmt->i_height;                    break;                default:                    free( p_stream );                    return VLC_EGENERIC;            }            p_sys->i_video_bound++;            break;        case AUDIO_ES:            switch( p_input->p_fmt->i_fourcc )            {                case VLC_FOURCC( 'm', 'p','g', 'a' ):                    p_stream->i_stream_type = p_input->p_fmt->i_sample_rate >= 32000 ? 0x03 : 0x04;                    p_stream->i_stream_id = p_sys->i_stream_id_mpga;                    p_sys->i_stream_id_mpga++;                    break;                case VLC_FOURCC( 'a', '5','2', ' ' ):                    p_stream->i_stream_type = 0x81;                    p_stream->i_stream_id = p_sys->i_stream_id_a52;                    p_sys->i_stream_id_a52++;                    break;                case VLC_FOURCC( 'm', 'p','4', 'a' ):                    p_stream->i_stream_type = 0x11;                    p_stream->i_stream_id = 0xfa;                    p_sys->i_mpeg4_streams++;                    p_stream->i_es_id = p_stream->i_pid;                    break;                default:                    free( p_stream );                    return VLC_EGENERIC;            }            p_sys->i_audio_bound++;            break;        case SPU_ES:            switch( p_input->p_fmt->i_fourcc )            {                case VLC_FOURCC( 's', 'p','u', ' ' ):                    p_stream->i_stream_type = 0x82;                    p_stream->i_stream_id = 0x82;                    break;                default:                    free( p_stream );                    return VLC_EGENERIC;            }            break;        default:            free( p_stream );            return VLC_EGENERIC;    }    /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */    p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra_data;    if( p_stream->i_decoder_specific_info > 0 )    {        p_stream->p_decoder_specific_info =            malloc( p_stream->i_decoder_specific_info );        memcpy( p_stream->p_decoder_specific_info,                p_input->p_fmt->p_extra_data,                p_input->p_fmt->i_extra_data );    }    /* Init chain for TS building */    BufferChainInit( &p_stream->chain_ts );    /* We only change PMT version (PAT isn't changed) */    p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;    /* Update pcr_pid */    if( p_input->p_fmt->i_cat != SPU_ES &&        ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )    {        sout_buffer_t *p_data;        if( p_sys->p_pcr_input )        {            /* There was already a PCR stream, so clean context */            ts_stream_t   *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;            while( ( p_data = BufferChainGet( &p_pcr_stream->chain_ts ) ) )            {                sout_BufferDelete( p_mux->p_sout, p_data );            }        }        p_sys->i_pcr_pid   = p_stream->i_pid;        p_sys->p_pcr_input = p_input;        /* Empty TS buffer (avoid broken data/problems with pcr stream changement ) */        while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )        {            sout_BufferDelete( p_mux->p_sout, p_data );        }    }    return VLC_SUCCESS;}/***************************************************************************** * DelStream: called before a stream deletion *****************************************************************************/static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input ){    sout_mux_sys_t  *p_sys = p_mux->p_sys;    ts_stream_t     *p_stream;    sout_buffer_t   *p_data;    msg_Dbg( p_mux, "removing input" );    p_stream = (ts_stream_t*)p_input->p_sys;    if( p_sys->i_pcr_pid == p_stream->i_pid )    {        int i;        /* Find a new pcr stream (Prefer Video Stream) */        p_sys->i_pcr_pid = 0x1fff;        p_sys->p_pcr_input = NULL;        for( i = 0; i < p_mux->i_nb_inputs; i++ )        {            if( p_mux->pp_inputs[i] == p_input )            {                continue;            }            if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )            {                p_sys->i_pcr_pid  =                    ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;                p_sys->p_pcr_input= p_mux->pp_inputs[i];                break;            }            else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&                     p_sys->i_pcr_pid == 0x1fff )            {                p_sys->i_pcr_pid  =                    ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;                p_sys->p_pcr_input= p_mux->pp_inputs[i];            }        }        if( p_sys->p_pcr_input )        {            /* Empty TS buffer */            while( ( p_data = BufferChainGet( &((ts_stream_t*)p_sys->p_pcr_input->p_sys)->chain_ts ) ) )            {                sout_BufferDelete( p_mux->p_sout, p_data );            }        }    }    /* Empty all data in chain_ts */    while( ( p_data = BufferChainGet( &p_stream->chain_ts ) ) )    {        sout_BufferDelete( p_mux->p_sout, p_data );    }    if( p_stream->p_decoder_specific_info )    {        free( p_stream->p_decoder_specific_info );    }    if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )    {        p_sys->i_mpeg4_streams--;    }    free( p_stream );    /* We only change PMT version (PAT isn't changed) */    p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;    /*Empty TS buffer (avoid broken data/problems with pcr stream changement) */    while( ( p_data = BufferChainGet( &p_sys->chain_ts ) ) )    {        sout_BufferDelete( p_mux->p_sout, p_data );    }    return VLC_SUCCESS;}/***************************************************************************** * Mux: Call each time there is new data for at least one stream ***************************************************************************** * *****************************************************************************/static int Mux( sout_mux_t *p_mux ){    sout_mux_sys_t  *p_sys = p_mux->p_sys;    sout_input_t    *p_pcr_input = p_sys->p_pcr_input;    ts_stream_t     *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;    if( p_sys->i_pcr_pid == 0x1fff )    {        msg_Dbg( p_mux, "waiting PCR streams" );        msleep( 1000 );        return VLC_SUCCESS;    }    for( ;; )    {        ts_stream_t   *p_stream = NULL;        sout_buffer_t *p_data;        int     i_stream, i;        mtime_t i_dts;        /* fill ts packets for pcr XXX before GetPAT/GetPMT */        if( p_pcr_stream->chain_ts.p_first == NULL && TSFill( p_mux, p_pcr_input ) )        {            /* We need more data */            return VLC_SUCCESS;        }        if( p_sys->chain_ts.p_first == NULL  )        {            /* Every pcr packet send PAT/PMT */            GetPAT( p_mux, &p_sys->chain_ts);            GetPMT( p_mux, &p_sys->chain_ts );        }        /* search stream with lowest dts */        for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )        {            p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;            if( p_stream->chain_ts.p_first == NULL )            {                if( TSFill( p_mux, p_mux->pp_inputs[i] ) )                {                    /* We need more data */                    return VLC_SUCCESS;                }                if( p_stream->chain_ts.p_first == NULL )                {                    continue; /* SPU_ES */                }            }            if( i_stream == -1 ||                p_stream->chain_ts.p_first->i_dts < i_dts )            {                i_stream = i;                i_dts = p_stream->chain_ts.p_first->i_dts;            }        }        p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;        p_data = BufferChainGet( &p_stream->chain_ts );        BufferChainAppend( &p_sys->chain_ts, p_data );        if( p_stream->i_pid == p_pcr_stream->i_pid && p_stream->chain_ts.p_first == NULL )        {            sout_buffer_t *p_ts = p_sys->chain_ts.p_first;            /* We have consume all TS packets from the PCR stream */            if( p_sys->i_length > p_sys->i_pcr_delay )            {                /* Send TS data if last PCR was i_pcr_delay ago */                if( p_sys->i_bitrate_min > 0 ||                    p_sys->i_bitrate_max > 0 )                {                    TSSetConstraints( p_mux, &p_sys->chain_ts, p_sys->i_length,                                      p_sys->i_bitrate_min, p_sys->i_bitrate_max );                }                /* Send all data */                TSSetDate( &p_sys->chain_ts,                           p_sys->i_dts + 3  * p_sys->i_pcr_delay / 2,    /* latency is equal to i_pcr_delay, 3/2 is for security */                           p_sys->i_length );                sout_AccessOutWrite( p_mux->p_access, p_ts );                /* Reset the ts chain */                BufferChainInit( &p_sys->chain_ts );                p_sys->i_length = 0;            }        }    }    return VLC_SUCCESS;}/***************************************************************************** * * *****************************************************************************/static int TSFill( sout_mux_t *p_mux, sout_input_t *p_input ){    sout_mux_sys_t  *p_sys = p_mux->p_sys;    ts_stream_t     *p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;    ts_stream_t     *p_stream = (ts_stream_t*)p_input->p_sys;    mtime_t         i_dts, i_length;    sout_buffer_t   *p_data;    vlc_bool_t      b_pcr = VLC_FALSE;    vlc_bool_t      b_pcr_soft = VLC_FALSE;    for( ;; )    {        if( p_input->p_fifo->i_depth <= 0 )        {            if( p_input->p_fmt->i_cat == AUDIO_ES ||                p_input->p_fmt->i_cat == VIDEO_ES )            {                /* We need more data */                return VLC_EGENERIC;            }            else            {                return VLC_SUCCESS;            }        }        p_data = sout_FifoGet( p_input->p_fifo );        i_dts    = p_data->i_dts;        i_length = p_data->i_length;

⌨️ 快捷键说明

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