home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / vlc-1.1.2-win32.exe / sdk / include / vlc / plugins / vlc_block_helper.h < prev    next >
Encoding:
C/C++ Source or Header  |  2010-07-30  |  13.8 KB  |  525 lines

  1. /*****************************************************************************
  2.  * vlc_block_helper.h: Helper functions for data blocks management.
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 the VideoLAN team
  5.  * $Id: 7aa1989af0042ff8127b219ba3e24951367f4a4d $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23.  
  24. #ifndef VLC_BLOCK_HELPER_H
  25. #define VLC_BLOCK_HELPER_H 1
  26.  
  27. #include <vlc_block.h>
  28.  
  29. typedef struct block_bytestream_t
  30. {
  31.     block_t             *p_chain;
  32.     block_t             *p_block;
  33.     size_t              i_offset;
  34.  
  35. } block_bytestream_t;
  36.  
  37. /*****************************************************************************
  38.  * block_bytestream_t management
  39.  *****************************************************************************/
  40. LIBVLC_USED
  41. static inline block_bytestream_t block_BytestreamInit( void )
  42. {
  43.     block_bytestream_t bytestream;
  44.  
  45.     bytestream.i_offset = 0;
  46.     bytestream.p_chain = bytestream.p_block = NULL;
  47.  
  48.     return bytestream;
  49. }
  50.  
  51. static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream )
  52. {
  53.     while( p_bytestream->p_chain )
  54.     {
  55.         block_t *p_next;
  56.         p_next = p_bytestream->p_chain->p_next;
  57.         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
  58.         p_bytestream->p_chain = p_next;
  59.     }
  60.     p_bytestream->i_offset = 0;
  61.     p_bytestream->p_chain = p_bytestream->p_block = NULL;
  62. }
  63.  
  64. /**
  65.  * It flush all data (read and unread) from a block_bytestream_t.
  66.  */
  67. static inline void block_BytestreamEmpty( block_bytestream_t *p_bytestream )
  68. {
  69.     block_BytestreamRelease( p_bytestream );
  70.  
  71.     *p_bytestream = block_BytestreamInit();
  72. }
  73.  
  74. /**
  75.  * It flushes all already read data from a block_bytestream_t.
  76.  */
  77. static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream )
  78. {
  79.     while( p_bytestream->p_chain != p_bytestream->p_block )
  80.     {
  81.         block_t *p_next;
  82.         p_next = p_bytestream->p_chain->p_next;
  83.         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
  84.         p_bytestream->p_chain = p_next;
  85.     }
  86.     while( p_bytestream->p_block &&
  87.            (p_bytestream->p_block->i_buffer - p_bytestream->i_offset) == 0 )
  88.     {
  89.         block_t *p_next;
  90.         p_next = p_bytestream->p_chain->p_next;
  91.         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
  92.         p_bytestream->p_chain = p_bytestream->p_block = p_next;
  93.         p_bytestream->i_offset = 0;
  94.     }
  95. }
  96.  
  97. static inline void block_BytestreamPush( block_bytestream_t *p_bytestream,
  98.                                          block_t *p_block )
  99. {
  100.     block_ChainAppend( &p_bytestream->p_chain, p_block );
  101.     if( !p_bytestream->p_block ) p_bytestream->p_block = p_block;
  102. }
  103.  
  104. LIBVLC_USED
  105. static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream )
  106. {
  107.     block_t *p_block;
  108.  
  109.     block_BytestreamFlush( p_bytestream );
  110.  
  111.     p_block = p_bytestream->p_block;
  112.     if( p_block == NULL )
  113.     {
  114.         return NULL;
  115.     }
  116.     else if( !p_block->p_next )
  117.     {
  118.         p_block->p_buffer += p_bytestream->i_offset;
  119.         p_block->i_buffer -= p_bytestream->i_offset;
  120.         p_bytestream->i_offset = 0;
  121.         p_bytestream->p_chain = p_bytestream->p_block = NULL;
  122.         return p_block;
  123.     }
  124.  
  125.     while( p_block->p_next && p_block->p_next->p_next )
  126.         p_block = p_block->p_next;
  127.  
  128.     {
  129.         block_t *p_block_old = p_block;
  130.         p_block = p_block->p_next;
  131.         p_block_old->p_next = NULL;
  132.     }
  133.  
  134.     return p_block;
  135. }
  136.  
  137. static inline int block_SkipByte( block_bytestream_t *p_bytestream )
  138. {
  139.     /* Most common case first */
  140.     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
  141.     {
  142.         p_bytestream->i_offset++;
  143.         return VLC_SUCCESS;
  144.     }
  145.     else
  146.     {
  147.         block_t *p_block;
  148.  
  149.         /* Less common case which is also slower */
  150.         for( p_block = p_bytestream->p_block->p_next;
  151.              p_block != NULL; p_block = p_block->p_next )
  152.         {
  153.             if( p_block->i_buffer )
  154.             {
  155.                 p_bytestream->i_offset = 1;
  156.                 p_bytestream->p_block = p_block;
  157.                 return VLC_SUCCESS;
  158.             }
  159.         }
  160.     }
  161.  
  162.     /* Not enough data, bail out */
  163.     return VLC_EGENERIC;
  164. }
  165.  
  166. static inline int block_PeekByte( block_bytestream_t *p_bytestream,
  167.                                   uint8_t *p_data )
  168. {
  169.     /* Most common case first */
  170.     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
  171.     {
  172.         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
  173.         return VLC_SUCCESS;
  174.     }
  175.     else
  176.     {
  177.         block_t *p_block;
  178.  
  179.         /* Less common case which is also slower */
  180.         for( p_block = p_bytestream->p_block->p_next;
  181.              p_block != NULL; p_block = p_block->p_next )
  182.         {
  183.             if( p_block->i_buffer )
  184.             {
  185.                 *p_data = p_block->p_buffer[0];
  186.                 return VLC_SUCCESS;
  187.             }
  188.         }
  189.     }
  190.  
  191.     /* Not enough data, bail out */
  192.     return VLC_EGENERIC;
  193. }
  194.  
  195. static inline int block_GetByte( block_bytestream_t *p_bytestream,
  196.                                  uint8_t *p_data )
  197. {
  198.     /* Most common case first */
  199.     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
  200.     {
  201.         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
  202.         p_bytestream->i_offset++;
  203.         return VLC_SUCCESS;
  204.     }
  205.     else
  206.     {
  207.         block_t *p_block;
  208.  
  209.         /* Less common case which is also slower */
  210.         for( p_block = p_bytestream->p_block->p_next;
  211.              p_block != NULL; p_block = p_block->p_next )
  212.         {
  213.             if( p_block->i_buffer )
  214.             {
  215.                 *p_data = p_block->p_buffer[0];
  216.                 p_bytestream->i_offset = 1;
  217.                 p_bytestream->p_block = p_block;
  218.                 return VLC_SUCCESS;
  219.             }
  220.         }
  221.     }
  222.  
  223.     /* Not enough data, bail out */
  224.     return VLC_EGENERIC;
  225. }
  226.  
  227. static inline int block_WaitBytes( block_bytestream_t *p_bytestream,
  228.                                    size_t i_data )
  229. {
  230.     block_t *p_block;
  231.     size_t i_offset, i_copy, i_size;
  232.  
  233.     /* Check we have that much data */
  234.     i_offset = p_bytestream->i_offset;
  235.     i_size = i_data;
  236.     i_copy = 0;
  237.     for( p_block = p_bytestream->p_block;
  238.          p_block != NULL; p_block = p_block->p_next )
  239.     {
  240.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  241.         i_size -= i_copy;
  242.         i_offset = 0;
  243.  
  244.         if( !i_size ) break;
  245.     }
  246.  
  247.     if( i_size )
  248.     {
  249.         /* Not enough data, bail out */
  250.         return VLC_EGENERIC;
  251.     }
  252.     return VLC_SUCCESS;
  253. }
  254.  
  255. static inline int block_SkipBytes( block_bytestream_t *p_bytestream,
  256.                                    size_t i_data )
  257. {
  258.     block_t *p_block;
  259.     size_t i_offset, i_copy;
  260.  
  261.     /* Check we have that much data */
  262.     i_offset = p_bytestream->i_offset;
  263.     i_copy = 0;
  264.     for( p_block = p_bytestream->p_block;
  265.          p_block != NULL; p_block = p_block->p_next )
  266.     {
  267.         i_copy = __MIN( i_data, p_block->i_buffer - i_offset );
  268.         i_data -= i_copy;
  269.  
  270.         if( !i_data ) break;
  271.  
  272.         i_offset = 0;
  273.     }
  274.  
  275.     if( i_data )
  276.     {
  277.         /* Not enough data, bail out */
  278.         return VLC_EGENERIC;
  279.     }
  280.  
  281.     p_bytestream->p_block = p_block;
  282.     p_bytestream->i_offset = i_offset + i_copy;
  283.     return VLC_SUCCESS;
  284. }
  285.  
  286. static inline int block_PeekBytes( block_bytestream_t *p_bytestream,
  287.                                    uint8_t *p_data, size_t i_data )
  288. {
  289.     block_t *p_block;
  290.     size_t i_offset, i_copy, i_size;
  291.  
  292.     /* Check we have that much data */
  293.     i_offset = p_bytestream->i_offset;
  294.     i_size = i_data;
  295.     i_copy = 0;
  296.     for( p_block = p_bytestream->p_block;
  297.          p_block != NULL; p_block = p_block->p_next )
  298.     {
  299.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  300.         i_size -= i_copy;
  301.         i_offset = 0;
  302.  
  303.         if( !i_size ) break;
  304.     }
  305.  
  306.     if( i_size )
  307.     {
  308.         /* Not enough data, bail out */
  309.         return VLC_EGENERIC;
  310.     }
  311.  
  312.     /* Copy the data */
  313.     i_offset = p_bytestream->i_offset;
  314.     i_size = i_data;
  315.     i_copy = 0;
  316.     for( p_block = p_bytestream->p_block;
  317.          p_block != NULL; p_block = p_block->p_next )
  318.     {
  319.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  320.         i_size -= i_copy;
  321.  
  322.         if( i_copy )
  323.         {
  324.             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
  325.             p_data += i_copy;
  326.         }
  327.  
  328.         i_offset = 0;
  329.  
  330.         if( !i_size ) break;
  331.     }
  332.  
  333.     return VLC_SUCCESS;
  334. }
  335.  
  336. static inline int block_GetBytes( block_bytestream_t *p_bytestream,
  337.                                   uint8_t *p_data, size_t i_data )
  338. {
  339.     block_t *p_block;
  340.     size_t i_offset, i_copy, i_size;
  341.  
  342.     /* Check we have that much data */
  343.     i_offset = p_bytestream->i_offset;
  344.     i_size = i_data;
  345.     i_copy = 0;
  346.     for( p_block = p_bytestream->p_block;
  347.          p_block != NULL; p_block = p_block->p_next )
  348.     {
  349.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  350.         i_size -= i_copy;
  351.         i_offset = 0;
  352.  
  353.         if( !i_size ) break;
  354.     }
  355.  
  356.     if( i_size )
  357.     {
  358.         /* Not enough data, bail out */
  359.         return VLC_EGENERIC;
  360.     }
  361.  
  362.     /* Copy the data */
  363.     i_offset = p_bytestream->i_offset;
  364.     i_size = i_data;
  365.     i_copy = 0;
  366.     for( p_block = p_bytestream->p_block;
  367.          p_block != NULL; p_block = p_block->p_next )
  368.     {
  369.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  370.         i_size -= i_copy;
  371.  
  372.         if( i_copy )
  373.         {
  374.             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
  375.             p_data += i_copy;
  376.         }
  377.  
  378.         if( !i_size ) break;
  379.  
  380.         i_offset = 0;
  381.     }
  382.  
  383.     /* No buffer given, just skip the data */
  384.     p_bytestream->p_block = p_block;
  385.     p_bytestream->i_offset = i_offset + i_copy;
  386.  
  387.     return VLC_SUCCESS;
  388. }
  389.  
  390. static inline int block_PeekOffsetBytes( block_bytestream_t *p_bytestream,
  391.     size_t i_peek_offset, uint8_t *p_data, size_t i_data )
  392. {
  393.     block_t *p_block;
  394.     size_t i_offset, i_copy, i_size;
  395.  
  396.     /* Check we have that much data */
  397.     i_offset = p_bytestream->i_offset;
  398.     i_size = i_data + i_peek_offset;
  399.     i_copy = 0;
  400.     for( p_block = p_bytestream->p_block;
  401.          p_block != NULL; p_block = p_block->p_next )
  402.     {
  403.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  404.         i_size -= i_copy;
  405.         i_offset = 0;
  406.  
  407.         if( !i_size ) break;
  408.     }
  409.  
  410.     if( i_size )
  411.     {
  412.         /* Not enough data, bail out */
  413.         return VLC_EGENERIC;
  414.     }
  415.  
  416.     /* Find the right place */
  417.     i_offset = p_bytestream->i_offset;
  418.     i_size = i_peek_offset;
  419.     i_copy = 0;
  420.     for( p_block = p_bytestream->p_block;
  421.          p_block != NULL; p_block = p_block->p_next )
  422.     {
  423.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  424.         i_size -= i_copy;
  425.  
  426.         if( !i_size ) break;
  427.  
  428.         i_offset = 0;
  429.     }
  430.  
  431.     /* Copy the data */
  432.     i_offset += i_copy;
  433.     i_size = i_data;
  434.     i_copy = 0;
  435.     for( ; p_block != NULL; p_block = p_block->p_next )
  436.     {
  437.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  438.         i_size -= i_copy;
  439.  
  440.         if( i_copy )
  441.         {
  442.             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
  443.             p_data += i_copy;
  444.         }
  445.  
  446.         i_offset = 0;
  447.  
  448.         if( !i_size ) break;
  449.     }
  450.  
  451.     return VLC_SUCCESS;
  452. }
  453.  
  454. static inline int block_FindStartcodeFromOffset(
  455.     block_bytestream_t *p_bytestream, size_t *pi_offset,
  456.     const uint8_t *p_startcode, int i_startcode_length )
  457. {
  458.     block_t *p_block, *p_block_backup = 0;
  459.     int i_size = 0;
  460.     size_t i_offset, i_offset_backup = 0;
  461.     int i_caller_offset_backup = 0, i_match;
  462.  
  463.     /* Find the right place */
  464.     i_size = *pi_offset + p_bytestream->i_offset;
  465.     for( p_block = p_bytestream->p_block;
  466.          p_block != NULL; p_block = p_block->p_next )
  467.     {
  468.         i_size -= p_block->i_buffer;
  469.         if( i_size < 0 ) break;
  470.     }
  471.  
  472.     if( i_size >= 0 )
  473.     {
  474.         /* Not enough data, bail out */
  475.         return VLC_EGENERIC;
  476.     }
  477.  
  478.     /* Begin the search.
  479.      * We first look for an occurrence of the 1st startcode byte and
  480.      * if found, we do a more thorough check. */
  481.     i_size += p_block->i_buffer;
  482.     *pi_offset -= i_size;
  483.     i_match = 0;
  484.     for( ; p_block != NULL; p_block = p_block->p_next )
  485.     {
  486.         for( i_offset = i_size; i_offset < p_block->i_buffer; i_offset++ )
  487.         {
  488.             if( p_block->p_buffer[i_offset] == p_startcode[i_match] )
  489.             {
  490.                 if( !i_match )
  491.                 {
  492.                     p_block_backup = p_block;
  493.                     i_offset_backup = i_offset;
  494.                     i_caller_offset_backup = *pi_offset;
  495.                 }
  496.  
  497.                 if( i_match + 1 == i_startcode_length )
  498.                 {
  499.                     /* We have it */
  500.                     *pi_offset += i_offset - i_match;
  501.                     return VLC_SUCCESS;
  502.                 }
  503.  
  504.                 i_match++;
  505.             }
  506.             else if ( i_match )
  507.             {
  508.                 /* False positive */
  509.                 p_block = p_block_backup;
  510.                 i_offset = i_offset_backup;
  511.                 *pi_offset = i_caller_offset_backup;
  512.                 i_match = 0;
  513.             }
  514.  
  515.         }
  516.         i_size = 0;
  517.         *pi_offset += i_offset;
  518.     }
  519.  
  520.     *pi_offset -= i_match;
  521.     return VLC_EGENERIC;
  522. }
  523.  
  524. #endif /* VLC_BLOCK_HELPER_H */
  525.