vlc_block_helper.h
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:13k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * vlc_block_helper.h: Helper functions for data blocks management.
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: vlc_block_helper.h 8547 2004-08-28 11:29:48Z sam $
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. #ifndef _VLC_BLOCK_HELPER_H
  24. #define _VLC_BLOCK_HELPER_H 1
  25. typedef struct block_bytestream_t
  26. {
  27.     block_t             *p_chain;
  28.     block_t             *p_block;
  29.     int                 i_offset;
  30. } block_bytestream_t;
  31. #define block_BytestreamInit( a ) __block_BytestreamInit( VLC_OBJECT(a) )
  32. /*****************************************************************************
  33.  * block_bytestream_t management
  34.  *****************************************************************************/
  35. static inline block_bytestream_t __block_BytestreamInit( vlc_object_t *p_obj )
  36. {
  37.     block_bytestream_t bytestream;
  38.     bytestream.i_offset = 0;
  39.     bytestream.p_chain = bytestream.p_block = NULL;
  40.     return bytestream;
  41. }
  42. static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream )
  43. {
  44.     while( p_bytestream->p_chain )
  45.     {
  46.         block_t *p_next;
  47.         p_next = p_bytestream->p_chain->p_next;
  48.         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
  49.         p_bytestream->p_chain = p_next;
  50.     }
  51.     p_bytestream->i_offset = 0;
  52.     p_bytestream->p_chain = p_bytestream->p_block = NULL;
  53. }
  54. static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream )
  55. {
  56.     while( p_bytestream->p_chain != p_bytestream->p_block )
  57.     {
  58.         block_t *p_next;
  59.         p_next = p_bytestream->p_chain->p_next;
  60.         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
  61.         p_bytestream->p_chain = p_next;
  62.     }
  63.     while( p_bytestream->p_block &&
  64.            (p_bytestream->p_block->i_buffer - p_bytestream->i_offset) == 0 )
  65.     {
  66.         block_t *p_next;
  67.         p_next = p_bytestream->p_chain->p_next;
  68.         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
  69.         p_bytestream->p_chain = p_bytestream->p_block = p_next;
  70.         p_bytestream->i_offset = 0;
  71.     }
  72. }
  73. static inline void block_BytestreamPush( block_bytestream_t *p_bytestream,
  74.                                          block_t *p_block )
  75. {
  76.     block_ChainAppend( &p_bytestream->p_chain, p_block );
  77.     if( !p_bytestream->p_block ) p_bytestream->p_block = p_block;
  78. }
  79. static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream )
  80. {
  81.     block_t *p_block;
  82.     block_BytestreamFlush( p_bytestream );
  83.     p_block = p_bytestream->p_block;
  84.     if( p_block == NULL )
  85.     {
  86.         return NULL;
  87.     }
  88.     else if( !p_block->p_next )
  89.     {
  90.         p_block->p_buffer += p_bytestream->i_offset;
  91.         p_block->i_buffer -= p_bytestream->i_offset;
  92.         p_bytestream->i_offset = 0;
  93.         p_bytestream->p_chain = p_bytestream->p_block = NULL;
  94.         return p_block;
  95.     }
  96.     while( p_block->p_next && p_block->p_next->p_next )
  97.         p_block = p_block->p_next;
  98.     {
  99.         block_t *p_block_old = p_block;
  100.         p_block = p_block->p_next;
  101.         p_block_old->p_next = NULL;
  102.     }
  103.     return p_block;
  104. }
  105. static inline int block_SkipByte( block_bytestream_t *p_bytestream )
  106. {
  107.     /* Most common case first */
  108.     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
  109.     {
  110.         p_bytestream->i_offset++;
  111.         return VLC_SUCCESS;
  112.     }
  113.     else
  114.     {
  115.         block_t *p_block;
  116.         /* Less common case which is also slower */
  117.         for( p_block = p_bytestream->p_block->p_next;
  118.              p_block != NULL; p_block = p_block->p_next )
  119.         {
  120.             if( p_block->i_buffer )
  121.             {
  122.                 p_bytestream->i_offset = 1;
  123.                 p_bytestream->p_block = p_block;
  124.                 return VLC_SUCCESS;
  125.             }
  126.         }
  127.     }
  128.     /* Not enough data, bail out */
  129.     return VLC_EGENERIC;
  130. }
  131. static inline int block_PeekByte( block_bytestream_t *p_bytestream,
  132.                                   uint8_t *p_data )
  133. {
  134.     /* Most common case first */
  135.     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
  136.     {
  137.         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
  138.         return VLC_SUCCESS;
  139.     }
  140.     else
  141.     {
  142.         block_t *p_block;
  143.         /* Less common case which is also slower */
  144.         for( p_block = p_bytestream->p_block->p_next;
  145.              p_block != NULL; p_block = p_block->p_next )
  146.         {
  147.             if( p_block->i_buffer )
  148.             {
  149.                 *p_data = p_block->p_buffer[0];
  150.                 return VLC_SUCCESS;
  151.             }
  152.         }
  153.     }
  154.     /* Not enough data, bail out */
  155.     return VLC_EGENERIC;
  156. }
  157. static inline int block_GetByte( block_bytestream_t *p_bytestream,
  158.                                  uint8_t *p_data )
  159. {
  160.     /* Most common case first */
  161.     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
  162.     {
  163.         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
  164.         p_bytestream->i_offset++;
  165.         return VLC_SUCCESS;
  166.     }
  167.     else
  168.     {
  169.         block_t *p_block;
  170.         /* Less common case which is also slower */
  171.         for( p_block = p_bytestream->p_block->p_next;
  172.              p_block != NULL; p_block = p_block->p_next )
  173.         {
  174.             if( p_block->i_buffer )
  175.             {
  176.                 *p_data = p_block->p_buffer[0];
  177.                 p_bytestream->i_offset = 1;
  178.                 p_bytestream->p_block = p_block;
  179.                 return VLC_SUCCESS;
  180.             }
  181.         }
  182.     }
  183.     /* Not enough data, bail out */
  184.     return VLC_EGENERIC;
  185. }
  186. static inline int block_WaitBytes( block_bytestream_t *p_bytestream,
  187.                                    int i_data )
  188. {
  189.     block_t *p_block;
  190.     int i_offset, i_copy, i_size;
  191.     /* Check we have that much data */
  192.     i_offset = p_bytestream->i_offset;
  193.     i_size = i_data;
  194.     i_copy = 0;
  195.     for( p_block = p_bytestream->p_block;
  196.          p_block != NULL; p_block = p_block->p_next )
  197.     {
  198.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  199.         i_size -= i_copy;
  200.         i_offset = 0;
  201.         if( !i_size ) break;
  202.     }
  203.     if( i_size )
  204.     {
  205.         /* Not enough data, bail out */
  206.         return VLC_EGENERIC;
  207.     }
  208.     return VLC_SUCCESS;
  209. }
  210. static inline int block_SkipBytes( block_bytestream_t *p_bytestream,
  211.                                    int i_data )
  212. {
  213.     block_t *p_block;
  214.     int i_offset, i_copy;
  215.     /* Check we have that much data */
  216.     i_offset = p_bytestream->i_offset;
  217.     i_copy = 0;
  218.     for( p_block = p_bytestream->p_block;
  219.          p_block != NULL; p_block = p_block->p_next )
  220.     {
  221.         i_copy = __MIN( i_data, p_block->i_buffer - i_offset );
  222.         i_data -= i_copy;
  223.         if( !i_data ) break;
  224.         i_offset = 0;
  225.     }
  226.     if( i_data )
  227.     {
  228.         /* Not enough data, bail out */
  229.         return VLC_EGENERIC;
  230.     }
  231.     p_bytestream->p_block = p_block;
  232.     p_bytestream->i_offset = i_offset + i_copy;
  233.     return VLC_SUCCESS;
  234. }
  235. static inline int block_PeekBytes( block_bytestream_t *p_bytestream,
  236.                                    uint8_t *p_data, int i_data )
  237. {
  238.     block_t *p_block;
  239.     int i_offset, i_copy, i_size;
  240.     /* Check we have that much data */
  241.     i_offset = p_bytestream->i_offset;
  242.     i_size = i_data;
  243.     i_copy = 0;
  244.     for( p_block = p_bytestream->p_block;
  245.          p_block != NULL; p_block = p_block->p_next )
  246.     {
  247.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  248.         i_size -= i_copy;
  249.         i_offset = 0;
  250.         if( !i_size ) break;
  251.     }
  252.     if( i_size )
  253.     {
  254.         /* Not enough data, bail out */
  255.         return VLC_EGENERIC;
  256.     }
  257.     /* Copy the data */
  258.     i_offset = p_bytestream->i_offset;
  259.     i_size = i_data;
  260.     i_copy = 0;
  261.     for( p_block = p_bytestream->p_block;
  262.          p_block != NULL; p_block = p_block->p_next )
  263.     {
  264.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  265.         i_size -= i_copy;
  266.         if( i_copy )
  267.         {
  268.             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
  269.             p_data += i_copy;
  270.         }
  271.         i_offset = 0;
  272.         if( !i_size ) break;
  273.     }
  274.     return VLC_SUCCESS;
  275. }
  276. static inline int block_GetBytes( block_bytestream_t *p_bytestream,
  277.                                   uint8_t *p_data, int i_data )
  278. {
  279.     block_t *p_block;
  280.     int i_offset, i_copy, i_size;
  281.     /* Check we have that much data */
  282.     i_offset = p_bytestream->i_offset;
  283.     i_size = i_data;
  284.     i_copy = 0;
  285.     for( p_block = p_bytestream->p_block;
  286.          p_block != NULL; p_block = p_block->p_next )
  287.     {
  288.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  289.         i_size -= i_copy;
  290.         i_offset = 0;
  291.         if( !i_size ) break;
  292.     }
  293.     if( i_size )
  294.     {
  295.         /* Not enough data, bail out */
  296.         return VLC_EGENERIC;
  297.     }
  298.     /* Copy the data */
  299.     i_offset = p_bytestream->i_offset;
  300.     i_size = i_data;
  301.     i_copy = 0;
  302.     for( p_block = p_bytestream->p_block;
  303.          p_block != NULL; p_block = p_block->p_next )
  304.     {
  305.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  306.         i_size -= i_copy;
  307.         if( i_copy )
  308.         {
  309.             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
  310.             p_data += i_copy;
  311.         }
  312.         if( !i_size ) break;
  313.         i_offset = 0;
  314.     }
  315.     /* No buffer given, just skip the data */
  316.     p_bytestream->p_block = p_block;
  317.     p_bytestream->i_offset = i_offset + i_copy;
  318.     return VLC_SUCCESS;
  319. }
  320. static inline int block_PeekOffsetBytes( block_bytestream_t *p_bytestream,
  321.     int i_peek_offset, uint8_t *p_data, int i_data )
  322. {
  323.     block_t *p_block;
  324.     int i_offset, i_copy, i_size;
  325.     /* Check we have that much data */
  326.     i_offset = p_bytestream->i_offset;
  327.     i_size = i_data + i_peek_offset;
  328.     i_copy = 0;
  329.     for( p_block = p_bytestream->p_block;
  330.          p_block != NULL; p_block = p_block->p_next )
  331.     {
  332.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  333.         i_size -= i_copy;
  334.         i_offset = 0;
  335.         if( !i_size ) break;
  336.     }
  337.     if( i_size )
  338.     {
  339.         /* Not enough data, bail out */
  340.         return VLC_EGENERIC;
  341.     }
  342.     /* Find the right place */
  343.     i_offset = p_bytestream->i_offset;
  344.     i_size = i_peek_offset;
  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.         if( !i_size ) break;
  352.         i_offset = 0;
  353.     }
  354.     /* Copy the data */
  355.     i_offset += i_copy;
  356.     i_size = i_data;
  357.     i_copy = 0;
  358.     for( ; p_block != NULL; p_block = p_block->p_next )
  359.     {
  360.         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
  361.         i_size -= i_copy;
  362.         if( i_copy )
  363.         {
  364.             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
  365.             p_data += i_copy;
  366.         }
  367.         i_offset = 0;
  368.         if( !i_size ) break;
  369.     }
  370.     return VLC_SUCCESS;
  371. }
  372. static inline int block_FindStartcodeFromOffset(
  373.     block_bytestream_t *p_bytestream, int *pi_offset,
  374.     uint8_t *p_startcode, int i_startcode_length )
  375. {
  376.     block_t *p_block, *p_block_backup = 0;
  377.     int i_size, i_offset, i_offset_backup = 0;
  378.     int i_caller_offset_backup = 0, i_match;
  379.     /* Find the right place */
  380.     i_size = *pi_offset + p_bytestream->i_offset;
  381.     for( p_block = p_bytestream->p_block;
  382.          p_block != NULL; p_block = p_block->p_next )
  383.     {
  384.         i_size -= p_block->i_buffer;
  385.         if( i_size < 0 ) break;
  386.     }
  387.     if( i_size >= 0 )
  388.     {
  389.         /* Not enough data, bail out */
  390.         return VLC_EGENERIC;
  391.     }
  392.     /* Begin the search.
  393.      * We first look for an occurrence of the 1st startcode byte and
  394.      * if found, we do a more thorough check. */
  395.     i_size = p_block->i_buffer + i_size;
  396.     *pi_offset -= i_size;
  397.     i_match = 0;
  398.     for( ; p_block != NULL; p_block = p_block->p_next )
  399.     {
  400.         for( i_offset = i_size; i_offset < p_block->i_buffer; i_offset++ )
  401.         {
  402.             if( p_block->p_buffer[i_offset] == p_startcode[i_match] )
  403.             {
  404.                 if( !i_match )
  405.                 {
  406.                     p_block_backup = p_block;
  407.                     i_offset_backup = i_offset;
  408.                     i_caller_offset_backup = *pi_offset;
  409.                 }
  410.                 if( i_match + 1 == i_startcode_length )
  411.                 {
  412.                     /* We have it */
  413.                     *pi_offset += i_offset - i_match;
  414.                     return VLC_SUCCESS;
  415.                 }
  416.                 i_match++;
  417.             }
  418.             else if ( i_match )
  419.             {
  420.                 /* False positive */
  421.                 p_block = p_block_backup;
  422.                 i_offset = i_offset_backup;
  423.                 *pi_offset = i_caller_offset_backup;
  424.                 i_match = 0;
  425.             }
  426.         }
  427.         i_size = 0;
  428.         *pi_offset += i_offset;
  429.     }
  430.     *pi_offset -= i_match;
  431.     return VLC_EGENERIC;
  432. }
  433. #endif /* VLC_BLOCK_HELPER_H */