Beispiel #1
0
/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_MPGV )
        return VLC_EGENERIC;

    es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_CODEC_MPGV );
    p_dec->fmt_out.i_original_fourcc = p_dec->fmt_in.i_original_fourcc;

    p_dec->pf_packetize = Packetize;
    p_dec->pf_get_cc = GetCc;

    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
    if( !p_dec->p_sys )
        return VLC_ENOMEM;
    memset( p_dec->p_sys, 0, sizeof( decoder_sys_t ) );

    /* Misc init */
    packetizer_Init( &p_sys->packetizer,
                     p_mp2v_startcode, sizeof(p_mp2v_startcode),
                     NULL, 0, 4,
                     PacketizeReset, PacketizeParse, PacketizeValidate, p_dec );

    p_sys->p_seq = NULL;
    p_sys->p_ext = NULL;
    p_sys->p_frame = NULL;
    p_sys->pp_last = &p_sys->p_frame;
    p_sys->b_frame_slice = false;

    p_sys->i_dts = p_sys->i_pts = VLC_TS_INVALID;

    p_sys->i_frame_rate = 1;
    p_sys->i_frame_rate_base = 1;
    p_sys->b_seq_progressive = true;
    p_sys->b_low_delay = true;
    p_sys->i_seq_old = 0;

    p_sys->i_temporal_ref = 0;
    p_sys->i_picture_type = 0;
    p_sys->i_picture_structure = 0x03; /* frame */
    p_sys->i_top_field_first = 0;
    p_sys->i_repeat_first_field = 0;
    p_sys->i_progressive_frame = 0;
    p_sys->b_inited = 0;

    p_sys->i_interpolated_dts = VLC_TS_INVALID;
    p_sys->i_last_ref_pts = VLC_TS_INVALID;
    p_sys->b_second_field = 0;

    p_sys->b_discontinuity = false;
    p_sys->b_sync_on_intra_frame = var_CreateGetBool( p_dec, "packetizer-mpegvideo-sync-iframe" );
    if( p_sys->b_sync_on_intra_frame )
        msg_Dbg( p_dec, "syncing on intra frame now" );

    p_sys->b_cc_reset = false;
    p_sys->i_cc_pts = 0;
    p_sys->i_cc_dts = 0;
    p_sys->i_cc_flags = 0;
    cc_Init( &p_sys->cc );

    return VLC_SUCCESS;
}
Beispiel #2
0
/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;
    uint32_t i_accel = 0;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_MPGV )
        return VLC_EGENERIC;

    /* Select onl recognized original format (standard mpeg video) */
    switch( p_dec->fmt_in.i_original_fourcc )
    {
    case VLC_FOURCC('m','p','g','1'):
    case VLC_FOURCC('m','p','g','2'):
    case VLC_FOURCC('m','p','g','v'):
    case VLC_FOURCC('P','I','M','1'):
    case VLC_FOURCC('h','d','v','2'):
        break;
    default:
        if( p_dec->fmt_in.i_original_fourcc )
            return VLC_EGENERIC;
        break;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL )
        return VLC_ENOMEM;

    /* Initialize the thread properties */
    p_sys->p_mpeg2dec = NULL;
    p_sys->p_synchro  = NULL;
    p_sys->p_info     = NULL;
    p_sys->i_current_pts  = 0;
    p_sys->i_previous_pts = 0;
    p_sys->i_current_dts  = 0;
    p_sys->i_previous_dts = 0;
    p_sys->b_garbage_pic = false;
    p_sys->b_slice_i  = false;
    p_sys->b_second_field = false;
    p_sys->b_skip     = false;
    p_sys->b_preroll = false;
    DpbInit( p_dec );

    p_sys->i_cc_pts = 0;
    p_sys->i_cc_dts = 0;
    p_sys->i_cc_flags = 0;
#if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0)
    p_dec->pf_get_cc = GetCc;
    cc_Init( &p_sys->cc );
