packetizer_helper.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef _PACKETIZER_H
00025 #define _PACKETIZER_H 1
00026
00027 #include <vlc_block.h>
00028
00029 enum
00030 {
00031 STATE_NOSYNC,
00032 STATE_NEXT_SYNC
00033 };
00034
00035 typedef void (*packetizer_reset_t)( void *p_private, bool b_broken );
00036 typedef block_t *(*packetizer_parse_t)( void *p_private, bool *pb_ts_used, block_t * );
00037 typedef int (*packetizer_validate_t)( void *p_private, block_t * );
00038
00039 typedef struct
00040 {
00041 int i_state;
00042 block_bytestream_t bytestream;
00043 size_t i_offset;
00044 bool b_flushing;
00045
00046 int i_startcode;
00047 const uint8_t *p_startcode;
00048
00049 int i_au_prepend;
00050 const uint8_t *p_au_prepend;
00051
00052 unsigned i_au_min_size;
00053
00054 void *p_private;
00055 packetizer_reset_t pf_reset;
00056 packetizer_parse_t pf_parse;
00057 packetizer_validate_t pf_validate;
00058
00059 } packetizer_t;
00060
00061 static inline void packetizer_Init( packetizer_t *p_pack,
00062 const uint8_t *p_startcode, int i_startcode,
00063 const uint8_t *p_au_prepend, int i_au_prepend,
00064 unsigned i_au_min_size,
00065 packetizer_reset_t pf_reset,
00066 packetizer_parse_t pf_parse,
00067 packetizer_validate_t pf_validate,
00068 void *p_private )
00069 {
00070 p_pack->i_state = STATE_NOSYNC;
00071 p_pack->bytestream = block_BytestreamInit();
00072 p_pack->i_offset = 0;
00073 p_pack->b_flushing = false;
00074
00075 p_pack->i_au_prepend = i_au_prepend;
00076 p_pack->p_au_prepend = p_au_prepend;
00077 p_pack->i_au_min_size = i_au_min_size;
00078
00079 p_pack->i_startcode = i_startcode;
00080 p_pack->p_startcode = p_startcode;
00081 p_pack->pf_reset = pf_reset;
00082 p_pack->pf_parse = pf_parse;
00083 p_pack->pf_validate = pf_validate;
00084 p_pack->p_private = p_private;
00085 }
00086
00087 static inline void packetizer_Clean( packetizer_t *p_pack )
00088 {
00089 block_BytestreamRelease( &p_pack->bytestream );
00090 }
00091
00092 static inline block_t *packetizer_Packetize( packetizer_t *p_pack, block_t **pp_block )
00093 {
00094 if( !pp_block || !*pp_block )
00095 return NULL;
00096
00097 if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
00098 {
00099 const bool b_broken = ( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED ) != 0;
00100 if( b_broken )
00101 {
00102 p_pack->i_state = STATE_NOSYNC;
00103 block_BytestreamEmpty( &p_pack->bytestream );
00104 p_pack->i_offset = 0;
00105 }
00106 p_pack->pf_reset( p_pack->p_private, b_broken );
00107
00108 block_Release( *pp_block );
00109 return NULL;
00110 }
00111
00112 block_BytestreamPush( &p_pack->bytestream, *pp_block );
00113
00114 for( ;; )
00115 {
00116 bool b_used_ts;
00117 block_t *p_pic;
00118
00119 switch( p_pack->i_state )
00120 {
00121 case STATE_NOSYNC:
00122
00123 if( !block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
00124 p_pack->p_startcode, p_pack->i_startcode ) )
00125 p_pack->i_state = STATE_NEXT_SYNC;
00126
00127 if( p_pack->i_offset )
00128 {
00129 block_SkipBytes( &p_pack->bytestream, p_pack->i_offset );
00130 p_pack->i_offset = 0;
00131 block_BytestreamFlush( &p_pack->bytestream );
00132 }
00133
00134 if( p_pack->i_state != STATE_NEXT_SYNC )
00135 return NULL;
00136
00137 p_pack->i_offset = 1;
00138
00139 case STATE_NEXT_SYNC:
00140
00141 if( block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
00142 p_pack->p_startcode, p_pack->i_startcode ) )
00143 {
00144 if( !p_pack->b_flushing || !p_pack->bytestream.p_chain )
00145 return NULL;
00146
00147
00148
00149 block_ChainProperties( p_pack->bytestream.p_chain,
00150 NULL, &p_pack->i_offset, NULL );
00151 p_pack->i_offset -= p_pack->bytestream .i_offset;
00152
00153 if( p_pack->i_offset <= (size_t)p_pack->i_startcode )
00154 return NULL;
00155 }
00156
00157 block_BytestreamFlush( &p_pack->bytestream );
00158
00159
00160 block_t *p_block_bytestream = p_pack->bytestream.p_block;
00161
00162 p_pic = block_New( p_dec, p_pack->i_offset + p_pack->i_au_prepend );
00163 p_pic->i_pts = p_block_bytestream->i_pts;
00164 p_pic->i_dts = p_block_bytestream->i_dts;
00165
00166 block_GetBytes( &p_pack->bytestream, &p_pic->p_buffer[p_pack->i_au_prepend],
00167 p_pic->i_buffer - p_pack->i_au_prepend );
00168 if( p_pack->i_au_prepend > 0 )
00169 memcpy( p_pic->p_buffer, p_pack->p_au_prepend, p_pack->i_au_prepend );
00170
00171 p_pack->i_offset = 0;
00172
00173
00174 if( p_pic->i_buffer < p_pack->i_au_min_size )
00175 {
00176 block_Release( p_pic );
00177 p_pic = NULL;
00178 }
00179 else
00180 {
00181 p_pic = p_pack->pf_parse( p_pack->p_private, &b_used_ts, p_pic );
00182 if( b_used_ts )
00183 {
00184 p_block_bytestream->i_dts = VLC_TS_INVALID;
00185 p_block_bytestream->i_pts = VLC_TS_INVALID;
00186 }
00187 }
00188
00189 if( !p_pic )
00190 {
00191 p_pack->i_state = STATE_NOSYNC;
00192 break;
00193 }
00194 if( p_pack->pf_validate( p_pack->p_private, p_pic ) )
00195 {
00196 p_pack->i_state = STATE_NOSYNC;
00197 block_Release( p_pic );
00198 break;
00199 }
00200
00201
00202 *pp_block = block_BytestreamPop( &p_pack->bytestream );
00203
00204 p_pack->i_state = STATE_NOSYNC;
00205
00206 return p_pic;
00207 }
00208 }
00209 }
00210
00211 static inline void packetizer_Header( packetizer_t *p_pack,
00212 const uint8_t *p_header, int i_header )
00213 {
00214 block_t *p_init = block_Alloc( i_header );
00215 if( !p_init )
00216 return;
00217
00218 memcpy( p_init->p_buffer, p_header, i_header );
00219
00220 p_pack->b_flushing = true;
00221
00222 block_t *p_pic;
00223 while( ( p_pic = packetizer_Packetize( p_pack, &p_init ) ) )
00224 block_Release( p_pic );
00225
00226 p_pack->i_state = STATE_NOSYNC;
00227 block_BytestreamEmpty( &p_pack->bytestream );
00228 p_pack->i_offset = 0;
00229 p_pack->b_flushing = false;
00230 }
00231
00232 #endif
00233