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

Generated on Sun Nov 22 08:05:12 2009 for VLC by  doxygen 1.5.6