#endif
    p_sys->p_gop_user_data = NULL;
    p_sys->i_gop_user_data = 0;

#if defined( __i386__ ) || defined( __x86_64__ )
    if( vlc_CPU() & CPU_CAPABILITY_MMX )
    {
        i_accel |= MPEG2_ACCEL_X86_MMX;
    }

    if( vlc_CPU() & CPU_CAPABILITY_3DNOW )
    {
        i_accel |= MPEG2_ACCEL_X86_3DNOW;
    }

    if( vlc_CPU() & CPU_CAPABILITY_MMXEXT )
    {
        i_accel |= MPEG2_ACCEL_X86_MMXEXT;
    }

#elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
    if( vlc_CPU() & CPU_CAPABILITY_ALTIVEC )
    {
        i_accel |= MPEG2_ACCEL_PPC_ALTIVEC;
    }

#else
    /* If we do not know this CPU, trust libmpeg2's feature detection */
    i_accel = MPEG2_ACCEL_DETECT;

#endif

    /* Set CPU acceleration features */
    mpeg2_accel( i_accel );

    /* Initialize decoder */
    p_sys->p_mpeg2dec = mpeg2_init();
    if( p_sys->p_mpeg2dec == NULL)
    {
        msg_Err( p_dec, "mpeg2_init() failed" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );

    p_dec->pf_decode_video = DecodeBlock;
    p_dec->fmt_out.i_cat = VIDEO_ES;
    p_dec->fmt_out.i_codec = 0;

    return VLC_SUCCESS;
}
Beispiel #3
0
/*****************************************************************************
 * Open: probe the packetizer and return score
 * When opening after demux, the packetizer is only loaded AFTER the decoder
 * That means that what you set in fmt_out is ignored by the decoder in this special case
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    decoder_t     *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;
    int i;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 )
        return VLC_EGENERIC;
    if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1') &&
        p_dec->fmt_in.i_extra < 7 )
        return VLC_EGENERIC;

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL )
    {
        return VLC_ENOMEM;
    }

    packetizer_Init( &p_sys->packetizer,
                     p_h264_startcode, sizeof(p_h264_startcode),
                     p_h264_startcode, 1, 5,
                     PacketizeReset, PacketizeParse, PacketizeValidate, p_dec );

    p_sys->b_slice = false;
    p_sys->p_frame = NULL;
    p_sys->b_frame_sps = false;
    p_sys->b_frame_pps = false;

    p_sys->b_header= false;
    p_sys->b_sps   = false;
    p_sys->b_pps   = false;
    for( i = 0; i < SPS_MAX; i++ )
        p_sys->pp_sps[i] = NULL;
    for( i = 0; i < PPS_MAX; i++ )
        p_sys->pp_pps[i] = NULL;
    p_sys->i_recovery_frames = -1;

    p_sys->slice.i_nal_type = -1;
    p_sys->slice.i_nal_ref_idc = -1;
    p_sys->slice.i_idr_pic_id = -1;
    p_sys->slice.i_frame_num = -1;
    p_sys->slice.i_frame_type = 0;
    p_sys->slice.i_pic_parameter_set_id = -1;
    p_sys->slice.i_field_pic_flag = 0;
    p_sys->slice.i_bottom_field_flag = -1;
    p_sys->slice.i_pic_order_cnt_lsb = -1;
    p_sys->slice.i_delta_pic_order_cnt_bottom = -1;

    p_sys->i_frame_dts = VLC_TS_INVALID;
    p_sys->i_frame_pts = VLC_TS_INVALID;

    /* Setup properties */
    es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
    p_dec->fmt_out.i_codec = VLC_CODEC_H264;

    if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
    {
        /* This type of stream is produced by mp4 and matroska
         * when we want to store it in another streamformat, you need to convert
         * The fmt_in.p_extra should ALWAYS contain the avcC
         * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */
        uint8_t *p = &((uint8_t*)p_dec->fmt_in.p_extra)[4];
        int i_sps, i_pps;
        bool b_dummy;
        int i;

        /* Parse avcC */
        p_sys->i_avcC_length_size = 1 + ((*p++)&0x03);

        /* Read SPS */
        i_sps = (*p++)&0x1f;
        for( i = 0; i < i_sps; i++ )
        {
            uint16_t i_length = GetWBE( p ); p += 2;
            if( i_length >
                (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p )
            {
                return VLC_EGENERIC;
            }
            block_t *p_sps = CreateAnnexbNAL( p_dec, p, i_length );
            if( !p_sps )
                return VLC_EGENERIC;
            ParseNALBlock( p_dec, &b_dummy, p_sps );
            p += i_length;
        }
        /* Read PPS */
        i_pps = *p++;
        for( i = 0; i < i_pps; i++ )
        {
            uint16_t i_length = GetWBE( p ); p += 2;
            if( i_length >
                (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p )
            {
                return VLC_EGENERIC;
            }
            block_t *p_pps = CreateAnnexbNAL( p_dec, p, i_length );
            if( !p_pps )
                return VLC_EGENERIC;
            ParseNALBlock( p_dec, &b_dummy, p_pps );
            p += i_length;
        }
        msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d",
                 p_sys->i_avcC_length_size, i_sps, i_pps );

        if( !p_sys->b_sps || !p_sys->b_pps )
            return VLC_EGENERIC;

        /* FIXME: FFMPEG isn't happy at all if you leave this */
        if( p_dec->fmt_out.i_extra > 0 )
            free( p_dec->fmt_out.p_extra );
        p_dec->fmt_out.i_extra = 0;
        p_dec->fmt_out.p_extra = NULL;

        /* Set the new extradata */
        for( i = 0; i < SPS_MAX; i++ )
        {
            if( p_sys->pp_sps[i] )
                p_dec->fmt_out.i_extra += p_sys->pp_sps[i]->i_buffer;
        }
        for( i = 0; i < PPS_MAX; i++ )
        {
            if( p_sys->pp_pps[i] )
                p_dec->fmt_out.i_extra += p_sys->pp_pps[i]->i_buffer;
        }
        p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra );
        if( p_dec->fmt_out.p_extra )
        {
            uint8_t *p_dst = p_dec->fmt_out.p_extra;

            for( i = 0; i < SPS_MAX; i++ )
            {
                if( p_sys->pp_sps[i] )
                {
                    memcpy( p_dst, p_sys->pp_sps[i]->p_buffer, p_sys->pp_sps[i]->i_buffer );
                    p_dst += p_sys->pp_sps[i]->i_buffer;
                }
            }
            for( i = 0; i < PPS_MAX; i++ )
            {
                if( p_sys->pp_pps[i] )
                {
                    memcpy( p_dst, p_sys->pp_pps[i]->p_buffer, p_sys->pp_pps[i]->i_buffer );
                    p_dst += p_sys->pp_pps[i]->i_buffer;
                }
            }
            p_sys->b_header = true;
        }
        else
        {
            p_dec->fmt_out.i_extra = 0;
        }

        /* Set callback */
        p_dec->pf_packetize = PacketizeAVC1;
        /* TODO CC ? */
    }
    else
    {
        /* This type of stream contains data with 3 of 4 byte startcodes
         * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes
         * The fmt_out.p_extra should be the same */

        /* Set callback */
        p_dec->pf_packetize = Packetize;
        p_dec->pf_get_cc = GetCc;

        /* */
        p_sys->i_cc_pts = VLC_TS_INVALID;
        p_sys->i_cc_dts = VLC_TS_INVALID;
        p_sys->i_cc_flags = 0;
        cc_Init( &p_sys->cc );
        cc_Init( &p_sys->cc_next );

        /* */
        if( p_dec->fmt_in.i_extra > 0 )
            packetizer_Header( &p_sys->packetizer,
                               p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
    }

    return VLC_SUCCESS;
}