vlc_block_helper.h
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:14k
源码类别:

midi

开发平台:

Unix_Linux

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