avcodec: add avpriv_dca_parse_core_frame_header()
authorfoo86 <foobaz86@gmail.com>
Mon, 10 Jul 2017 14:11:33 +0000 (17:11 +0300)
committerJames Almer <jamrial@gmail.com>
Wed, 19 Jul 2017 00:04:56 +0000 (21:04 -0300)
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>
libavcodec/dca.c
libavcodec/dca.h
libavcodec/version.h

index fb79619..39f8f3d 100644 (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;
+}
index 1d10de4..cf6204e 100644 (file)
 #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 */
index 096b062..5b99785 100644 (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, \