vlc_block_helper.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * vlc_block_helper.h: Helper functions for data blocks management.
00003  *****************************************************************************
00004  * Copyright (C) 2003 VLC authors and VideoLAN
00005  * $Id: fdd5fdbeafee1f296c157410ef3e69a7cf57d3e5 $
00006  *
00007  * Authors: Gildas Bazin <gbazin@netcourrier.com>
00008  *
00009  * This program is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License as published by
00011  * the Free Software Foundation; either version 2.1 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017  * GNU Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public License
00020  * along with this program; if not, write to the Free Software Foundation,
00021  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
00022  *****************************************************************************/
00023 
00024 #ifndef VLC_BLOCK_HELPER_H
00025 #define VLC_BLOCK_HELPER_H 1
00026 
00027 #include <vlc_block.h>
00028 
00029 typedef struct block_bytestream_t
00030 {
00031     block_t *p_chain;  /**< byte stream head block */
00032     block_t *p_block;  /**< byte stream read pointer block */
00033     size_t   i_offset; /**< byte stream read pointer offset within block */
00034     /* TODO? add tail pointer for faster push? */
00035 } block_bytestream_t;
00036 
00037 /*****************************************************************************
00038  * block_bytestream_t management
00039  *****************************************************************************/
00040 static inline void block_BytestreamInit( block_bytestream_t *p_bytestream )
00041 {
00042     p_bytestream->p_chain = p_bytestream->p_block = NULL;
00043     p_bytestream->i_offset = 0;
00044 }
00045 
00046 static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream )
00047 {
00048     for( block_t *block = p_bytestream->p_chain; block != NULL; )
00049     {
00050         block_t *p_next = block->p_next;
00051 
00052         block_Release( block );
00053         block = p_next;
00054     }
00055 }
00056 
00057 /**
00058  * It flush all data (read and unread) from a block_bytestream_t.
00059  */
00060 static inline void block_BytestreamEmpty( block_bytestream_t *p_bytestream )
00061 {
00062     block_BytestreamRelease( p_bytestream );
00063     block_BytestreamInit( p_bytestream );
00064 }
00065 
00066 /**
00067  * It flushes all already read data from a block_bytestream_t.
00068  */
00069 static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream )
00070 {
00071     block_t *block = p_bytestream->p_chain;
00072 
00073     while( block != p_bytestream->p_block )
00074     {
00075         block_t *p_next = block->p_next;
00076 
00077         block_Release( block );
00078         block = p_next;
00079     }
00080 
00081     while( block != NULL && block->i_buffer == p_bytestream->i_offset )
00082     {
00083         block_t *p_next = block->p_next;
00084 
00085         block_Release( block );
00086         block = p_next;
00087         p_bytestream->i_offset = 0;
00088     }
00089 
00090     p_bytestream->p_chain = p_bytestream->p_block = block;
00091 }
00092 
00093 static inline void block_BytestreamPush( block_bytestream_t *p_bytestream,
00094                                          block_t *p_block )
00095 {
00096     block_ChainAppend( &p_bytestream->p_chain, p_block );
00097     if( !p_bytestream->p_block ) p_bytestream->p_block = p_block;
00098 }
00099 
00100 VLC_USED
00101 static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream )
00102 {
00103     block_t *p_block;
00104 
00105     block_BytestreamFlush( p_bytestream );
00106 
00107     p_block = p_bytestream->p_block;
00108     if( p_block == NULL )
00109     {
00110         return NULL;
00111     }
00112     else if( !p_block->p_next )
00113     {
00114         p_block->p_buffer += p_bytestream->i_offset;
00115         p_block->i_buffer -= p_bytestream->i_offset;
00116         p_bytestream->i_offset = 0;
00117         p_bytestream->p_chain = p_bytestream->p_block = NULL;
00118         return p_block;
00119     }
00120 
00121     while( p_block->p_next && p_block->p_next->p_next )
00122         p_block = p_block->p_next;
00123 
00124     block_t *p_block_old = p_block;
00125     p_block = p_block->p_next;
00126     p_block_old->p_next = NULL;
00127 
00128     return p_block;
00129 }
00130 
00131 static inline int block_SkipByte( block_bytestream_t *p_bytestream )
00132 {
00133     /* Most common case first */
00134     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
00135     {
00136         p_bytestream->i_offset++;
00137         return VLC_SUCCESS;
00138     }
00139     else
00140     {
00141         block_t *p_block;
00142 
00143         /* Less common case which is also slower */
00144         for( p_block = p_bytestream->p_block->p_next;
00145              p_block != NULL; p_block = p_block->p_next )
00146         {
00147             if( p_block->i_buffer )
00148             {
00149                 p_bytestream->i_offset = 1;
00150                 p_bytestream->p_block = p_block;
00151                 return VLC_SUCCESS;
00152             }
00153         }
00154     }
00155 
00156     /* Not enough data, bail out */
00157     return VLC_EGENERIC;
00158 }
00159 
00160 static inline int block_PeekByte( block_bytestream_t *p_bytestream,
00161                                   uint8_t *p_data )
00162 {
00163     /* Most common case first */
00164     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
00165     {
00166         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
00167         return VLC_SUCCESS;
00168     }
00169     else
00170     {
00171         block_t *p_block;
00172 
00173         /* Less common case which is also slower */
00174         for( p_block = p_bytestream->p_block->p_next;
00175              p_block != NULL; p_block = p_block->p_next )
00176         {
00177             if( p_block->i_buffer )
00178             {
00179                 *p_data = p_block->p_buffer[0];
00180                 return VLC_SUCCESS;
00181             }
00182         }
00183     }
00184 
00185     /* Not enough data, bail out */
00186     return VLC_EGENERIC;
00187 }
00188 
00189 static inline int block_GetByte( block_bytestream_t *p_bytestream,
00190                                  uint8_t *p_data )
00191 {
00192     /* Most common case first */
00193     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
00194     {
00195         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
00196         p_bytestream->i_offset++;
00197         return VLC_SUCCESS;
00198     }
00199     else
00200     {
00201         block_t *p_block;
00202 
00203         /* Less common case which is also slower */
00204         for( p_block = p_bytestream->p_block->p_next;
00205              p_block != NULL; p_block = p_block->p_next )
00206         {
00207             if( p_block->i_buffer )
00208             {
00209                 *p_data = p_block->p_buffer[0];
00210                 p_bytestream->i_offset = 1;
00211                 p_bytestream->p_block = p_block;
00212                 return VLC_SUCCESS;
00213             }
00214         }
00215     }
00216 
00217     /* Not enough data, bail out */
00218     return VLC_EGENERIC;
00219 }
00220 
00221 static inline int block_WaitBytes( block_bytestream_t *p_bytestream,
00222                                    size_t i_data )
00223 {
00224     block_t *p_block;
00225     size_t i_offset, i_copy, i_size;
00226 
00227     /* Check we have that much data */
00228     i_offset = p_bytestream->i_offset;
00229     i_size = i_data;
00230     i_copy = 0;
00231     for( p_block = p_bytestream->p_block;
00232          p_block != NULL; p_block = p_block->p_next )
00233     {
00234         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00235         i_size -= i_copy;
00236         i_offset = 0;
00237 
00238         if( !i_size ) break;
00239     }
00240 
00241     if( i_size )
00242     {
00243         /* Not enough data, bail out */
00244         return VLC_EGENERIC;
00245     }
00246     return VLC_SUCCESS;
00247 }
00248 
00249 static inline int block_SkipBytes( block_bytestream_t *p_bytestream,
00250                                    size_t i_data )
00251 {
00252     block_t *p_block;
00253     size_t i_offset, i_copy;
00254 
00255     /* Check we have that much data */
00256     i_offset = p_bytestream->i_offset;
00257     i_copy = 0;
00258     for( p_block = p_bytestream->p_block;
00259          p_block != NULL; p_block = p_block->p_next )
00260     {
00261         i_copy = __MIN( i_data, p_block->i_buffer - i_offset );
00262         i_data -= i_copy;
00263 
00264         if( !i_data ) break;
00265 
00266         i_offset = 0;
00267     }
00268 
00269     if( i_data )
00270     {
00271         /* Not enough data, bail out */
00272         return VLC_EGENERIC;
00273     }
00274 
00275     p_bytestream->p_block = p_block;
00276     p_bytestream->i_offset = i_offset + i_copy;
00277     return VLC_SUCCESS;
00278 }
00279 
00280 static inline int block_PeekBytes( block_bytestream_t *p_bytestream,
00281                                    uint8_t *p_data, size_t i_data )
00282 {
00283     block_t *p_block;
00284     size_t i_offset, i_copy, i_size;
00285 
00286     /* Check we have that much data */
00287     i_offset = p_bytestream->i_offset;
00288     i_size = i_data;
00289     i_copy = 0;
00290     for( p_block = p_bytestream->p_block;
00291          p_block != NULL; p_block = p_block->p_next )
00292     {
00293         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00294         i_size -= i_copy;
00295         i_offset = 0;
00296 
00297         if( !i_size ) break;
00298     }
00299 
00300     if( i_size )
00301     {
00302         /* Not enough data, bail out */
00303         return VLC_EGENERIC;
00304     }
00305 
00306     /* Copy the data */
00307     i_offset = p_bytestream->i_offset;
00308     i_size = i_data;
00309     i_copy = 0;
00310     for( p_block = p_bytestream->p_block;
00311          p_block != NULL; p_block = p_block->p_next )
00312     {
00313         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00314         i_size -= i_copy;
00315 
00316         if( i_copy )
00317         {
00318             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
00319             p_data += i_copy;
00320         }
00321 
00322         i_offset = 0;
00323 
00324         if( !i_size ) break;
00325     }
00326 
00327     return VLC_SUCCESS;
00328 }
00329 
00330 static inline int block_GetBytes( block_bytestream_t *p_bytestream,
00331                                   uint8_t *p_data, size_t i_data )
00332 {
00333     block_t *p_block;
00334     size_t i_offset, i_copy, i_size;
00335 
00336     /* Check we have that much data */
00337     i_offset = p_bytestream->i_offset;
00338     i_size = i_data;
00339     i_copy = 0;
00340     for( p_block = p_bytestream->p_block;
00341          p_block != NULL; p_block = p_block->p_next )
00342     {
00343         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00344         i_size -= i_copy;
00345         i_offset = 0;
00346 
00347         if( !i_size ) break;
00348     }
00349 
00350     if( i_size )
00351     {
00352         /* Not enough data, bail out */
00353         return VLC_EGENERIC;
00354     }
00355 
00356     /* Copy the data */
00357     i_offset = p_bytestream->i_offset;
00358     i_size = i_data;
00359     i_copy = 0;
00360     for( p_block = p_bytestream->p_block;
00361          p_block != NULL; p_block = p_block->p_next )
00362     {
00363         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00364         i_size -= i_copy;
00365 
00366         if( i_copy )
00367         {
00368             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
00369             p_data += i_copy;
00370         }
00371 
00372         if( !i_size ) break;
00373 
00374         i_offset = 0;
00375     }
00376 
00377     p_bytestream->p_block = p_block;
00378     p_bytestream->i_offset = i_offset + i_copy;
00379 
00380     return VLC_SUCCESS;
00381 }
00382 
00383 static inline int block_PeekOffsetBytes( block_bytestream_t *p_bytestream,
00384     size_t i_peek_offset, uint8_t *p_data, size_t i_data )
00385 {
00386     block_t *p_block;
00387     size_t i_offset, i_copy, i_size;
00388 
00389     /* Check we have that much data */
00390     i_offset = p_bytestream->i_offset;
00391     i_size = i_data + i_peek_offset;
00392     i_copy = 0;
00393     for( p_block = p_bytestream->p_block;
00394          p_block != NULL; p_block = p_block->p_next )
00395     {
00396         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00397         i_size -= i_copy;
00398         i_offset = 0;
00399 
00400         if( !i_size ) break;
00401     }
00402 
00403     if( i_size )
00404     {
00405         /* Not enough data, bail out */
00406         return VLC_EGENERIC;
00407     }
00408 
00409     /* Find the right place */
00410     i_offset = p_bytestream->i_offset;
00411     i_size = i_peek_offset;
00412     i_copy = 0;
00413     for( p_block = p_bytestream->p_block;
00414          p_block != NULL; p_block = p_block->p_next )
00415     {
00416         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00417         i_size -= i_copy;
00418 
00419         if( !i_size ) break;
00420 
00421         i_offset = 0;
00422     }
00423 
00424     /* Copy the data */
00425     i_offset += i_copy;
00426     i_size = i_data;
00427     i_copy = 0;
00428     for( ; p_block != NULL; p_block = p_block->p_next )
00429     {
00430         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
00431         i_size -= i_copy;
00432 
00433         if( i_copy )
00434         {
00435             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
00436             p_data += i_copy;
00437         }
00438 
00439         i_offset = 0;
00440 
00441         if( !i_size ) break;
00442     }
00443 
00444     return VLC_SUCCESS;
00445 }
00446 
00447 static inline int block_FindStartcodeFromOffset(
00448     block_bytestream_t *p_bytestream, size_t *pi_offset,
00449     const uint8_t *p_startcode, int i_startcode_length )
00450 {
00451     block_t *p_block, *p_block_backup = 0;
00452     int i_size = 0;
00453     size_t i_offset, i_offset_backup = 0;
00454     int i_caller_offset_backup = 0, i_match;
00455 
00456     /* Find the right place */
00457     i_size = *pi_offset + p_bytestream->i_offset;
00458     for( p_block = p_bytestream->p_block;
00459          p_block != NULL; p_block = p_block->p_next )
00460     {
00461         i_size -= p_block->i_buffer;
00462         if( i_size < 0 ) break;
00463     }
00464 
00465     if( i_size >= 0 )
00466     {
00467         /* Not enough data, bail out */
00468         return VLC_EGENERIC;
00469     }
00470 
00471     /* Begin the search.
00472      * We first look for an occurrence of the 1st startcode byte and
00473      * if found, we do a more thorough check. */
00474     i_size += p_block->i_buffer;
00475     *pi_offset -= i_size;
00476     i_match = 0;
00477     for( ; p_block != NULL; p_block = p_block->p_next )
00478     {
00479         for( i_offset = i_size; i_offset < p_block->i_buffer; i_offset++ )
00480         {
00481             if( p_block->p_buffer[i_offset] == p_startcode[i_match] )
00482             {
00483                 if( !i_match )
00484                 {
00485                     p_block_backup = p_block;
00486                     i_offset_backup = i_offset;
00487                     i_caller_offset_backup = *pi_offset;
00488                 }
00489 
00490                 if( i_match + 1 == i_startcode_length )
00491                 {
00492                     /* We have it */
00493                     *pi_offset += i_offset - i_match;
00494                     return VLC_SUCCESS;
00495                 }
00496 
00497                 i_match++;
00498             }
00499             else if ( i_match )
00500             {
00501                 /* False positive */
00502                 p_block = p_block_backup;
00503                 i_offset = i_offset_backup;
00504                 *pi_offset = i_caller_offset_backup;
00505                 i_match = 0;
00506             }
00507 
00508         }
00509         i_size = 0;
00510         *pi_offset += i_offset;
00511     }
00512 
00513     *pi_offset -= i_match;
00514     return VLC_EGENERIC;
00515 }
00516 
00517 #endif /* VLC_BLOCK_HELPER_H */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines