From 2123ddb4251bf39bde8b38a1307a0f6154d260e6 Mon Sep 17 00:00:00 2001 From: foo86 Date: Mon, 10 Jul 2017 17:11:33 +0300 Subject: [PATCH] avcodec: add avpriv_dca_parse_core_frame_header() There are 3 different places where DCA core frame header is parsed: decoder, parser and demuxer. Each one uses ad-hoc code. Add common core frame header parsing function that will be used in all places. Signed-off-by: James Almer --- libavcodec/dca.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ libavcodec/dca.h | 49 ++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +-- 3 files changed, 111 insertions(+), 2 deletions(-) diff --git a/libavcodec/dca.c b/libavcodec/dca.c index fb796191d6..39f8f3d81c 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -28,7 +28,9 @@ #include "libavutil/error.h" #include "dca.h" +#include "dca_core.h" #include "dca_syncwords.h" +#include "get_bits.h" #include "put_bits.h" const uint32_t avpriv_dca_sample_rates[16] = { @@ -85,3 +87,61 @@ int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, return AVERROR_INVALIDDATA; } } + +int avpriv_dca_parse_core_frame_header(GetBitContext *gb, DCACoreFrameHeader *h) +{ + if (get_bits_long(gb, 32) != DCA_SYNCWORD_CORE_BE) + return DCA_PARSE_ERROR_SYNC_WORD; + + h->normal_frame = get_bits1(gb); + h->deficit_samples = get_bits(gb, 5) + 1; + if (h->deficit_samples != DCA_PCMBLOCK_SAMPLES) + return DCA_PARSE_ERROR_DEFICIT_SAMPLES; + + h->crc_present = get_bits1(gb); + h->npcmblocks = get_bits(gb, 7) + 1; + if (h->npcmblocks & (DCA_SUBBAND_SAMPLES - 1)) + return DCA_PARSE_ERROR_PCM_BLOCKS; + + h->frame_size = get_bits(gb, 14) + 1; + if (h->frame_size < 96) + return DCA_PARSE_ERROR_FRAME_SIZE; + + h->audio_mode = get_bits(gb, 6); + if (h->audio_mode >= DCA_AMODE_COUNT) + return DCA_PARSE_ERROR_AMODE; + + h->sr_code = get_bits(gb, 4); + if (!avpriv_dca_sample_rates[h->sr_code]) + return DCA_PARSE_ERROR_SAMPLE_RATE; + + h->br_code = get_bits(gb, 5); + if (get_bits1(gb)) + return DCA_PARSE_ERROR_RESERVED_BIT; + + h->drc_present = get_bits1(gb); + h->ts_present = get_bits1(gb); + h->aux_present = get_bits1(gb); + h->hdcd_master = get_bits1(gb); + h->ext_audio_type = get_bits(gb, 3); + h->ext_audio_present = get_bits1(gb); + h->sync_ssf = get_bits1(gb); + h->lfe_present = get_bits(gb, 2); + if (h->lfe_present == DCA_LFE_FLAG_INVALID) + return DCA_PARSE_ERROR_LFE_FLAG; + + h->predictor_history = get_bits1(gb); + if (h->crc_present) + skip_bits(gb, 16); + h->filter_perfect = get_bits1(gb); + h->encoder_rev = get_bits(gb, 4); + h->copy_hist = get_bits(gb, 2); + h->pcmr_code = get_bits(gb, 3); + if (!ff_dca_bits_per_sample[h->pcmr_code]) + return DCA_PARSE_ERROR_PCM_RES; + + h->sumdiff_front = get_bits1(gb); + h->sumdiff_surround = get_bits1(gb); + h->dn_code = get_bits(gb, 4); + return 0; +} diff --git a/libavcodec/dca.h b/libavcodec/dca.h index 1d10de4b94..cf6204e554 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -32,6 +32,49 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" +#include "get_bits.h" + +#define DCA_CORE_FRAME_HEADER_SIZE 18 + +enum DCAParseError { + DCA_PARSE_ERROR_SYNC_WORD = -1, + DCA_PARSE_ERROR_DEFICIT_SAMPLES = -2, + DCA_PARSE_ERROR_PCM_BLOCKS = -3, + DCA_PARSE_ERROR_FRAME_SIZE = -4, + DCA_PARSE_ERROR_AMODE = -5, + DCA_PARSE_ERROR_SAMPLE_RATE = -6, + DCA_PARSE_ERROR_RESERVED_BIT = -7, + DCA_PARSE_ERROR_LFE_FLAG = -8, + DCA_PARSE_ERROR_PCM_RES = -9 +}; + +typedef struct DCACoreFrameHeader { + uint8_t normal_frame; ///< Frame type + uint8_t deficit_samples; ///< Deficit sample count + uint8_t crc_present; ///< CRC present flag + uint8_t npcmblocks; ///< Number of PCM sample blocks + uint16_t frame_size; ///< Primary frame byte size + uint8_t audio_mode; ///< Audio channel arrangement + uint8_t sr_code; ///< Core audio sampling frequency + uint8_t br_code; ///< Transmission bit rate + uint8_t drc_present; ///< Embedded dynamic range flag + uint8_t ts_present; ///< Embedded time stamp flag + uint8_t aux_present; ///< Auxiliary data flag + uint8_t hdcd_master; ///< HDCD mastering flag + uint8_t ext_audio_type; ///< Extension audio descriptor flag + uint8_t ext_audio_present; ///< Extended coding flag + uint8_t sync_ssf; ///< Audio sync word insertion flag + uint8_t lfe_present; ///< Low frequency effects flag + uint8_t predictor_history; ///< Predictor history flag switch + uint8_t filter_perfect; ///< Multirate interpolator switch + uint8_t encoder_rev; ///< Encoder software revision + uint8_t copy_hist; ///< Copy history + uint8_t pcmr_code; ///< Source PCM resolution + uint8_t sumdiff_front; ///< Front sum/difference flag + uint8_t sumdiff_surround; ///< Surround sum/difference flag + uint8_t dn_code; ///< Dialog normalization / unspecified +} DCACoreFrameHeader; + enum DCASpeaker { DCA_SPEAKER_C, DCA_SPEAKER_L, DCA_SPEAKER_R, DCA_SPEAKER_Ls, DCA_SPEAKER_Rs, DCA_SPEAKER_LFE1, DCA_SPEAKER_Cs, DCA_SPEAKER_Lsr, @@ -165,4 +208,10 @@ extern const uint8_t ff_dca_bits_per_sample[8]; int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, int max_size); +/** + * Parse and validate core frame header + * @return 0 on success, negative DCA_PARSE_ERROR_ code on failure + */ +int avpriv_dca_parse_core_frame_header(GetBitContext *gb, DCACoreFrameHeader *h); + #endif /* AVCODEC_DCA_H */ diff --git a/libavcodec/version.h b/libavcodec/version.h index 096b062e97..5b99785a72 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 57 -#define LIBAVCODEC_VERSION_MINOR 100 -#define LIBAVCODEC_VERSION_MICRO 104 +#define LIBAVCODEC_VERSION_MINOR 101 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \