home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 October / maximum-cd-2009-10.iso / DiscContents / vlc-1.0.0-win32.exe / sdk / include / vlc / plugins / vlc_block_helper.h < prev    next >
Encoding:
C/C++ Source or Header  |  2009-07-06  |  13.8 KB  |  524 lines

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