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

📄 decoder.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
            VLC_FOURCC('c', 'c', '1', ' '),            VLC_FOURCC('c', 'c', '2', ' '),            VLC_FOURCC('c', 'c', '3', ' '),            VLC_FOURCC('c', 'c', '4', ' '),        };        decoder_t *p_cc;        es_format_t fmt;        es_format_Init( &fmt, SPU_ES, fcc[i_channel] );        p_cc = CreateDecoder( p_owner->p_input, &fmt, VLC_OBJECT_DECODER );        if( !p_cc )        {            msg_Err( p_dec, "could not create decoder" );            intf_UserFatal( p_dec, false, _("Streaming / Transcoding failed"),                            _("VLC could not open the decoder module.") );            return VLC_EGENERIC;        }        else if( !p_cc->p_module )        {            DecoderUnsupportedCodec( p_dec, fcc[i_channel] );            DeleteDecoder( p_cc );            vlc_object_release( p_cc );            return VLC_EGENERIC;        }        vlc_mutex_lock( &p_owner->lock_cc );        p_dec->p_owner->pp_cc[i_channel] = p_cc;        vlc_mutex_unlock( &p_owner->lock_cc );    }    else    {        decoder_t *p_cc;        vlc_mutex_lock( &p_owner->lock_cc );        p_cc = p_dec->p_owner->pp_cc[i_channel];        p_dec->p_owner->pp_cc[i_channel] = NULL;        vlc_mutex_unlock( &p_dec->p_owner->lock_cc );        if( p_cc )        {            vlc_object_kill( p_cc );            module_Unneed( p_cc, p_cc->p_module );            DeleteDecoder( p_cc );            vlc_object_release( p_cc );        }    }    return VLC_SUCCESS;}int input_DecoderGetCcState( decoder_t *p_dec, bool *pb_decode, int i_channel ){    decoder_owner_sys_t *p_owner = p_dec->p_owner;    *pb_decode = false;    if( i_channel < 0 || i_channel >= 4 || !p_owner->pb_cc_present[i_channel] )        return VLC_EGENERIC;    vlc_mutex_lock( &p_owner->lock_cc );    *pb_decode = p_dec->p_owner->pp_cc[i_channel] != NULL;    vlc_mutex_unlock( &p_dec->p_owner->lock_cc );    return VLC_EGENERIC;}/** * Create a decoder object * * \param p_input the input thread * \param p_es the es descriptor * \param i_object_type Object type as define in include/vlc_objects.h * \return the decoder object */static decoder_t * CreateDecoder( input_thread_t *p_input,                                  es_format_t *fmt, int i_object_type ){    decoder_t *p_dec;    decoder_owner_sys_t *p_owner;    int i;    p_dec = vlc_object_create( p_input, i_object_type );    if( p_dec == NULL )        return NULL;    p_dec->pf_decode_audio = 0;    p_dec->pf_decode_video = 0;    p_dec->pf_decode_sub = 0;    p_dec->pf_get_cc = 0;    p_dec->pf_packetize = 0;    /* Initialize the decoder fifo */    p_dec->p_module = NULL;    memset( &null_es_format, 0, sizeof(es_format_t) );    es_format_Copy( &p_dec->fmt_in, fmt );    es_format_Copy( &p_dec->fmt_out, &null_es_format );    /* Allocate our private structure for the decoder */    p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) );    if( p_dec->p_owner == NULL )    {        vlc_object_release( p_dec );        return NULL;    }    p_dec->p_owner->b_own_thread = true;    p_dec->p_owner->i_preroll_end = -1;    p_dec->p_owner->p_input = p_input;    p_dec->p_owner->p_aout = NULL;    p_dec->p_owner->p_aout_input = NULL;    p_dec->p_owner->p_vout = NULL;    p_dec->p_owner->p_spu_vout = NULL;    p_dec->p_owner->i_spu_channel = 0;    p_dec->p_owner->p_sout = p_input->p->p_sout;    p_dec->p_owner->p_sout_input = NULL;    p_dec->p_owner->p_packetizer = NULL;    /* decoder fifo */    if( ( p_dec->p_owner->p_fifo = block_FifoNew() ) == NULL )    {        free( p_dec->p_owner );        vlc_object_release( p_dec );        return NULL;    }    /* Set buffers allocation callbacks for the decoders */    p_dec->pf_aout_buffer_new = aout_new_buffer;    p_dec->pf_aout_buffer_del = aout_del_buffer;    p_dec->pf_vout_buffer_new = vout_new_buffer;    p_dec->pf_vout_buffer_del = vout_del_buffer;    p_dec->pf_picture_link    = vout_link_picture;    p_dec->pf_picture_unlink  = vout_unlink_picture;    p_dec->pf_spu_buffer_new  = spu_new_buffer;    p_dec->pf_spu_buffer_del  = spu_del_buffer;    vlc_object_attach( p_dec, p_input );    /* Find a suitable decoder/packetizer module */    if( i_object_type == VLC_OBJECT_DECODER )        p_dec->p_module = module_Need( p_dec, "decoder", "$codec", 0 );    else        p_dec->p_module = module_Need( p_dec, "packetizer", "$packetizer", 0 );    /* Check if decoder requires already packetized data */    if( i_object_type == VLC_OBJECT_DECODER &&        p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized )    {        p_dec->p_owner->p_packetizer =            vlc_object_create( p_input, VLC_OBJECT_PACKETIZER );        if( p_dec->p_owner->p_packetizer )        {            es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_in,                            &p_dec->fmt_in );            es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_out,                            &null_es_format );            vlc_object_attach( p_dec->p_owner->p_packetizer, p_input );            p_dec->p_owner->p_packetizer->p_module =                module_Need( p_dec->p_owner->p_packetizer,                             "packetizer", "$packetizer", 0 );            if( !p_dec->p_owner->p_packetizer->p_module )            {                es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in );                vlc_object_detach( p_dec->p_owner->p_packetizer );                vlc_object_release( p_dec->p_owner->p_packetizer );            }        }    }    /* Copy ourself the input replay gain */    if( fmt->i_cat == AUDIO_ES )    {        for( i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )        {            if( !p_dec->fmt_out.audio_replay_gain.pb_peak[i] )            {                p_dec->fmt_out.audio_replay_gain.pb_peak[i] = fmt->audio_replay_gain.pb_peak[i];                p_dec->fmt_out.audio_replay_gain.pf_peak[i] = fmt->audio_replay_gain.pf_peak[i];            }            if( !p_dec->fmt_out.audio_replay_gain.pb_gain[i] )            {                p_dec->fmt_out.audio_replay_gain.pb_gain[i] = fmt->audio_replay_gain.pb_gain[i];                p_dec->fmt_out.audio_replay_gain.pf_gain[i] = fmt->audio_replay_gain.pf_gain[i];            }        }    }    /* */    p_owner->b_cc_supported = false;    if( i_object_type == VLC_OBJECT_DECODER )    {        if( p_owner->p_packetizer && p_owner->p_packetizer->pf_get_cc )            p_owner->b_cc_supported = true;        if( p_dec->pf_get_cc )            p_owner->b_cc_supported = true;    }    vlc_mutex_init( &p_owner->lock_cc );    for( i = 0; i < 4; i++ )    {        p_owner->pb_cc_present[i] = false;        p_owner->pp_cc[i] = NULL;    }    return p_dec;}/** * The decoding main loop * * \param p_dec the decoder * \return 0 */static void* DecoderThread( vlc_object_t *p_this ){    decoder_t * p_dec = (decoder_t *)p_this;    block_t *p_block;    /* The decoder's main loop */    while( !p_dec->b_die && !p_dec->b_error )    {        if( ( p_block = block_FifoGet( p_dec->p_owner->p_fifo ) ) == NULL )        {            p_dec->b_error = 1;            break;        }        if( DecoderDecode( p_dec, p_block ) != VLC_SUCCESS )        {            break;        }    }    while( !p_dec->b_die )    {        /* Trash all received PES packets */        p_block = block_FifoGet( p_dec->p_owner->p_fifo );        if( p_block ) block_Release( p_block );    }    /* We do it here because of the dll loader that wants close() in the     * same thread than open()/decode() */    module_Unneed( p_dec, p_dec->p_module );    return 0;}static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p ){    if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )        *pi_preroll = INT64_MAX;    else if( p->i_pts > 0 )        *pi_preroll = __MIN( *pi_preroll, p->i_pts );    else if( p->i_dts > 0 )        *pi_preroll = __MIN( *pi_preroll, p->i_dts );}static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ){    input_thread_t  *p_input = p_dec->p_owner->p_input;    const int       i_rate = p_block->i_rate;    aout_buffer_t   *p_aout_buf;    while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )    {        aout_instance_t *p_aout = p_dec->p_owner->p_aout;        aout_input_t    *p_aout_input = p_dec->p_owner->p_aout_input;        if( p_dec->b_die )        {            /* It prevent freezing VLC in case of broken decoder */            aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf );            if( p_block )                block_Release( p_block );            break;        }        vlc_mutex_lock( &p_input->p->counters.counters_lock );        stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_audio, 1, NULL );        vlc_mutex_unlock( &p_input->p->counters.counters_lock );        if( p_aout_buf->start_date < p_dec->p_owner->i_preroll_end )        {            aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf );            continue;        }        if( p_dec->p_owner->i_preroll_end > 0 )        {            /* FIXME TODO flush audio output (don't know how to do that) */            msg_Dbg( p_dec, "End of audio preroll" );            p_dec->p_owner->i_preroll_end = -1;        }        aout_DecPlay( p_aout, p_aout_input, p_aout_buf, i_rate );    }}static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc ){    block_t *p_cc;    bool pb_present[4];    int i;    int i_cc_decoder;    assert( p_dec_cc->pf_get_cc != NULL );    /* Do not try retreiving CC if not wanted (sout) or cannot be retreived */    if( !p_dec->p_owner->b_cc_supported )        return;    p_cc = p_dec_cc->pf_get_cc( p_dec_cc, pb_present );    if( !p_cc )        return;    vlc_mutex_lock( &p_dec->p_owner->lock_cc );    for( i = 0, i_cc_decoder = 0; i < 4; i++ )    {        p_dec->p_owner->pb_cc_present[i] |= pb_present[i];        if( p_dec->p_owner->pp_cc[i] )            i_cc_decoder++;    }    for( i = 0; i < 4; i++ )    {        if( !p_dec->p_owner->pp_cc[i] )            continue;        if( i_cc_decoder > 1 )            DecoderDecode( p_dec->p_owner->pp_cc[i], block_Duplicate( p_cc ) );        else            DecoderDecode( p_dec->p_owner->pp_cc[i], p_cc );        i_cc_decoder--;    }    vlc_mutex_unlock( &p_dec->p_owner->lock_cc );}static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic ){    vlc_mutex_lock( &p_vout->picture_lock );    if( p_pic->i_status == READY_PICTURE )    {        /* Grr cannot destroy ready picture by myself so be sure vout won't like it */        p_pic->date = 1;    }    else if( p_pic->i_refcount > 0 )    {        p_pic->i_status = DISPLAYED_PICTURE;    }    else    {        p_pic->i_status = DESTROYED_PICTURE;        p_vout->i_heap_size--;    }    vlc_mutex_unlock( &p_vout->picture_lock );}static void VoutFlushPicture( vout_thread_t *p_vout ){    int i;    vlc_mutex_lock( &p_vout->picture_lock );    for( i = 0; i < p_vout->render.i_pictures; i++ )    {        picture_t *p_pic = p_vout->render.pp_picture[i];        if( p_pic->i_status == READY_PICTURE ||            p_pic->i_status == DISPLAYED_PICTURE )        {            /* We cannot change picture status if it is in READY_PICTURE state,             * Just make sure they won't be displayed */            p_pic->date = 1;        }    }    vlc_mutex_unlock( &p_vout->picture_lock );}

⌨️ 快捷键说明

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