static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block ) { decoder_t *p_dec = p_private; /* Check if we have a picture start code */ *pb_ts_used = p_block->p_buffer[3] == 0x00; return ParseMPEGBlock( p_dec, p_block ); }
static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block ) { decoder_t *p_dec = p_private; const mtime_t i_dts = p_block->i_dts; const mtime_t i_pts = p_block->i_pts; block_t *p_au = ParseMPEGBlock( p_dec, p_block ); *pb_ts_used = p_au && p_au->i_dts == i_dts && p_au->i_pts == i_pts; return p_au; }
/***************************************************************************** * Packetize: *****************************************************************************/ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic; if( pp_block == NULL || *pp_block == NULL ) { return NULL; } if( (*pp_block)->i_flags & BLOCK_FLAG_DISCONTINUITY ) { p_sys->i_state = STATE_NOSYNC; if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame ); p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; p_sys->b_frame_slice = VLC_FALSE; block_Release( *pp_block ); return NULL; } block_BytestreamPush( &p_sys->bytestream, *pp_block ); while( 1 ) { switch( p_sys->i_state ) { case STATE_NOSYNC: if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS ) { p_sys->i_state = STATE_NEXT_SYNC; } if( p_sys->i_offset ) { block_SkipBytes( &p_sys->bytestream, p_sys->i_offset ); p_sys->i_offset = 0; block_BytestreamFlush( &p_sys->bytestream ); } if( p_sys->i_state != STATE_NEXT_SYNC ) { /* Need more data */ return NULL; } p_sys->i_offset = 1; /* To find next startcode */ case STATE_NEXT_SYNC: /* TODO: If p_block == NULL, flush the buffer without checking the * next sync word */ /* Find the next startcode */ if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS ) { /* Need more data */ return NULL; } /* Get the new fragment and set the pts/dts */ p_pic = block_New( p_dec, p_sys->i_offset ); block_BytestreamFlush( &p_sys->bytestream ); p_pic->i_pts = p_sys->bytestream.p_block->i_pts; p_pic->i_dts = p_sys->bytestream.p_block->i_dts; block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, p_pic->i_buffer ); /* don't reuse the same timestamps several times */ if( p_pic->i_buffer >= 4 && p_pic->p_buffer[3] == 0x00 ) { /* We have a picture start code */ p_sys->bytestream.p_block->i_pts = 0; p_sys->bytestream.p_block->i_dts = 0; } p_sys->i_offset = 0; /* Get picture if any */ if( !( p_pic = ParseMPEGBlock( p_dec, p_pic ) ) ) { p_sys->i_state = STATE_NOSYNC; break; } /* We've just started the stream, wait for the first PTS. * We discard here so we can still get the sequence header. */ if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 && p_sys->i_interpolated_dts <= 0 ) { msg_Dbg( p_dec, "need a starting pts/dts" ); p_sys->i_state = STATE_NOSYNC; block_Release( p_pic ); break; } /* When starting the stream we can have the first frame with * a null DTS (i_interpolated_pts is initialized to 0) */ if( !p_pic->i_dts ) p_pic->i_dts = p_pic->i_pts; /* So p_block doesn't get re-added several times */ *pp_block = block_BytestreamPop( &p_sys->bytestream ); p_sys->i_state = STATE_NOSYNC; return p_pic; } } }