/***************************************************************************** * a52.h: ATSC A/52:2012 Digital Audio Compression Standard ***************************************************************************** * Copyright (C) 2013-2018 VideoLAN * * Authors: Benjamin Cohen * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject * to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *****************************************************************************/ /* * Normative references: * - ATSC A/52:2012 */ #ifndef __BITSTREAM_ATSC_A52_H__ #define __BITSTREAM_ATSC_A52_H__ #include /* uint8_t, uint16_t, etc... */ #include /* memcmp */ #include /* bool */ #ifdef __cplusplus extern "C" { #endif #define A52_BSID 8 #define A52_BSID_ANNEX_D 1 #define A52_BSID_ANNEX_E 16 #define A52_FSCOD_48KHZ 0 #define A52_FSCOD_441KHZ 1 #define A52_FSCOD_32KHZ 2 #define A52_FSCOD_RESERVED 3 #define A52_FRAME_SAMPLES 1536 /***************************************************************************** * A/52 syncinfo (A/52:2012 Table 5.1) * - syncword 16 * - crc1 16 * - fscod 2 * - frmsizecod 6 *****************************************************************************/ #define A52_SYNCINFO_SIZE 5 /* A/52 Frame Size Code Table (A/52:2012 Table 5.18) */ static const uint16_t a52_frame_size_code_tab[38][3] = { { 64, 69, 96 }, { 64, 70, 96 }, { 80, 87, 120 }, { 80, 88, 120 }, { 96, 104, 144 }, { 96, 105, 144 }, { 112, 121, 168 }, { 112, 122, 168 }, { 128, 139, 192 }, { 128, 140, 192 }, { 160, 174, 240 }, { 160, 175, 240 }, { 192, 208, 288 }, { 192, 209, 288 }, { 224, 243, 336 }, { 224, 244, 336 }, { 256, 278, 384 }, { 256, 279, 384 }, { 320, 348, 480 }, { 320, 349, 480 }, { 384, 417, 576 }, { 384, 418, 576 }, { 448, 487, 672 }, { 448, 488, 672 }, { 512, 557, 768 }, { 512, 558, 768 }, { 640, 696, 960 }, { 640, 697, 960 }, { 768, 835, 1152 }, { 768, 836, 1152 }, { 896, 975, 1344 }, { 896, 976, 1344 }, { 1024, 1114, 1536 }, { 1024, 1115, 1536 }, { 1152, 1253, 1728 }, { 1152, 1254, 1728 }, { 1280, 1393, 1920 }, { 1280, 1394, 1920 }, }; /* A/52 Bitrate Table (A/52:2012 Table 5.18) */ static const uint16_t a52_bitrate_tab[38] = { 32, 32, 40, 40, 48, 48, 56, 56, 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192, 224, 224, 256, 256, 320, 320, 384, 384, 448, 448, 512, 512, 576, 576, 640, 640 }; static inline uint16_t a52_get_sync(const uint8_t *p_a52) { return (p_a52[0] << 8 | p_a52[1]); } static inline void a52_set_sync(uint8_t *p_a52) { p_a52[0] = 0xb; p_a52[1] = 0x77; } static inline uint16_t a52_get_crc(const uint8_t *p_a52) { return (p_a52[2] << 8 | p_a52[3]); } static inline void a52_set_crc(uint8_t *p_a52, uint16_t i_crc) { p_a52[2] = i_crc >> 8; p_a52[3] = i_crc & 0xff; } static inline uint8_t a52_get_fscod(const uint8_t *p_a52) { return (p_a52[4] & 0xc0) >> 6; } static inline void a52_set_fscod(uint8_t *p_a52, uint8_t i_fscod) { p_a52[4] &= ~0xc0; p_a52[4] |= (i_fscod & 0x3) << 6; } static inline uint8_t a52_get_frmsizecod(const uint8_t *p_a52) { return p_a52[4] & 0x3f; } static inline void a52_set_frmsizecod(uint8_t *p_a52, uint8_t i_frmsizecod) { p_a52[4] &= ~0x3f; p_a52[4] |= i_frmsizecod & 0x3f; } static inline uint16_t a52_get_frame_size(uint8_t i_fscod, uint8_t i_frmsizecod) { i_fscod &= 0x3; if ((i_fscod == A52_FSCOD_RESERVED) || (i_frmsizecod > 37)) { return 0; } return a52_frame_size_code_tab[i_frmsizecod][i_fscod] * 2; } static inline bool a52_sync_compare_formats(const uint8_t *p_a521, const uint8_t *p_a522) { return p_a521[0] == p_a522[0] && p_a521[1] == p_a522[1] && p_a521[4] == p_a522[4]; } /***************************************************************************** * A/52 bsi (Bit Stream Information) *****************************************************************************/ static inline uint8_t a52_get_bsid(const uint8_t *p_a52) { return (p_a52[5] & 0xf8) >> 3; } static inline void a52_set_bsid(uint8_t *p_a52, uint8_t i_bsid) { p_a52[5] &= ~0xf8; p_a52[5] |= (i_bsid & 0xf8) << 3; } static inline uint8_t a52_get_bsmod(const uint8_t *p_a52) { return (p_a52[5] & 0x7); } static inline void a52_set_bsmod(uint8_t *p_a52, uint8_t i_bsid) { p_a52[5] &= ~0x7; p_a52[5] |= i_bsid & 0x7; } static inline uint8_t a52_get_acmod(const uint8_t *p_a52) { return (p_a52[6] & 0xe0) >> 5; } static inline void a52_set_acmod(uint8_t *p_a52, uint8_t i_acmod) { p_a52[6] &= ~0xe0; p_a52[6] |= (i_acmod & 0x7) << 5; } static inline uint8_t a52_get_cmixlev(const uint8_t *p_a52) { return (p_a52[6] & 0x18) >> 3; } static inline void a52_set_cmixlev(uint8_t *p_a52, uint8_t i_cmixlev) { p_a52[6] &= ~0x18; p_a52[6] |= (i_cmixlev & 0x3) << 3; } /***************************************************************************** * A/52 Annex E *****************************************************************************/ #define A52E_FSCOD2_24KHZ 0 #define A52E_FSCOD2_2205KHZ 1 #define A52E_FSCOD2_16KHZ 2 #define A52E_FSCOD2_RESERVED 3 static inline uint8_t a52e_get_strmtyp(const uint8_t *p_a52) { return (p_a52[2] & 0xc0) >> 5; } static inline void a52e_set_strmtyp(uint8_t *p_a52, uint8_t i_strmtyp) { p_a52[2] &= ~0xc0; p_a52[2] |= (i_strmtyp & 0x3) << 6; } static inline uint8_t a52e_get_substreamid(const uint8_t *p_a52) { return (p_a52[2] & 0x38) >> 3; } static inline void a52e_set_substreamid(uint8_t *p_a52, uint8_t i_substreamid) { p_a52[2] &= ~0x38; p_a52[2] |= (i_substreamid & 0x7) << 3; } static inline uint16_t a52e_get_frmsiz(const uint8_t *p_a52) { return ((p_a52[2] & 0x7) << 8) | p_a52[3]; } static inline void a52e_set_frmsiz(uint8_t *p_a52, uint16_t i_frmsiz) { p_a52[2] &= ~0x7; p_a52[2] |= (i_frmsiz >> 8) & 0x7; p_a52[3] = i_frmsiz & 0xff; } static inline uint16_t a52e_get_frame_size(uint16_t i_frmsiz) { return (i_frmsiz + 1) * 2; } static inline uint8_t a52e_get_fscod(const uint8_t *p_a52) { return (p_a52[4] & 0xc0) >> 6; } static inline void a52e_set_fscod(uint8_t *p_a52, uint8_t i_fscod) { p_a52[4] &= ~0xc0; p_a52[4] |= (i_fscod & 0x3) << 6; } static inline uint8_t a52e_get_fscod2(const uint8_t *p_a52) { return (p_a52[4] & 0x30) >> 4; } static inline void a52e_set_fscod2(uint8_t *p_a52, uint8_t i_fscod) { p_a52[4] &= ~0x30; p_a52[4] |= (i_fscod & 0x3) << 4; } static inline uint8_t a52e_get_acmod(const uint8_t *p_a52) { return (p_a52[4] & 0xe) >> 1; } static inline void a52e_set_acmod(uint8_t *p_a52, uint8_t i_acmod) { p_a52[4] &= ~0xe; p_a52[4] |= (i_acmod & 0x7) << 1; } static inline uint8_t a52e_get_lfeon(const uint8_t *p_a52) { return p_a52[4] & 0x1; } static inline void a52e_set_lfeon(uint8_t *p_a52, uint8_t i_lfeon) { p_a52[4] &= ~0x1; p_a52[4] |= i_lfeon & 0x1; } static inline bool a52e_sync_compare_formats(const uint8_t *p_a521, const uint8_t *p_a522) { return !memcmp(p_a521, p_a522, A52_SYNCINFO_SIZE); } #ifdef __cplusplus } #endif #endif