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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * packetizer.h: Packetizer helpers
  3.  *****************************************************************************
  4.  * Copyright (C) 2009 Laurent Aimar
  5.  * $Id: 1c6e67b205a9fa0e40c2e4e641f074fcfc70c3bd $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
  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 _PACKETIZER_H
  24. #define _PACKETIZER_H 1
  25. #include <vlc_block.h>
  26. enum
  27. {
  28.     STATE_NOSYNC,
  29.     STATE_NEXT_SYNC
  30. };
  31. typedef void (*packetizer_reset_t)( void *p_private, bool b_broken );
  32. typedef block_t *(*packetizer_parse_t)( void *p_private, bool *pb_ts_used, block_t * );
  33. typedef int (*packetizer_validate_t)( void *p_private, block_t * );
  34. typedef struct
  35. {
  36.     int i_state;
  37.     block_bytestream_t bytestream;
  38.     size_t i_offset;
  39.     bool   b_flushing;
  40.     int i_startcode;
  41.     const uint8_t *p_startcode;
  42.     int i_au_prepend;
  43.     const uint8_t *p_au_prepend;
  44.     void *p_private;
  45.     packetizer_reset_t    pf_reset;
  46.     packetizer_parse_t    pf_parse;
  47.     packetizer_validate_t pf_validate;
  48. } packetizer_t;
  49. static inline void packetizer_Init( packetizer_t *p_pack,
  50.                                     const uint8_t *p_startcode, int i_startcode,
  51.                                     const uint8_t *p_au_prepend, int i_au_prepend,
  52.                                     packetizer_reset_t pf_reset,
  53.                                     packetizer_parse_t pf_parse,
  54.                                     packetizer_validate_t pf_validate,
  55.                                     void *p_private )
  56. {
  57.     p_pack->i_state = STATE_NOSYNC;
  58.     p_pack->bytestream = block_BytestreamInit();
  59.     p_pack->i_offset = 0;
  60.     p_pack->b_flushing = false;
  61.     p_pack->i_au_prepend = i_au_prepend;
  62.     p_pack->p_au_prepend = p_au_prepend;
  63.     p_pack->i_startcode = i_startcode;
  64.     p_pack->p_startcode = p_startcode;
  65.     p_pack->pf_reset = pf_reset;
  66.     p_pack->pf_parse = pf_parse;
  67.     p_pack->pf_validate = pf_validate;
  68.     p_pack->p_private = p_private;
  69. }
  70. static inline void packetizer_Clean( packetizer_t *p_pack )
  71. {
  72.     block_BytestreamRelease( &p_pack->bytestream );
  73. }
  74. static inline block_t *packetizer_Packetize( packetizer_t *p_pack, block_t **pp_block )
  75. {
  76.     if( !pp_block || !*pp_block )
  77.         return NULL;
  78.     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
  79.     {
  80.         const bool b_broken = ( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED ) != 0;
  81.         if( b_broken )
  82.         {
  83.             p_pack->i_state = STATE_NOSYNC;
  84.             block_BytestreamEmpty( &p_pack->bytestream );
  85.             p_pack->i_offset = 0;
  86.         }
  87.         p_pack->pf_reset( p_pack->p_private, b_broken );
  88.         block_Release( *pp_block );
  89.         return NULL;
  90.     }
  91.     block_BytestreamPush( &p_pack->bytestream, *pp_block );
  92.     for( ;; )
  93.     {
  94.         bool b_used_ts;
  95.         block_t *p_pic;
  96.         switch( p_pack->i_state )
  97.         {
  98.         case STATE_NOSYNC:
  99.             /* Find a startcode */
  100.             if( !block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
  101.                                                 p_pack->p_startcode, p_pack->i_startcode ) )
  102.                 p_pack->i_state = STATE_NEXT_SYNC;
  103.             if( p_pack->i_offset )
  104.             {
  105.                 block_SkipBytes( &p_pack->bytestream, p_pack->i_offset );
  106.                 p_pack->i_offset = 0;
  107.                 block_BytestreamFlush( &p_pack->bytestream );
  108.             }
  109.             if( p_pack->i_state != STATE_NEXT_SYNC )
  110.                 return NULL; /* Need more data */
  111.             p_pack->i_offset = 1; /* To find next startcode */
  112.         case STATE_NEXT_SYNC:
  113.             /* Find the next startcode */
  114.             if( block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
  115.                                                p_pack->p_startcode, p_pack->i_startcode ) )
  116.             {
  117.                 if( !p_pack->b_flushing || !p_pack->bytestream.p_chain )
  118.                     return NULL; /* Need more data */
  119.                 /* When flusing and we don't find a startcode, suppose that
  120.                  * the data extend up to the end */
  121.                 block_ChainProperties( p_pack->bytestream.p_chain,
  122.                                        NULL, &p_pack->i_offset, NULL );
  123.                 p_pack->i_offset -= p_pack->bytestream .i_offset;
  124.                 if( p_pack->i_offset <= (size_t)p_pack->i_startcode )
  125.                     return NULL;
  126.             }
  127.             block_BytestreamFlush( &p_pack->bytestream );
  128.             /* Get the new fragment and set the pts/dts */
  129.             block_t *p_block_bytestream = p_pack->bytestream.p_block;
  130.             p_pic = block_New( p_dec, p_pack->i_offset + p_pack->i_au_prepend );
  131.             p_pic->i_pts = p_block_bytestream->i_pts;
  132.             p_pic->i_dts = p_block_bytestream->i_dts;
  133.             block_GetBytes( &p_pack->bytestream, &p_pic->p_buffer[p_pack->i_au_prepend],
  134.                             p_pic->i_buffer - p_pack->i_au_prepend );
  135.             if( p_pack->i_au_prepend > 0 )
  136.                 memcpy( p_pic->p_buffer, p_pack->p_au_prepend, p_pack->i_au_prepend );
  137.             p_pack->i_offset = 0;
  138.             /* Parse the NAL */
  139.             p_pic = p_pack->pf_parse( p_pack->p_private, &b_used_ts, p_pic );
  140.             if( b_used_ts )
  141.             {
  142.                 p_block_bytestream->i_dts = -1;
  143.                 p_block_bytestream->i_pts = -1;
  144.             }
  145.             if( !p_pic )
  146.             {
  147.                 p_pack->i_state = STATE_NOSYNC;
  148.                 break;
  149.             }
  150.             if( p_pack->pf_validate( p_pack->p_private, p_pic ) )
  151.             {
  152.                 p_pack->i_state = STATE_NOSYNC;
  153.                 block_Release( p_pic );
  154.                 break;
  155.             }
  156.             /* So p_block doesn't get re-added several times */
  157.             *pp_block = block_BytestreamPop( &p_pack->bytestream );
  158.             p_pack->i_state = STATE_NOSYNC;
  159.             return p_pic;
  160.         }
  161.     }
  162. }
  163. static inline void packetizer_Header( packetizer_t *p_pack,
  164.                                       const uint8_t *p_header, int i_header )
  165. {
  166.     block_t *p_init = block_Alloc( i_header );
  167.     if( !p_init )
  168.         return;
  169.     memcpy( p_init->p_buffer, p_header, i_header );
  170.     p_pack->b_flushing = true;
  171.     block_t *p_pic;
  172.     while( ( p_pic = packetizer_Packetize( p_pack, &p_init ) ) )
  173.         block_Release( p_pic ); /* Should not happen (only sequence header) */
  174.     p_pack->i_state = STATE_NOSYNC;
  175.     block_BytestreamEmpty( &p_pack->bytestream );
  176.     p_pack->i_offset = 0;
  177.     p_pack->b_flushing = false;
  178. }
  179. #endif