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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * a52.h
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2009 Laurent Aimar
  5.  * $Id: 204be334fd9b8dfbe22ac1b191f65676d80efe8d $
  6.  *
  7.  * Authors: Stéphane Borel <stef@via.ecp.fr>
  8.  *          Christophe Massiot <massiot@via.ecp.fr>
  9.  *          Gildas Bazin <gbazin@videolan.org>
  10.  *          Laurent Aimar <fenrir@via.ecp.fr>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  25.  *****************************************************************************/
  26. #ifndef _VLC_A52_H
  27. #define _VLC_A52_H 1
  28. #include <vlc_aout.h>
  29. #include <vlc_bits.h>
  30. typedef struct
  31. {
  32.     unsigned int i_count;
  33.     unsigned int i_configuration;
  34. } vlc_a52_acmod_t;
  35. /**
  36.  * Minimum AC3 header size that vlc_a52_header_Parse needs.
  37.  */
  38. #define VLC_A52_HEADER_SIZE (8)
  39. /**
  40.  * AC3 header information.
  41.  */
  42. typedef struct
  43. {
  44.     bool b_eac3;
  45.     unsigned int i_channels;
  46.     unsigned int i_channels_conf;
  47.     unsigned int i_rate;
  48.     unsigned int i_bitrate;
  49.     unsigned int i_size;
  50.     unsigned int i_samples;
  51. } vlc_a52_header_t;
  52. /**
  53.  * It parse AC3 sync info.
  54.  *
  55.  * This code is borrowed from liba52 by Aaron Holtzman & Michel Lespinasse,
  56.  * since we don't want to oblige S/PDIF people to use liba52 just to get
  57.  * their SyncInfo...
  58.  */
  59. static inline int vlc_a52_header_ParseAc3( vlc_a52_header_t *p_header,
  60.                                            const uint8_t *p_buf,
  61.                                            const vlc_a52_acmod_t *p_acmod )
  62. {
  63.     static const uint8_t pi_halfrate[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
  64.     static const unsigned int pi_bitrate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
  65.                                 128, 160, 192, 224, 256, 320, 384, 448,
  66.                                 512, 576, 640 };
  67.     static const uint8_t pi_lfeon[8] = { 0x10, 0x10, 0x04, 0x04,
  68.                                       0x04, 0x01, 0x04, 0x01 };
  69.     /* */
  70.     const unsigned i_rate_shift = pi_halfrate[p_buf[5] >> 3];
  71.     /* acmod, dsurmod and lfeon */
  72.     const unsigned i_acmod = p_buf[6] >> 5;
  73.     if( (p_buf[6] & 0xf8) == 0x50 )
  74.     {
  75.         /* Dolby surround = stereo + Dolby */
  76.         p_header->i_channels = 2;
  77.         p_header->i_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
  78.                             | AOUT_CHAN_DOLBYSTEREO;
  79.     }
  80.     else
  81.     {
  82.         p_header->i_channels      = p_acmod[i_acmod].i_count;
  83.         p_header->i_channels_conf = p_acmod[i_acmod].i_configuration;
  84.     }
  85.     if( p_buf[6] & pi_lfeon[i_acmod] )
  86.     {
  87.         p_header->i_channels++;
  88.         p_header->i_channels_conf |= AOUT_CHAN_LFE;
  89.     }
  90.     const unsigned i_frmsizecod = p_buf[4] & 63;
  91.     if( i_frmsizecod >= 38 )
  92.         return VLC_EGENERIC;
  93.     const unsigned i_bitrate_base = pi_bitrate[i_frmsizecod >> 1];
  94.     p_header->i_bitrate = (i_bitrate_base * 1000) >> i_rate_shift;
  95.     switch( p_buf[4] & 0xc0 )
  96.     {
  97.     case 0:
  98.         p_header->i_rate = 48000 >> i_rate_shift;
  99.         p_header->i_size = 4 * i_bitrate_base;
  100.         break;
  101.     case 0x40:
  102.         p_header->i_rate = 44100 >> i_rate_shift;
  103.         p_header->i_size = 2 * (320 * i_bitrate_base / 147 + (i_frmsizecod & 1));
  104.         break;
  105.     case 0x80:
  106.         p_header->i_rate = 32000 >> i_rate_shift;
  107.         p_header->i_size = 6 * i_bitrate_base;
  108.         break;
  109.     default:
  110.         return VLC_EGENERIC;
  111.     }
  112.     p_header->i_samples = 6*256;
  113.     p_header->b_eac3 = false;
  114.     return VLC_SUCCESS;
  115. }
  116. /**
  117.  * It parse E-AC3 sync info
  118.  */
  119. static inline int vlc_a52_header_ParseEac3( vlc_a52_header_t *p_header,
  120.                                             const uint8_t *p_buf,
  121.                                             const vlc_a52_acmod_t *p_acmod )
  122. {
  123.     static const unsigned pi_samplerate[3] = { 48000, 44100, 32000 };
  124.     unsigned i_numblkscod;
  125.     bs_t s;
  126.     bs_init( &s, (void*)p_buf, VLC_A52_HEADER_SIZE );
  127.     bs_skip( &s, 16 +   /* start code */
  128.                  2 +    /* stream type */
  129.                  3 );   /* substream id */
  130.     const unsigned i_frame_size = bs_read( &s, 11 );
  131.     if( i_frame_size < 2 )
  132.         return VLC_EGENERIC;
  133.     p_header->i_size = 2 * ( i_frame_size + 1 );
  134.     const unsigned i_fscod = bs_read( &s, 2 );
  135.     if( i_fscod == 0x03 )
  136.     {
  137.         const unsigned i_fscod2 = bs_read( &s, 2 );
  138.         if( i_fscod2 == 0X03 )
  139.             return VLC_EGENERIC;
  140.         p_header->i_rate = pi_samplerate[i_fscod2] / 2;
  141.         i_numblkscod = 6;
  142.     }
  143.     else
  144.     {
  145.         static const int pi_blocks[4] = { 1, 2, 3, 6 };
  146.         p_header->i_rate = pi_samplerate[i_fscod];
  147.         i_numblkscod = pi_blocks[bs_read( &s, 2 )];
  148.     }
  149.     const unsigned i_acmod = bs_read( &s, 3 );
  150.     const unsigned i_lfeon = bs_read1( &s );
  151.     p_header->i_channels      = p_acmod[i_acmod].i_count + i_lfeon;
  152.     p_header->i_channels_conf = p_acmod[i_acmod].i_configuration | ( i_lfeon ? AOUT_CHAN_LFE : 0);
  153.     p_header->i_bitrate = 8 * p_header->i_size * (p_header->i_rate) / (i_numblkscod * 256);
  154.     p_header->i_samples = i_numblkscod * 256;
  155.     p_header->b_eac3 = true;
  156.     return VLC_SUCCESS;
  157. }
  158. /**
  159.  * It will parse the header AC3 frame and fill vlc_a52_header_t* if
  160.  * it is valid or return VLC_EGENERIC.
  161.  *
  162.  * XXX It will only recognize big endian bitstream ie starting with 0x0b, 0x77
  163.  */
  164. static inline int vlc_a52_header_Parse( vlc_a52_header_t *p_header,
  165.                                         const uint8_t *p_buffer, int i_buffer )
  166. {
  167.     static const vlc_a52_acmod_t p_acmod[8] = {
  168.         { 2, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_DUALMONO },   /* Dual-channel 1+1 */
  169.         { 1, AOUT_CHAN_CENTER },                                        /* Mono 1/0 */
  170.         { 2, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT },                        /* Stereo 2/0 */
  171.         { 3, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER },     /* 3F 3/0 */
  172.         { 3, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER }, /* 2F1R 2/1 */
  173.         { 4, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
  174.              AOUT_CHAN_REARCENTER },                                    /* 3F1R 3/1 */
  175.         { 4, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
  176.              AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT },                /* 2F2R 2/2 */
  177.         { 5, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
  178.              AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT },                /* 3F2R 3/2 */
  179.     };
  180.     if( i_buffer < VLC_A52_HEADER_SIZE )
  181.         return VLC_EGENERIC;
  182.     /* Check synword */
  183.     if( p_buffer[0] != 0x0b || p_buffer[1] != 0x77 )
  184.         return VLC_EGENERIC;
  185.     /* Check bsid */
  186.     const int bsid = p_buffer[5] >> 3;
  187.     if( bsid > 16 )
  188.         return VLC_EGENERIC;
  189.     if( bsid <= 10 )
  190.     {
  191.         if( vlc_a52_header_ParseAc3( p_header, p_buffer, p_acmod ) )
  192.             return VLC_EGENERIC;
  193.     }
  194.     else
  195.     {
  196.         if( vlc_a52_header_ParseEac3( p_header, p_buffer, p_acmod ) )
  197.             return VLC_EGENERIC;
  198.     }
  199.     return VLC_SUCCESS;
  200. }
  201. #endif