home *** CD-ROM | disk | FTP | other *** search
/ mail.altrad.com / 2015.02.mail.altrad.com.tar / mail.altrad.com / TEST / vlc-2-0-5-win32.exe / sdk / include / vlc / plugins / vlc_block_helper.h < prev    next >
C/C++ Source or Header  |  2012-12-12  |  14KB  |  521 lines

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