aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Ruggles <justin.ruggles@gmail.com>2008-11-13 03:18:07 +0000
committerJustin Ruggles <justin.ruggles@gmail.com>2008-11-13 03:18:07 +0000
commit0c5d750df9d0293b2ce27b6821c3209952c4e6b8 (patch)
tree4592966be28f73400c1c9b47c2801feea58444d7
parent6c6f9272891d17be3e082e34ae60b33c0b31f1e3 (diff)
downloadffmpeg-0c5d750df9d0293b2ce27b6821c3209952c4e6b8.tar.gz
add a generic function to decode banding structure for coupling, spectral
extension, or enhanced coupling Originally committed as revision 15811 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--libavcodec/ac3dec.c84
1 files changed, 67 insertions, 17 deletions
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index 4cb1154f27..3e8b0b5afc 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -711,6 +711,68 @@ static void ac3_upmix_delay(AC3DecodeContext *s)
}
/**
+ * Decode band structure for coupling, spectral extension, or enhanced coupling.
+ * @param[in] gbc bit reader context
+ * @param[in] blk block number
+ * @param[in] eac3 flag to indicate E-AC-3
+ * @param[in] ecpl flag to indicate enhanced coupling
+ * @param[in] start_subband subband number for start of range
+ * @param[in] end_subband subband number for end of range
+ * @param[in] default_band_struct default band structure table
+ * @param[out] band_struct decoded band structure
+ * @param[out] num_subbands number of subbands (optionally NULL)
+ * @param[out] num_bands number of bands (optionally NULL)
+ * @param[out] band_sizes array containing the number of bins in each band (optionally NULL)
+ */
+static void decode_band_structure(GetBitContext *gbc, int blk, int eac3,
+ int ecpl, int start_subband, int end_subband,
+ const uint8_t *default_band_struct,
+ uint8_t *band_struct, int *num_subbands,
+ int *num_bands, int *band_sizes)
+{
+ int subbnd, bnd, n_subbands, n_bands, bnd_sz[22];
+
+ n_subbands = end_subband - start_subband;
+
+ /* decode band structure from bitstream or use default */
+ if (!eac3 || get_bits1(gbc)) {
+ for (subbnd = 0; subbnd < n_subbands - 1; subbnd++) {
+ band_struct[subbnd] = get_bits1(gbc);
+ }
+ } else if (!blk) {
+ memcpy(band_struct,
+ &default_band_struct[start_subband+1],
+ n_subbands-1);
+ }
+ band_struct[n_subbands-1] = 0;
+
+ /* calculate number of bands and band sizes based on band structure.
+ note that the first 4 subbands in enhanced coupling span only 6 bins
+ instead of 12. */
+ if (num_bands || band_sizes ) {
+ n_bands = n_subbands;
+ bnd_sz[0] = ecpl ? 6 : 12;
+ for (bnd = 0, subbnd = 1; subbnd < n_subbands; subbnd++) {
+ int subbnd_size = (ecpl && subbnd < 4) ? 6 : 12;
+ if (band_struct[subbnd-1]) {
+ n_bands--;
+ bnd_sz[bnd] += subbnd_size;
+ } else {
+ bnd_sz[++bnd] = subbnd_size;
+ }
+ }
+ }
+
+ /* set optional output params */
+ if (num_subbands)
+ *num_subbands = n_subbands;
+ if (num_bands)
+ *num_bands = n_bands;
+ if (band_sizes)
+ memcpy(band_sizes, bnd_sz, sizeof(int)*n_bands);
+}
+
+/**
* Decode a single audio block from the AC-3 bitstream.
*/
static int decode_audio_block(AC3DecodeContext *s, int blk)
@@ -812,23 +874,11 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
s->start_freq[CPL_CH] = cpl_start_subband * 12 + 37;
s->end_freq[CPL_CH] = cpl_end_subband * 12 + 37;
- /* coupling band structure */
- s->num_cpl_bands = s->num_cpl_subbands;
- if (!s->eac3 || get_bits1(gbc)) {
- for (bnd = 0; bnd < s->num_cpl_subbands - 1; bnd++) {
- s->cpl_band_struct[bnd] = get_bits1(gbc);
- }
- } else if (!blk) {
- memcpy(s->cpl_band_struct,
- &ff_eac3_default_cpl_band_struct[cpl_start_subband+1],
- s->num_cpl_subbands-1);
- }
- s->cpl_band_struct[s->num_cpl_subbands-1] = 0;
-
- /* calculate number of coupling bands based on band structure */
- for (bnd = 0; bnd < s->num_cpl_subbands-1; bnd++) {
- s->num_cpl_bands -= s->cpl_band_struct[bnd];
- }
+ decode_band_structure(gbc, blk, s->eac3, 0,
+ cpl_start_subband, cpl_end_subband,
+ ff_eac3_default_cpl_band_struct,
+ s->cpl_band_struct, &s->num_cpl_subbands,
+ &s->num_cpl_bands, NULL);
} else {
/* coupling not in use */
for (ch = 1; ch <= fbw_channels; ch++) {