From 7760b096a26c12839755d5231c4bf69d7a7d752f Mon Sep 17 00:00:00 2001 From: Christophe Massiot Date: Fri, 19 Jul 2013 12:00:37 +0200 Subject: [PATCH] add MPEG audio parsing + complete ADTS --- mpeg/aac.h | 83 +++++++++++++++++---- mpeg/mpga.h | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 277 insertions(+), 16 deletions(-) create mode 100644 mpeg/mpga.h diff --git a/mpeg/aac.h b/mpeg/aac.h index cb5b59c..78f439f 100644 --- a/mpeg/aac.h +++ b/mpeg/aac.h @@ -1,7 +1,7 @@ /***************************************************************************** * aac.h: ISO/IEC 14496-3 Advanced Audio Coding ***************************************************************************** - * Copyright (C) 2010 VideoLAN + * Copyright (C) 2010, 2013 VideoLAN * * Authors: Christophe Massiot * @@ -46,6 +46,7 @@ extern "C" * ADTS header *****************************************************************************/ #define ADTS_HEADER_SIZE 7 +#define ADTS_SAMPLES_PER_BLOCK 1024 /* fixed header */ static inline void adts_set_sync(uint8_t *p_adts) @@ -59,16 +60,41 @@ static inline void adts_set_sync(uint8_t *p_adts) p_adts[6] = 0x0; } +static inline bool adts_get_protection_absent(const uint8_t *p_adts) +{ + return !!(p_adts[1] & 0x01); +} + +static inline void adts_clear_protection_absent(uint8_t *p_adts) +{ + p_adts[1] &= ~0x01; +} + +static inline uint8_t adts_get_profile(const uint8_t *p_adts) +{ + return p_adts[2] >> 6; +} + static inline void adts_set_profile(uint8_t *p_adts, uint8_t i_profile) { p_adts[2] &= ~0xc0; p_adts[2] |= i_profile << 6; } -static inline void adts_set_index(uint8_t *p_adts, uint8_t i_index) +static inline uint8_t adts_get_sampling_freq(const uint8_t *p_adts) +{ + return (p_adts[2] & 0x3c) >> 2; +} + +static inline void adts_set_sampling_freq(uint8_t *p_adts, uint8_t i_freq) { p_adts[2] &= ~0x3c; - p_adts[2] |= (i_index & 0xf) << 2; + p_adts[2] |= (i_freq & 0xf) << 2; +} + +static inline uint8_t adts_get_channels(const uint8_t *p_adts) +{ + return ((p_adts[2] & 0x01) << 2) | (p_adts[3] >> 6); } static inline void adts_set_channels(uint8_t *p_adts, uint8_t i_channels) @@ -79,23 +105,33 @@ static inline void adts_set_channels(uint8_t *p_adts, uint8_t i_channels) p_adts[3] |= (i_channels & 0x7) << 6; } -static inline void adts_set_copy(uint8_t *p_adts, bool b_copy) +static inline bool adts_get_copy(const uint8_t *p_adts) { - if (!b_copy) - p_adts[3] &= ~0x20; - else - p_adts[3] |= 0x20; + return !!(p_adts[3] & 0x20); } -static inline void adts_set_home(uint8_t *p_adts, bool b_home) +static inline void adts_set_copy(uint8_t *p_adts) { - if (!b_home) - p_adts[3] &= ~0x10; - else - p_adts[3] |= 0x10; + p_adts[3] |= 0x20; +} + +static inline bool adts_get_home(const uint8_t *p_adts) +{ + return !!(p_adts[3] & 0x10); +} + +static inline void adts_set_home(uint8_t *p_adts) +{ + p_adts[3] |= 0x10; } /* variable header */ +static inline void adts_get_cp_id(const uint8_t *p_adts, bool *pb_bit, bool *pb_start) +{ + *pb_bit = !!(p_adts[3] & 0x08); + *pb_start = !!(p_adts[3] & 0x04); +} + static inline void adts_set_cp_id(uint8_t *p_adts, bool b_bit, bool b_start) { p_adts[3] &= ~0x0c; @@ -105,6 +141,11 @@ static inline void adts_set_cp_id(uint8_t *p_adts, bool b_bit, bool b_start) p_adts[3] |= 0x04; } +static inline uint16_t adts_get_length(const uint8_t *p_adts) +{ + return ((p_adts[3] & 0x03) << 11) | (p_adts[4] << 3) | (p_adts[5] >> 5); +} + static inline void adts_set_length(uint8_t *p_adts, uint16_t i_length) { p_adts[3] &= ~0x03; @@ -114,6 +155,11 @@ static inline void adts_set_length(uint8_t *p_adts, uint16_t i_length) p_adts[5] |= (i_length << 5) & 0xe0; } +static inline uint16_t adts_get_fullness(const uint8_t *p_adts) +{ + return ((p_adts[5] & 0x1f) << 6) | (p_adts[6] >> 2); +} + static inline void adts_set_fullness(uint8_t *p_adts, uint16_t i_fullness) { p_adts[5] &= ~0x1f; @@ -122,11 +168,16 @@ static inline void adts_set_fullness(uint8_t *p_adts, uint16_t i_fullness) p_adts[6] |= (i_fullness << 2) & 0xfc; } -/* i_blocks == number of blocks - 1 */ -static inline void adts_set_num_blocks(uint8_t *p_adts, uint8_t i_blocks) +/* blocks == number of blocks - 1 */ +static inline uint8_t adts_get_num_blocks(const uint8_t *p_adts) +{ + return (p_adts[6] & 0x03); +} + +static inline void adts_set_num_blocks(uint8_t *p_adts, uint8_t i_blocks_min1) { p_adts[6] &= ~0x03; - p_adts[6] |= i_blocks & 0x03; + p_adts[6] |= i_blocks_min1 & 0x03; } #ifdef __cplusplus diff --git a/mpeg/mpga.h b/mpeg/mpga.h new file mode 100644 index 0000000..57b773d --- /dev/null +++ b/mpeg/mpga.h @@ -0,0 +1,210 @@ +/***************************************************************************** + * mpga.h: ISO/IEC 11172-3 and 13818-3 MPEG audio + ***************************************************************************** + * Copyright (C) 2013 VideoLAN + * + * Authors: Christophe Massiot + * + * 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: + * - ISO/IEC 11172-3 + * - ISO/IEC 13818-3 + */ + +#ifndef __BITSTREAM_MPEG_MPGA_H__ +#define __BITSTREAM_MPEG_MPGA_H__ + +#include /* uint8_t, uint16_t, etc... */ +#include /* bool */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** + * MPEG audio header + *****************************************************************************/ +#define MPGA_HEADER_SIZE 4 + +#define MPGA_ID_1 1 +#define MPGA_ID_2 0 + +#define MPGA_LAYER_1 3 +#define MPGA_LAYER_2 2 +#define MPGA_LAYER_3 1 +#define MPGA_LAYER_ADTS 0 + +#define MPGA_BITRATE_INVALID 15 +#define MPGA_SAMPLERATE_INVALID 3 + +#define MPGA_MODE_STEREO 0 +#define MPGA_MODE_JOINT 1 +#define MPGA_MODE_DUAL_MONO 2 +#define MPGA_MODE_MONO 3 + +#define MPGA_EMPHASIS_NONE 0 +#define MPGA_EMPHASIS_50_15 1 +#define MPGA_EMPHASIS_INVALID 2 +#define MPGA_EMPHASIS_J_17 3 + +static inline void mpga_set_sync(uint8_t *p_mpga) +{ + p_mpga[0] = 0xff; + p_mpga[1] = 0xf9; + p_mpga[2] = 0x0; + p_mpga[3] = 0x0; +} + +/* unofficial extension */ +static inline bool mpga_get_mpeg25(const uint8_t *p_mpga) +{ + return !(p_mpga[1] & 0x10); +} + +static inline void mpga_set_mpeg25(uint8_t *p_mpga) +{ + p_mpga[1] &= ~0x10; +} + +static inline bool mpga_get_id(const uint8_t *p_mpga) +{ + return !!(p_mpga[1] & 0x08); +} + +static inline void mpga_clear_id(uint8_t *p_mpga) +{ + p_mpga[1] &= ~0x08; +} + +static inline uint8_t mpga_get_layer(const uint8_t *p_mpga) +{ + return (p_mpga[1] & 0x06) >> 1; +} + +static inline void mpga_set_layer(uint8_t *p_mpga, uint8_t i_layer) +{ + p_mpga[1] &= ~0x06; + p_mpga[1] |= (i_layer & 0x3) << 1; +} + +static inline bool mpga_get_protection_absent(const uint8_t *p_mpga) +{ + return !!(p_mpga[1] & 0x01); +} + +static inline void mpga_clear_protection_absent(uint8_t *p_mpga) +{ + p_mpga[1] &= ~0x01; +} + +static inline uint8_t mpga_get_bitrate_index(const uint8_t *p_mpga) +{ + return p_mpga[2] >> 4; +} + +static inline void mpga_set_bitrate_index(uint8_t *p_mpga, uint8_t i_index) +{ + p_mpga[2] &= ~0xf0; + p_mpga[2] |= i_index << 4; +} + +static inline uint8_t mpga_get_sampling_freq(const uint8_t *p_mpga) +{ + return (p_mpga[2] & 0xc) >> 2; +} + +static inline void mpga_set_sampling_freq(uint8_t *p_mpga, uint8_t i_freq) +{ + p_mpga[2] &= ~0x0c; + p_mpga[2] |= (i_freq & 0x3) << 2; +} + +static inline bool mpga_get_padding(const uint8_t *p_mpga) +{ + return !!(p_mpga[2] & 0x02); +} + +static inline void mpga_set_padding(uint8_t *p_mpga) +{ + p_mpga[2] |= 0x02; +} + +static inline uint8_t mpga_get_mode(const uint8_t *p_mpga) +{ + return (p_mpga[3] & 0xc0) >> 6; +} + +static inline void mpga_set_mode(uint8_t *p_mpga, uint8_t i_mode) +{ + p_mpga[3] &= ~0xc0; + p_mpga[3] |= i_mode << 6; +} + +static inline uint8_t mpga_get_mode_ext(const uint8_t *p_mpga) +{ + return (p_mpga[3] & 0x30) >> 4; +} + +static inline void mpga_set_mode_ext(uint8_t *p_mpga, uint8_t i_mode_ext) +{ + p_mpga[3] &= ~0x30; + p_mpga[3] |= (i_mode_ext & 0x3) << 4; +} + +static inline bool mpga_get_copyright(const uint8_t *p_mpga) +{ + return !!(p_mpga[3] & 0x80); +} + +static inline void mpga_set_copyright(uint8_t *p_mpga) +{ + p_mpga[3] |= 0x80; +} + +static inline bool mpga_get_original(const uint8_t *p_mpga) +{ + return !!(p_mpga[3] & 0x40); +} + +static inline void mpga_set_original(uint8_t *p_mpga) +{ + p_mpga[3] |= 0x40; +} + +static inline uint8_t mpga_get_emphasis(const uint8_t *p_mpga) +{ + return p_mpga[3] & 0x03; +} + +static inline void mpga_set_emphasis(uint8_t *p_mpga, uint8_t i_emphasis) +{ + p_mpga[3] &= ~0x03; + p_mpga[3] |= i_emphasis & 0x03; +} + +#ifdef __cplusplus +} +#endif + +#endif