/***************************************************************************** * Open: probe the packetizer and return score *****************************************************************************/ 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_MP4V ) 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; memset( p_sys, 0, sizeof(decoder_sys_t) ); /* Misc init */ packetizer_Init( &p_sys->packetizer, p_mp4v_startcode, sizeof(p_mp4v_startcode), startcode_FindAnnexB, NULL, 0, 4, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_CODEC_MP4V; free(p_dec->fmt_out.p_extra); if( p_dec->fmt_in.i_extra ) { /* We have a vol */ p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.p_extra = xmalloc( p_dec->fmt_in.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); msg_Dbg( p_dec, "opening with vol size: %d", p_dec->fmt_in.i_extra ); ParseVOL( p_dec, &p_dec->fmt_out, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); } else { /* No vol, we'll have to look for one later on */ p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = 0; } /* Set callback */ p_dec->pf_packetize = Packetize; p_dec->pf_flush = PacketizeFlush; return VLC_SUCCESS; }
/***************************************************************************** * ParseMPEGBlock: Re-assemble fragments into a block containing a picture *****************************************************************************/ static block_t *ParseMPEGBlock( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic = NULL; if( p_frag->p_buffer[3] == 0xB0 || p_frag->p_buffer[3] == 0xB1 || p_frag->p_buffer[3] == 0xB2 ) { /* VOS and USERDATA */ #if 0 /* Remove VOS start/end code from the original stream */ block_Release( p_frag ); #else /* Append the block for now since ts/ps muxers rely on VOL * being present in the stream */ block_ChainLastAppend( &p_sys->pp_last, p_frag ); #endif return NULL; } if( p_frag->p_buffer[3] >= 0x20 && p_frag->p_buffer[3] <= 0x2f ) { /* Copy the complete VOL */ if( (size_t)p_dec->fmt_out.i_extra != p_frag->i_buffer ) { p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, p_frag->i_buffer ); p_dec->fmt_out.i_extra = p_frag->i_buffer; } memcpy( p_dec->fmt_out.p_extra, p_frag->p_buffer, p_frag->i_buffer ); ParseVOL( p_dec, &p_dec->fmt_out, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); #if 0 /* Remove from the original stream */ block_Release( p_frag ); #else /* Append the block for now since ts/ps muxers rely on VOL * being present in the stream */ block_ChainLastAppend( &p_sys->pp_last, p_frag ); #endif return NULL; } else { if( !p_dec->fmt_out.i_extra ) { msg_Warn( p_dec, "waiting for VOL" ); block_Release( p_frag ); return NULL; } /* Append the block */ block_ChainLastAppend( &p_sys->pp_last, p_frag ); } if( p_frag->p_buffer[3] == 0xb6 && ParseVOP( p_dec, p_frag ) == VLC_SUCCESS ) { /* We are dealing with a VOP */ p_pic = block_ChainGather( p_sys->p_frame ); p_pic->i_flags = p_sys->i_flags; p_pic->i_pts = p_sys->i_interpolated_pts; p_pic->i_dts = p_sys->i_interpolated_dts; if ( p_dec->fmt_out.video.i_cpb_buffer && p_dec->fmt_out.i_bitrate ) { mtime_t i_cpb_delay = p_sys->i_vbv_occupancy * INT64_C(1000000) / p_dec->fmt_out.i_bitrate; p_pic->i_delay = i_cpb_delay; } else p_pic->i_delay = DEFAULT_DELAY * 1000; /* Reset context */ p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; } return p_pic; }