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

Generated on Mon Nov 22 07:55:19 2010 for VLC by  doxygen 1.5.6