home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 May / maximum-cd-2009-05.iso / DiscContents / vlc-0.9.8a-win32.exe / sdk / include / vlc / plugins / vlc_block_helper.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-06  |  13.5 KB  |  510 lines

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