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 <jamrial@gmail.com>
This commit is contained in:
foo86 2017-07-10 17:11:33 +03:00 committed by James Almer
parent 9e37cc1101
commit 2123ddb425
3 changed files with 111 additions and 2 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -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, \