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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * a52.c: parse A/52 audio sync info and packetize the stream
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2002 the VideoLAN team
  5.  * $Id: 474a1d0063f6498f8001ea0b3067785b34ab6c64 $
  6.  *
  7.  * Authors: Stéphane Borel <stef@via.ecp.fr>
  8.  *          Christophe Massiot <massiot@via.ecp.fr>
  9.  *          Gildas Bazin <gbazin@videolan.org>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  24.  *****************************************************************************/
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #ifdef HAVE_CONFIG_H
  29. # include "config.h"
  30. #endif
  31. #include <vlc_common.h>
  32. #include <vlc_plugin.h>
  33. #include <vlc_codec.h>
  34. #include <vlc_aout.h>
  35. #include <vlc_block_helper.h>
  36. #include "a52.h"
  37. /*****************************************************************************
  38.  * Module descriptor
  39.  *****************************************************************************/
  40. static int  OpenDecoder   ( vlc_object_t * );
  41. static int  OpenPacketizer( vlc_object_t * );
  42. static void CloseCommon   ( vlc_object_t * );
  43. vlc_module_begin ()
  44.     set_description( N_("A/52 parser") )
  45.     set_capability( "decoder", 100 )
  46.     set_callbacks( OpenDecoder, CloseCommon )
  47.     set_category( CAT_INPUT )
  48.     set_subcategory( SUBCAT_INPUT_ACODEC )
  49.     add_submodule ()
  50.     set_description( N_("A/52 audio packetizer") )
  51.     set_capability( "packetizer", 10 )
  52.     set_callbacks( OpenPacketizer, CloseCommon )
  53. vlc_module_end ()
  54. /*****************************************************************************
  55.  * decoder_sys_t : decoder descriptor
  56.  *****************************************************************************/
  57. struct decoder_sys_t
  58. {
  59.     /* Module mode */
  60.     bool b_packetizer;
  61.     /*
  62.      * Input properties
  63.      */
  64.     int i_state;
  65.     block_bytestream_t bytestream;
  66.     /*
  67.      * Common properties
  68.      */
  69.     audio_date_t   end_date;
  70.     mtime_t i_pts;
  71.     vlc_a52_header_t frame;
  72. };
  73. enum {
  74.     STATE_NOSYNC,
  75.     STATE_SYNC,
  76.     STATE_HEADER,
  77.     STATE_NEXT_SYNC,
  78.     STATE_GET_DATA,
  79.     STATE_SEND_DATA
  80. };
  81. /****************************************************************************
  82.  * Local prototypes
  83.  ****************************************************************************/
  84. static void *DecodeBlock  ( decoder_t *, block_t ** );
  85. static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
  86. static aout_buffer_t *GetAoutBuffer( decoder_t * );
  87. static block_t       *GetSoutBuffer( decoder_t * );
  88. /*****************************************************************************
  89.  * OpenCommon: probe the decoder/packetizer and return score
  90.  *****************************************************************************/
  91. static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
  92. {
  93.     decoder_t *p_dec = (decoder_t*)p_this;
  94.     decoder_sys_t *p_sys;
  95.     vlc_fourcc_t i_codec;
  96.     switch( p_dec->fmt_in.i_codec )
  97.     {
  98.     case VLC_FOURCC('a','5','2',' '):
  99.     case VLC_FOURCC('a','5','2','b'):
  100.         i_codec = VLC_FOURCC('a','5','2',' ');
  101.         break;
  102.     case VLC_FOURCC('e','a','c','3'):
  103.         /* XXX ugly hack, a52 does not support eac3 so no eac3 pass-through
  104.          * support */
  105.         if( !b_packetizer )
  106.             return VLC_EGENERIC;
  107.         i_codec = VLC_FOURCC('e','a','c','3');
  108.         break;
  109.     default:
  110.         return VLC_EGENERIC;
  111.     }
  112.     /* Allocate the memory needed to store the decoder's structure */
  113.     if( ( p_dec->p_sys = p_sys =
  114.           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
  115.         return VLC_ENOMEM;
  116.     /* Misc init */
  117.     p_sys->b_packetizer = b_packetizer;
  118.     p_sys->i_state = STATE_NOSYNC;
  119.     aout_DateSet( &p_sys->end_date, 0 );
  120.     p_sys->bytestream = block_BytestreamInit();
  121.     /* Set output properties */
  122.     p_dec->fmt_out.i_cat = AUDIO_ES;
  123.     p_dec->fmt_out.i_codec = i_codec;
  124.     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
  125.     p_dec->fmt_out.audio.i_bytes_per_frame = 0;
  126.     /* Set callback */
  127.     if( b_packetizer )
  128.         p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
  129.             DecodeBlock;
  130.     else
  131.         p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
  132.             DecodeBlock;
  133.     return VLC_SUCCESS;
  134. }
  135. static int OpenDecoder( vlc_object_t *p_this )
  136. {
  137.     return OpenCommon( p_this, false );
  138. }
  139. static int OpenPacketizer( vlc_object_t *p_this )
  140. {
  141.     return OpenCommon( p_this, true );
  142. }
  143. /****************************************************************************
  144.  * DecodeBlock: the whole thing
  145.  ****************************************************************************
  146.  * This function is called just after the thread is launched.
  147.  ****************************************************************************/
  148. static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
  149. {
  150.     decoder_sys_t *p_sys = p_dec->p_sys;
  151.     uint8_t p_header[VLC_A52_HEADER_SIZE];
  152.     uint8_t *p_buf;
  153.     void *p_out_buffer;
  154.     if( !pp_block || !*pp_block ) return NULL;
  155.     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
  156.     {
  157.         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
  158.         {
  159.             p_sys->i_state = STATE_NOSYNC;
  160.             block_BytestreamEmpty( &p_sys->bytestream );
  161.         }
  162.         aout_DateSet( &p_sys->end_date, 0 );
  163.         block_Release( *pp_block );
  164.         return NULL;
  165.     }
  166.     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
  167.     {
  168.         /* We've just started the stream, wait for the first PTS. */
  169.         block_Release( *pp_block );
  170.         return NULL;
  171.     }
  172.     block_BytestreamPush( &p_sys->bytestream, *pp_block );
  173.     while( 1 )
  174.     {
  175.         switch( p_sys->i_state )
  176.         {
  177.         case STATE_NOSYNC:
  178.             while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
  179.                    == VLC_SUCCESS )
  180.             {
  181.                 if( p_header[0] == 0x0b && p_header[1] == 0x77 )
  182.                 {
  183.                     p_sys->i_state = STATE_SYNC;
  184.                     break;
  185.                 }
  186.                 block_SkipByte( &p_sys->bytestream );
  187.             }
  188.             if( p_sys->i_state != STATE_SYNC )
  189.             {
  190.                 block_BytestreamFlush( &p_sys->bytestream );
  191.                 /* Need more data */
  192.                 return NULL;
  193.             }
  194.         case STATE_SYNC:
  195.             /* New frame, set the Presentation Time Stamp */
  196.             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
  197.             if( p_sys->i_pts != 0 &&
  198.                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
  199.             {
  200.                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
  201.             }
  202.             p_sys->i_state = STATE_HEADER;
  203.         case STATE_HEADER:
  204.             /* Get A/52 frame header (VLC_A52_HEADER_SIZE bytes) */
  205.             if( block_PeekBytes( &p_sys->bytestream, p_header,
  206.                                  VLC_A52_HEADER_SIZE ) != VLC_SUCCESS )
  207.             {
  208.                 /* Need more data */
  209.                 return NULL;
  210.             }
  211.             /* Check if frame is valid and get frame info */
  212.             if( vlc_a52_header_Parse( &p_sys->frame, p_header, VLC_A52_HEADER_SIZE ) )
  213.             {
  214.                 msg_Dbg( p_dec, "emulated sync word" );
  215.                 block_SkipByte( &p_sys->bytestream );
  216.                 p_sys->i_state = STATE_NOSYNC;
  217.                 break;
  218.             }
  219.             p_sys->i_state = STATE_NEXT_SYNC;
  220.         case STATE_NEXT_SYNC:
  221.             /* TODO: If pp_block == NULL, flush the buffer without checking the
  222.              * next sync word */
  223.             /* Check if next expected frame contains the sync word */
  224.             if( block_PeekOffsetBytes( &p_sys->bytestream,
  225.                                        p_sys->frame.i_size, p_header, 2 )
  226.                 != VLC_SUCCESS )
  227.             {
  228.                 /* Need more data */
  229.                 return NULL;
  230.             }
  231.             if( p_sys->b_packetizer &&
  232.                 p_header[0] == 0 && p_header[1] == 0 )
  233.             {
  234.                 /* A52 wav files and audio CD's use stuffing */
  235.                 p_sys->i_state = STATE_GET_DATA;
  236.                 break;
  237.             }
  238.             if( p_header[0] != 0x0b || p_header[1] != 0x77 )
  239.             {
  240.                 msg_Dbg( p_dec, "emulated sync word "
  241.                          "(no sync on following frame)" );
  242.                 p_sys->i_state = STATE_NOSYNC;
  243.                 block_SkipByte( &p_sys->bytestream );
  244.                 break;
  245.             }
  246.             p_sys->i_state = STATE_SEND_DATA;
  247.             break;
  248.         case STATE_GET_DATA:
  249.             /* Make sure we have enough data.
  250.              * (Not useful if we went through NEXT_SYNC) */
  251.             if( block_WaitBytes( &p_sys->bytestream,
  252.                                  p_sys->frame.i_size ) != VLC_SUCCESS )
  253.             {
  254.                 /* Need more data */
  255.                 return NULL;
  256.             }
  257.             p_sys->i_state = STATE_SEND_DATA;
  258.         case STATE_SEND_DATA:
  259.             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
  260.             {
  261.                 //p_dec->b_error = true;
  262.                 return NULL;
  263.             }
  264.             /* Copy the whole frame into the buffer. When we reach this point
  265.              * we already know we have enough data available. */
  266.             block_GetBytes( &p_sys->bytestream, p_buf, p_sys->frame.i_size );
  267.             /* Make sure we don't reuse the same pts twice */
  268.             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
  269.                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
  270.             /* So p_block doesn't get re-added several times */
  271.             *pp_block = block_BytestreamPop( &p_sys->bytestream );
  272.             p_sys->i_state = STATE_NOSYNC;
  273.             return p_out_buffer;
  274.         }
  275.     }
  276.     return NULL;
  277. }
  278. /*****************************************************************************
  279.  * CloseCommon: clean up the decoder
  280.  *****************************************************************************/
  281. static void CloseCommon( vlc_object_t *p_this )
  282. {
  283.     decoder_t *p_dec = (decoder_t*)p_this;
  284.     decoder_sys_t *p_sys = p_dec->p_sys;
  285.     block_BytestreamRelease( &p_sys->bytestream );
  286.     free( p_sys );
  287. }
  288. /*****************************************************************************
  289.  * GetOutBuffer:
  290.  *****************************************************************************/
  291. static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
  292. {
  293.     decoder_sys_t *p_sys = p_dec->p_sys;
  294.     uint8_t *p_buf;
  295.     if( p_dec->fmt_out.audio.i_rate != p_sys->frame.i_rate )
  296.     {
  297.         msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
  298.                   p_sys->frame.i_channels, p_sys->frame.i_rate, p_sys->frame.i_bitrate );
  299.         aout_DateInit( &p_sys->end_date, p_sys->frame.i_rate );
  300.         aout_DateSet( &p_sys->end_date, p_sys->i_pts );
  301.     }
  302.     p_dec->fmt_out.audio.i_rate     = p_sys->frame.i_rate;
  303.     p_dec->fmt_out.audio.i_channels = p_sys->frame.i_channels;
  304.     if( p_dec->fmt_out.audio.i_bytes_per_frame < p_sys->frame.i_size )
  305.         p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->frame.i_size;
  306.     p_dec->fmt_out.audio.i_frame_length = p_sys->frame.i_samples;
  307.     p_dec->fmt_out.audio.i_original_channels = p_sys->frame.i_channels_conf;
  308.     p_dec->fmt_out.audio.i_physical_channels =
  309.         p_sys->frame.i_channels_conf & AOUT_CHAN_PHYSMASK;
  310.     p_dec->fmt_out.i_bitrate = p_sys->frame.i_bitrate;
  311.     if( p_sys->b_packetizer )
  312.     {
  313.         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
  314.         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
  315.         *pp_out_buffer = p_sout_buffer;
  316.     }
  317.     else
  318.     {
  319.         aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
  320.         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
  321.         *pp_out_buffer = p_aout_buffer;
  322.     }
  323.     return p_buf;
  324. }
  325. /*****************************************************************************
  326.  * GetAoutBuffer:
  327.  *****************************************************************************/
  328. static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
  329. {
  330.     decoder_sys_t *p_sys = p_dec->p_sys;
  331.     aout_buffer_t *p_buf;
  332.     p_buf = decoder_NewAudioBuffer( p_dec, p_sys->frame.i_samples );
  333.     if( p_buf == NULL ) return NULL;
  334.     p_buf->start_date = aout_DateGet( &p_sys->end_date );
  335.     p_buf->end_date = aout_DateIncrement( &p_sys->end_date, p_sys->frame.i_samples );
  336.     return p_buf;
  337. }
  338. /*****************************************************************************
  339.  * GetSoutBuffer:
  340.  *****************************************************************************/
  341. static block_t *GetSoutBuffer( decoder_t *p_dec )
  342. {
  343.     decoder_sys_t *p_sys = p_dec->p_sys;
  344.     block_t *p_block;
  345.     p_block = block_New( p_dec, p_sys->frame.i_size );
  346.     if( p_block == NULL ) return NULL;
  347.     p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
  348.     p_block->i_length =
  349.         aout_DateIncrement( &p_sys->end_date, p_sys->frame.i_samples ) - p_block->i_pts;
  350.     return p_block;
  351. }