shithub: aacenc

Download patch

ref: 20faadc49d21f56dc1b9a50a5b76774e39153166
parent: 7caf982e9711c30024db3149fca39c6ae5fbee6f
author: corrados <corrados>
date: Sun Jul 4 08:12:05 EDT 2004

made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set)
implemented HCR tool, VCB11, CRC, scalable bitstream order
note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32
960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts

--- a/include/faac.h
+++ b/include/faac.h
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: faac.h,v 1.32 2003/11/24 18:10:32 knik Exp $
+ * $Id: faac.h,v 1.33 2004/07/04 12:12:05 corrados Exp $
  */
 
 #ifndef _FAAC_H_
@@ -48,6 +48,10 @@
 
 
 typedef void *faacEncHandle;
+
+#ifndef HAVE_INT32_T
+typedef int int32_t;
+#endif
 
 /*
 	Allows an application to get FAAC version info. This is intended
--- a/include/faaccfg.h
+++ b/include/faaccfg.h
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: faaccfg.h,v 1.2 2003/10/29 10:31:24 stux Exp $
+ * $Id: faaccfg.h,v 1.3 2004/07/04 12:12:05 corrados Exp $
  */
 
 #ifndef _FAACCFG_H_
@@ -29,10 +29,10 @@
 #define MPEG4 0
 
 /* AAC object types */
-#define MAIN 0
-#define LOW  1
-#define SSR  2
-#define LTP  3
+#define MAIN 1
+#define LOW  2
+#define SSR  3
+#define LTP  4
 
 /* Input Formats */
 #define FAAC_INPUT_NULL    0
--- a/libfaac/aacquant.c
+++ b/libfaac/aacquant.c
@@ -17,7 +17,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: aacquant.c,v 1.29 2003/12/17 21:00:22 knik Exp $
+ * $Id: aacquant.c,v 1.30 2004/07/04 12:10:52 corrados Exp $
  */
 
 #include <math.h>
@@ -229,6 +229,11 @@
 
     /* place the codewords and their respective lengths in arrays data[] and len[] respectively */
     /* there are 'counter' elements in each array, and these are variable length arrays depending on the input */
+#ifdef DRM
+    coderInfo->iLenReordSpData = 0; /* init length of reordered spectral data */
+    coderInfo->iLenLongestCW = 0; /* init length of longest codeword */
+    coderInfo->cur_cw = 0; /* init codeword counter */
+#endif
     coderInfo->spectral_count = 0;
     sb = 0;
     for(i = 0; i < coderInfo->nr_of_sfb; i++) {
@@ -239,9 +244,10 @@
             coderInfo->sfb_offset[i],
             coderInfo->sfb_offset[i+1]-coderInfo->sfb_offset[i]);
 
-	if (coderInfo->book_vector[i])
-          sb = i;
+        if (coderInfo->book_vector[i])
+              sb = i;
     }
+
     // FIXME: Check those max_sfb/nr_of_sfb. Isn't it the same?
     coderInfo->max_sfb = coderInfo->nr_of_sfb = sb + 1;
 
@@ -598,7 +604,7 @@
 {
     int i,j,ii;
     int index = 0;
-    double xr_tmp[1024];
+    double xr_tmp[FRAME_LEN];
     int group_offset=0;
     int k=0;
     int windowOffset = 0;
@@ -626,13 +632,13 @@
         for (k=0; k<*nr_of_sfb; k++) {
             for (j=0; j < window_group_length[i]; j++) {
                 for (ii=0;ii< sfb_width_table[k];ii++)
-                    xr_tmp[index++] = xr[ii+ sfb_offset[k] + 128*j +group_offset];
+                    xr_tmp[index++] = xr[ii+ sfb_offset[k] + BLOCK_LEN_SHORT*j +group_offset];
             }
         }
-        group_offset +=  128*window_group_length[i];
+        group_offset +=  BLOCK_LEN_SHORT*window_group_length[i];
     }
 
-    for (k=0; k<1024; k++){
+    for (k=0; k<FRAME_LEN; k++){
         xr[k] = xr_tmp[k];
     }
 
--- a/libfaac/bitstream.c
+++ b/libfaac/bitstream.c
@@ -24,7 +24,7 @@
 Copyright (c) 1997.
 **********************************************************************/
 /*
- * $Id: bitstream.c,v 1.27 2003/10/14 15:23:44 menno Exp $
+ * $Id: bitstream.c,v 1.28 2004/07/04 12:10:52 corrados Exp $
  */
 
 #include <stdio.h>
@@ -99,9 +99,19 @@
                      int numBit);
 static int ByteAlign(BitStream* bitStream,
                      int writeFlag);
+#ifdef DRM
+static int PutBitHcr(BitStream *bitStream,
+                     unsigned long curpos,
+                     unsigned long data,
+                     int numBit);
+static int rewind_word(int W, int len);
+static int WriteReorderedSpectralData(CoderInfo *coderInfo,
+                                      BitStream *bitStream,
+                                      int writeFlag);
+static void calc_CRC(BitStream *bitStream, int len);
+#endif
 
 
-
 static int WriteFAACStr(BitStream *bitStream, char *version, int write)
 {
   int i;
@@ -430,6 +440,7 @@
 {
     int bits = 0;
 
+#ifndef DRM
     if (writeFlag) {
         /* write Single Element Channel (SCE) identifier */
         PutBit(bitStream, ID_SCE, LEN_SE_ID);
@@ -440,6 +451,7 @@
 
     bits += LEN_SE_ID;
     bits += LEN_TAG;
+#endif
 
     /* Write an Individual Channel Stream element */
     bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag);
@@ -510,7 +522,13 @@
             PutBit(bitStream, coderInfo->max_sfb, LEN_MAX_SFBL);
         }
         bits += LEN_MAX_SFBL;
-
+#ifdef DRM
+    }
+    if (writeFlag) {
+        PutBit(bitStream,coderInfo->tnsInfo.tnsDataPresent,LEN_TNS_PRES);
+    }
+    bits += LEN_TNS_PRES;
+#endif
         if (objectType == LTP)
         {
             bits++;
@@ -527,7 +545,9 @@
 
             bits += WritePredictorData(coderInfo, bitStream, writeFlag);
         }
+#ifndef DRM
     }
+#endif
 
     return bits;
 }
@@ -542,10 +562,12 @@
     /* returns the number of bits written to the bitstream */
     int bits = 0;
 
+#ifndef DRM
     /* Write the 8-bit global_gain */
     if (writeFlag)
         PutBit(bitStream, coderInfo->global_gain, LEN_GLOB_GAIN);
     bits += LEN_GLOB_GAIN;
+#endif
 
     /* Write ics information */
     if (!commonWindow) {
@@ -552,12 +574,41 @@
         bits += WriteICSInfo(coderInfo, bitStream, objectType, commonWindow, writeFlag);
     }
 
+#ifdef DRM
+    /* Write the 8-bit global_gain */
+    if (writeFlag)
+        PutBit(bitStream, coderInfo->global_gain, LEN_GLOB_GAIN);
+    bits += LEN_GLOB_GAIN;
+#endif
+
     bits += SortBookNumbers(coderInfo, bitStream, writeFlag);
     bits += WriteScalefactors(coderInfo, bitStream, writeFlag);
+#ifdef DRM
+    if (writeFlag) {
+        /* length_of_reordered_spectral_data */
+        PutBit(bitStream, coderInfo->iLenReordSpData, LEN_HCR_REORDSD);
+
+        /* length_of_longest_codeword */
+        PutBit(bitStream, coderInfo->iLenLongestCW, LEN_HCR_LONGCW);
+    }
+    bits += LEN_HCR_REORDSD + LEN_HCR_LONGCW;
+#else
     bits += WritePulseData(coderInfo, bitStream, writeFlag);
+#endif
     bits += WriteTNSData(coderInfo, bitStream, writeFlag);
+#ifndef DRM
     bits += WriteGainControlData(coderInfo, bitStream, writeFlag);
+#endif
+
+#ifdef DRM
+    /* DRM CRC calculation */
+    if (writeFlag)
+        calc_CRC(bitStream, bits);
+
+    bits += WriteReorderedSpectralData(coderInfo, bitStream, writeFlag);
+#else
     bits += WriteSpectralData(coderInfo, bitStream, writeFlag);
+#endif
 
     /* Return number of bits */
     return bits;
@@ -675,10 +726,12 @@
 
     TnsInfo* tnsInfoPtr = &coderInfo->tnsInfo;
 
+#ifndef DRM
     if (writeFlag) {
         PutBit(bitStream,tnsInfoPtr->tnsDataPresent,LEN_TNS_PRES);
     }
     bits += LEN_TNS_PRES;
+#endif
 
     /* If TNS is not present, bail */
     if (!tnsInfoPtr->tnsDataPresent) {
@@ -875,8 +928,14 @@
 
     bitStream = AllocMemory(sizeof(BitStream));
     bitStream->size = size;
+#ifdef DRM
+    /* skip first byte for CRC */
+    bitStream->numBit = 8;
+    bitStream->currentBit = 8;
+#else
     bitStream->numBit = 0;
     bitStream->currentBit = 0;
+#endif
     bitStream->data = buffer;
     SetMemory(bitStream->data, 0, size);
 
@@ -905,8 +964,10 @@
 
     idx = (bitStream->currentBit / BYTE_NUMBIT) % bitStream->size;
     numUsed = bitStream->currentBit % BYTE_NUMBIT;
+#ifndef DRM
     if (numUsed == 0)
         bitStream->data[idx] = 0;
+#endif
     bitStream->data[idx] |= (data & ((1<<numBit)-1)) <<
         (BYTE_NUMBIT-numUsed-numBit);
     bitStream->currentBit += numBit;
@@ -958,3 +1019,343 @@
     return j;
 }
 
+#ifdef DRM
+/*
+    ****************************************************************************
+    The following code was written by Volker Fischer (c) 2004
+
+    The GNU Lesser General Public License as published by the
+    Free Software Foundation applies to this code.
+    ****************************************************************************
+*/
+#define LEN_PRESORT_CODEBOOK 22
+static const unsigned short PresortedCodebook_VCB11[] = {11, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 9, 7, 5, 3, 1};
+static const int maxCwLen[32] = {0, 11, 9, 20, 16, 13, 11, 14, 12, 17, 14, 49,
+    0, 0, 0, 0, 14, 17, 21, 21, 25, 25, 29, 29, 29, 29, 33, 33, 33, 37, 37, 41}; /* 8.5.3.3.3.1 */
+
+typedef struct { /* segment parameters */
+    unsigned int left; /* left start of free space in segment */
+    unsigned int right; /* right position of free space in segment */
+    unsigned int len; /* length of free space in segment */
+} segment_t;
+
+typedef struct { /* codeword parameters */
+    unsigned int   cw_offset; /* offset in actual codeword data vector */
+    unsigned short window; /* which window belongs to this codeword */
+    unsigned short cb; /* codebook */
+    unsigned short num_sl_cw; /* number of spectral lines per codeword */
+    unsigned int   cw_nr; /* codeword number in the window */
+    unsigned short cw_len; /* codeword lenght */
+    unsigned short num_data; /* number of data cells for codeword */
+} cw_info_t;
+
+static int PutBitHcr(BitStream *bitStream,
+                     unsigned long curpos,
+                     unsigned long data,
+                     int numBit)
+{ /* data can be written at an arbitrary position in the bitstream */
+    bitStream->currentBit = curpos;
+    return PutBit(bitStream, data, numBit);
+}
+
+static int rewind_word(int W, int len)
+{ /* rewind len (max. 32) bits so that the MSB becomes LSB */
+    short i;
+    int tmp_W = 0;
+
+    for (i = 0; i < len; i++) {
+        tmp_W <<= 1;
+        if (W & (1<<i)) tmp_W |= 1;
+    }
+    return tmp_W;
+}
+
+static int WriteReorderedSpectralData(CoderInfo *coderInfo,
+                                      BitStream *bitStream,
+                                      int writeFlag)
+{
+    int i, j;
+    int cursegmsize, accsegmsize = 0;
+    int segmcnt = 0;
+    long startbitpos;
+    segment_t segment[FRAME_LEN];
+    int* window_group_length = coderInfo->window_group_length;
+    int* sfb_offset = coderInfo->sfb_offset;
+
+    cw_info_t cw_info[FRAME_LEN];
+    cw_info_t cw_info_preso[FRAME_LEN];
+
+    int num_cw = coderInfo->cur_cw;
+    int window_cw_cnt[MAX_SHORT_WINDOWS] = {0,0,0,0,0,0,0,0};
+
+    int presort, set, num_sets;
+
+    unsigned short cur_cb, cw_cnt;
+    short is_backwards;
+    int diff, tmp_data, cw_part_cnt, cur_cw_part;
+
+    int cur_cw_len, cur_data;
+    int sfb_cnt, win_cnt, acc_win_cnt, win_grp_cnt;
+    int coeff_cnt, last_sfb, cur_sfb_len;
+
+    /* set up local pointers to data and len */
+    /* data array contains data to be written */
+    /* len array contains lengths of data words */
+    int* data = coderInfo->data;
+    int* len  = coderInfo->len;
+    int* num_data = coderInfo->num_data_cw;
+
+    if (writeFlag) {
+        /* build offset table */
+        cur_data = 0;
+        cw_info[0].cw_offset = 0;
+        for (i = 0; i < num_cw; i++) {
+            cur_cw_len = 0;
+            for (j = 0; j < num_data[i]; j++) {
+                cur_cw_len += len[cur_data++];
+            }
+
+            cw_info[i].num_data = num_data[i];
+            cw_info[i].cw_len = cur_cw_len;
+            if (i > 0) /* calculate offset (codeword info parameter) */
+                cw_info[i].cw_offset = cw_info[i - 1].cw_offset + num_data[i - 1];
+        }
+
+        /* presort codewords ------------------------------------------------ */
+        /* classify codewords first */
+        sfb_cnt = win_cnt = win_grp_cnt = coeff_cnt = last_sfb = acc_win_cnt = 0;
+        cur_sfb_len = sfb_offset[1] / window_group_length[0];
+        cur_cb = coderInfo->book_vector[0];
+        for (i = 0; i < num_cw; i++) {
+            /* Set codeword info parameters */
+            cw_info[i].cb = cur_cb;
+            cw_info[i].num_sl_cw = (cur_cb < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN;
+
+            cw_info[i].window = acc_win_cnt + win_cnt;
+            cw_info[i].cw_nr = window_cw_cnt[cw_info[i].window];
+            window_cw_cnt[cw_info[i].window]++;
+
+            coeff_cnt += cw_info[i].num_sl_cw;
+            if (coeff_cnt - last_sfb >= cur_sfb_len) {
+                last_sfb += cur_sfb_len;
+
+                win_cnt++; /* next window */
+                if (win_cnt == window_group_length[win_grp_cnt]) {
+                    win_cnt = 0;
+
+                    sfb_cnt++; /* next sfb */
+                    if (sfb_cnt == coderInfo->all_sfb) {
+                        sfb_cnt = 0;
+
+                        acc_win_cnt += window_group_length[win_grp_cnt];
+                        win_grp_cnt++; /* next window group */
+                    }
+
+                    /* new codebook and sfb length */
+                    cur_cb = coderInfo->book_vector[sfb_cnt];
+                    if (last_sfb < FRAME_LEN) {
+                        cur_sfb_len = (sfb_offset[sfb_cnt + 1] - sfb_offset[sfb_cnt])
+                            / window_group_length[win_grp_cnt];
+                    }
+                }
+            }
+        }
+
+        /* presorting (first presorting step) */
+        /* only needed for short windows */
+        if (coderInfo->block_type == ONLY_SHORT_WINDOW) {
+            for (i = 0; i < MAX_SHORT_WINDOWS; i++)
+                window_cw_cnt[i] = 0; /* reset all counters */
+
+            win_cnt = 0;
+            cw_cnt = 0;
+            for (i = 0; i < num_cw; i++) {
+                for (j = 0; j < num_cw; j++) {
+                    if (cw_info[j].window == win_cnt) {
+                        if (cw_info[j].cw_nr == window_cw_cnt[win_cnt]) {
+                            cw_info_preso[cw_cnt++] = cw_info[j];
+                            window_cw_cnt[win_cnt]++;
+
+                            /* check if two one-dimensional codewords */
+                            if (cw_info[j].num_sl_cw == PAIR_LEN) {
+                                cw_info_preso[cw_cnt++] = cw_info[j + 1];
+                                window_cw_cnt[win_cnt]++;
+                            }
+
+                            win_cnt++; /* next window */
+                            if (win_cnt == MAX_SHORT_WINDOWS)
+                                win_cnt = 0;
+                        }
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i < num_cw; i++) {
+                cw_info_preso[i] = cw_info[i]; /* just copy */
+            }
+        }
+
+        /* presorting (second presorting step) */
+        cw_cnt = 0;
+        for (presort = 0; presort < LEN_PRESORT_CODEBOOK; presort++) {
+            /* next codebook that has to be processed according to presorting */
+            unsigned short nextCB = PresortedCodebook_VCB11[presort];
+
+            for (i = 0; i < num_cw; i++) {
+                /* process only codewords that are due now */
+                if ((cw_info_preso[i].cb == nextCB) ||
+                    ((nextCB < ESC_HCB) && (cw_info_preso[i].cb == nextCB + 1)))
+                {
+                    cw_info[cw_cnt++] = cw_info_preso[i];
+                }
+            }
+        }
+
+        /* init segments */
+        accsegmsize = 0;
+        for (i = 0; i < num_cw; i++) {
+            /* 8.5.3.3.3.2 Derivation of segment width */
+            cursegmsize = min(maxCwLen[cw_info[i].cb], coderInfo->iLenLongestCW);
+
+            if (accsegmsize + cursegmsize > coderInfo->iLenReordSpData) {
+                /* the last segment is extended until iLenReordSpData */
+                segment[segmcnt - 1].right = coderInfo->iLenReordSpData - 1;
+                segment[segmcnt - 1].len = coderInfo->iLenReordSpData - segment[segmcnt - 1].left;
+                break;
+            }
+
+            segment[segmcnt].left = accsegmsize;
+            segment[segmcnt].right = accsegmsize + cursegmsize - 1;
+            segment[segmcnt++].len = cursegmsize;
+            accsegmsize += cursegmsize;
+        }
+
+        /* store current bit position */
+        startbitpos = bitStream->currentBit;
+
+        /* write write priority codewords (PCWs) and nonPCWs ---------------- */
+        num_sets = num_cw / segmcnt; /* number of sets */
+
+        for (set = 0; set <= num_sets; set++) {
+            int trial;
+
+            /* ever second set the bit order is reversed */
+            is_backwards = set % 2;
+
+            for (trial = 0; trial < segmcnt; trial++) {
+                int codewordBase;
+                int set_encoded = segmcnt;
+
+                if (set == num_sets)
+                    set_encoded = num_cw - set * segmcnt; /* last set is shorter than the rest */
+
+                for (codewordBase = 0; codewordBase < segmcnt; codewordBase++) {
+                    int segment_index = (trial + codewordBase) % segmcnt;
+                    int codeword_index = codewordBase + set * segmcnt;
+
+                    if (codeword_index >= num_cw)
+                        break;
+
+                    if ((cw_info[codeword_index].cw_len > 0) && (segment[segment_index].len > 0)) {
+                        /* codeword is not yet written (completely) */
+                        /* space left in this segment */
+                        short tmplen;
+
+                        /* how many bits can be written? */
+                        if (segment[segment_index].len >= cw_info[codeword_index].cw_len) {
+                            tmplen = cw_info[codeword_index].cw_len;
+                            set_encoded--; /* CW fits into segment */
+                        } else {
+                            tmplen = segment[segment_index].len;
+                        }
+
+                        /* Adjust lengths */
+                        cw_info[codeword_index].cw_len -= tmplen;
+                        segment[segment_index].len -= tmplen;
+
+                        /* write codewords to bitstream */
+                        for (cw_part_cnt = 0; cw_part_cnt < cw_info[codeword_index].num_data; cw_part_cnt++) {
+                            cur_cw_part = cw_info[codeword_index].cw_offset + cw_part_cnt;
+
+                            if (len[cur_cw_part] <= tmplen) {
+                                /* write complete data, no partitioning */
+                                if (is_backwards) {
+                                    /* write data in reversed bit-order */
+                                    PutBitHcr(bitStream, startbitpos + segment[segment_index].right - len[cur_cw_part] + 1,
+                                        rewind_word(data[cur_cw_part], len[cur_cw_part]), len[cur_cw_part]);
+
+                                    segment[segment_index].right -= len[cur_cw_part];
+                                } else {
+                                    PutBitHcr(bitStream, startbitpos + segment[segment_index].left,
+                                        data[cur_cw_part], len[cur_cw_part]);
+
+                                    segment[segment_index].left += len[cur_cw_part];
+                                }
+
+                                tmplen -= len[cur_cw_part];
+                                len[cur_cw_part] = 0;
+                            } else {
+                                /* codeword part must be partitioned */
+                                /* data must be taken from the left side */
+                                tmp_data = data[cur_cw_part];
+
+                                diff = len[cur_cw_part] - tmplen;
+                                tmp_data >>= diff;
+
+                                /* remove bits which are already used */
+                                data[cur_cw_part] &= (1 << diff) - 1 /* diff number of ones */;
+                                len[cur_cw_part] = diff;
+
+                                if (is_backwards) {
+                                    /* write data in reversed bit-order */
+                                    PutBitHcr(bitStream, startbitpos + segment[segment_index].right - tmplen + 1,
+                                        rewind_word(tmp_data, tmplen), tmplen);
+
+                                    segment[segment_index].right -= tmplen;
+                                } else {
+                                    PutBitHcr(bitStream, startbitpos + segment[segment_index].left,
+                                        tmp_data, tmplen);
+
+                                    segment[segment_index].left += tmplen;
+                                }
+
+                                tmplen = 0;
+                            }
+                            
+                            if (tmplen == 0)
+                                break; /* all data written for this segment trial */
+                        }
+                    }
+                } /* of codewordBase */
+
+                if (set_encoded == 0)
+                    break; /* no unencoded codewords left in this set */
+            } /* of trial */
+        }
+
+        /* set parameter for bit stream to current correct position */
+        bitStream->currentBit = startbitpos + coderInfo->iLenReordSpData;
+        bitStream->numBit = bitStream->currentBit;
+    }
+
+    return coderInfo->iLenReordSpData;
+}
+
+static void calc_CRC(BitStream *bitStream, int len)
+{
+    int i;
+    unsigned char r = 255;  /* Initialize to all ones */
+
+    /* CRC polynome used x^8 + x^4 + x^3 + x^2 +1 */
+#define GPOLY 0435
+
+    for (i = 8; i < len + 8; i++) {
+        r = ( (r << 1) ^ (( (
+            ( bitStream->data[i / 8] >> (7 - (i % 8)) )
+            & 1) ^ ((r >> 7) & 1)) * GPOLY )) & 0xFF;
+    }
+
+    /* CRC is stored inverted, per definition at first byte in stream */
+    bitStream->data[0] = ~r;
+}
+#endif
--- a/libfaac/bitstream.h
+++ b/libfaac/bitstream.h
@@ -32,7 +32,7 @@
 Copyright (c) 1996.
 **********************************************************************/
 /*
- * $Id: bitstream.h,v 1.13 2002/08/19 16:35:53 knik Exp $
+ * $Id: bitstream.h,v 1.14 2004/07/04 12:10:52 corrados Exp $
  */
 
 #ifndef BITSTREAM_H
@@ -103,6 +103,15 @@
 
 #define LEN_PC_COMM 8
 
+#ifdef DRM
+# define LEN_HCR_REORDSD 14
+# define LEN_HCR_LONGCW 6
+# define FIRST_PAIR_HCB 5
+# define QUAD_LEN 4
+# define PAIR_LEN 2
+# define ESC_HCB 11
+#endif
+
 #define ID_SCE 0
 #define ID_CPE 1
 #define ID_CCE 2
@@ -118,10 +127,10 @@
 #define MPEG4 0
 
 /* AAC object types */
-#define MAIN 0
-#define LOW  1
-#define SSR  2
-#define LTP  3
+#define MAIN 1
+#define LOW  2
+#define SSR  3
+#define LTP  4
 
 
 #define BYTE_NUMBIT 8       /* bits in byte (char) */
--- a/libfaac/coder.h
+++ b/libfaac/coder.h
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: coder.h,v 1.11 2003/06/26 19:19:51 knik Exp $
+ * $Id: coder.h,v 1.12 2004/07/04 12:10:52 corrados Exp $
  */
 
 #ifndef CODER_H
@@ -26,15 +26,24 @@
 extern "C" {
 #endif /* __cplusplus */
 
+/* Allow encoding of Digital Radio Mondiale (DRM) */
+//#define DRM
 
 #define MAX_CHANNELS 64
-#define FRAME_LEN 1024
 
+#ifdef DRM
+# define FRAME_LEN 1024//960 // not working with 960, fixme
+# define BLOCK_LEN_LONG 1024//960
+# define BLOCK_LEN_SHORT 128//120
+#else
+# define FRAME_LEN 1024
+# define BLOCK_LEN_LONG 1024
+# define BLOCK_LEN_SHORT 128
+#endif
+
 #define NSFB_LONG  51
 #define NSFB_SHORT 15
 #define MAX_SHORT_WINDOWS 8
-#define BLOCK_LEN_LONG 1024
-#define BLOCK_LEN_SHORT 128
 #define MAX_SCFAC_BANDS ((NSFB_SHORT+1)*MAX_SHORT_WINDOWS)
 
 enum WINDOW_TYPE {
@@ -153,6 +162,15 @@
 
     /* Lengths of spectral bitstream elements */
     int *len;
+
+#ifdef DRM
+    int *num_data_cw;
+    int cur_cw;
+    int all_sfb;
+
+    int iLenLongestCW;
+    int iLenReordSpData;
+#endif
 
     /* Holds the requantized spectrum */
     double *requantFreq;
--- a/libfaac/frame.c
+++ b/libfaac/frame.c
@@ -16,7 +16,7 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * $Id: frame.c,v 1.61 2004/05/03 11:37:16 danchr Exp $
+ * $Id: frame.c,v 1.62 2004/07/04 12:10:52 corrados Exp $
  */
 
 /*
@@ -188,6 +188,14 @@
 			int rate; // per channel at 44100 sampling frequency
 			int cutoff;
 		}	rates[] = {
+#ifdef DRM
+            /* DRM needs lower bit-rates. We've chosen higher bandwidth values and
+               decrease the quantizer quality at the same time to preserve the
+               low bit-rate */
+            {7000,  1500},
+            {15000, 3000},
+            {23000, 4000},
+#endif
 			{29500, 5000},
 			{37500, 7000},
 			{47000, 10000},
@@ -199,7 +207,11 @@
 		int f0, f1;
 		int r0, r1;
 
-		config->quantqual = 100;
+#ifdef DRM
+        config->quantqual = 40; /* init with a lower value for DRM */
+#else
+        config->quantqual = 100;
+#endif
 
 		config->bitRate = (double)config->bitRate * 44100 / hEncoder->sampleRate;
 
@@ -218,19 +230,19 @@
 
 		if (config->bitRate > r1)
 			config->bitRate = r1;
-		if (config->bitRate < r0)
-			config->bitRate = r0;
+        if (config->bitRate < r0)
+            config->bitRate = r0;
 
 		if (f1 > f0)
-			config->bandWidth =
-					pow((double)config->bitRate / r1,
-					log((double)f1 / f0) / log ((double)r1 / r0)) * (double)f1;
+            config->bandWidth =
+                    pow((double)config->bitRate / r1,
+                    log((double)f1 / f0) / log ((double)r1 / r0)) * (double)f1;
 		else
 			config->bandWidth = f1;
 
 		config->bandWidth =
 				(double)config->bandWidth * hEncoder->sampleRate / 44100;
-				config->bitRate = (double)config->bitRate * hEncoder->sampleRate / 44100;
+		config->bitRate = (double)config->bitRate * hEncoder->sampleRate / 44100;
 
 		if (config->bandWidth > bwbase)
 		  config->bandWidth = bwbase;
@@ -240,7 +252,7 @@
 
     if (!config->bandWidth)
     {
-                config->bandWidth = (config->quantqual - 100) * bwmult + bwbase;
+        config->bandWidth = (config->quantqual - 100) * bwmult + bwbase;
     }
 
     hEncoder->config.bandWidth = config->bandWidth;
@@ -289,9 +301,13 @@
     unsigned int channel;
     faacEncHandle hEncoder;
 
-    *inputSamples = 1024*numChannels;
+    *inputSamples = FRAME_LEN*numChannels;
     *maxOutputBytes = (6144/8)*numChannels;
 
+#ifdef DRM
+    *maxOutputBytes += 1; /* for CRC */
+#endif
+
     hEncoder = (faacEncStruct*)AllocMemory(sizeof(faacEncStruct));
     SetMemory(hEncoder, 0, sizeof(faacEncStruct));
 
@@ -770,7 +786,7 @@
         /* If short window, reconstruction not needed for prediction */
         if ((coderInfo[channel].block_type == ONLY_SHORT_WINDOW)) {
             int sind;
-            for (sind = 0; sind < 1024; sind++) {
+            for (sind = 0; sind < BLOCK_LEN_LONG; sind++) {
 				coderInfo[channel].requantFreq[sind] = 0.0;
             }
         } else {
@@ -816,12 +832,11 @@
     if (hEncoder->config.bitRate)
 	{
 		double fix;
-		int desbits = numChannels * (hEncoder->config.bitRate * 1024)
+		int desbits = numChannels * (hEncoder->config.bitRate * FRAME_LEN)
 				/ hEncoder->sampleRate;
 		int diff = (frameBytes * 8) - desbits;
 
 		hEncoder->bitDiff += diff;
-
 		fix = (double)hEncoder->bitDiff / desbits;
 		fix *= 0.01;
 		fix = max(fix, -0.2);
@@ -832,8 +847,15 @@
 			hEncoder->aacquantCfg.quality *= (1.0 - fix);
 			if (hEncoder->aacquantCfg.quality > 300)
 				hEncoder->aacquantCfg.quality = 300;
-			if (hEncoder->aacquantCfg.quality < 50)
-				hEncoder->aacquantCfg.quality = 50;
+#ifdef DRM
+            /* since we have very low bit-rates in DRM, we have to decrease the
+               bandwidth and also decrease the quality */
+            if (hEncoder->aacquantCfg.quality < 10)
+                hEncoder->aacquantCfg.quality = 10;
+#else           
+            if (hEncoder->aacquantCfg.quality < 50)
+                hEncoder->aacquantCfg.quality = 50;
+#endif
 		}
     }
 
@@ -948,6 +970,18 @@
 
 /*
 $Log: frame.c,v $
+Revision 1.62  2004/07/04 12:10:52  corrados
+made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set)
+implemented HCR tool, VCB11, CRC, scalable bitstream order
+note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32
+960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts
+
+Revision 1.62  2004/07/  corrados
+made faac compliant with Digital Radio Mondiale (DRM) (DRM macro must be set)
+implemented HCR tool, VCB11, CRC, scalable bitstream order
+note: VCB11 only uses codebook 11! TODO: implement codebooks 16-32
+960 transform length is not yet implemented (TODO)! Use 1024 for encoding and 960 for decoding, resulting in a lot of artefacts
+
 Revision 1.61  2004/05/03 11:37:16  danchr
 bump version to unstable 1.24+
 
--- a/libfaac/huffman.c
+++ b/libfaac/huffman.c
@@ -23,7 +23,7 @@
 
 ***********/
 /*
- * $Id: huffman.c,v 1.8 2002/08/30 16:22:46 knik Exp $
+ * $Id: huffman.c,v 1.9 2004/07/04 12:10:52 corrados Exp $
  */
 
 #include <math.h>
@@ -43,6 +43,10 @@
     for (channel = 0; channel < numChannels; channel++) {
         coderInfo[channel].data = (int*)AllocMemory(5*FRAME_LEN*sizeof(int));
         coderInfo[channel].len = (int*)AllocMemory(5*FRAME_LEN*sizeof(int));
+
+#ifdef DRM
+        coderInfo[channel].num_data_cw = (int*)AllocMemory(FRAME_LEN*sizeof(int));
+#endif
     }
 }
 
@@ -88,7 +92,7 @@
 */
 
 {
-    int i,j,k,n;
+    int i,j,k;
     int hop;
     int min_book_choice[112][3];
     int bit_stats[240][3];
@@ -349,7 +353,6 @@
      OutputBits() is called, counter starts at the value it left off from the previous call.
 
    */
-
     int esc_sequence;
     int len_esc;
     int index;
@@ -359,8 +362,12 @@
     int counter;
 
     /* Set up local pointers to coderInfo elements data and len */
-    int* data= coderInfo->data;
-    int* len=  coderInfo->len;
+    int* data=      coderInfo->data;
+    int* len=       coderInfo->len;
+#ifdef DRM
+    int* num_data = coderInfo->num_data_cw;
+    int cur_cw_len;
+#endif
 
     counter = coderInfo->spectral_count;
 
@@ -368,10 +375,18 @@
     case 0:
     case INTENSITY_HCB2:
     case INTENSITY_HCB:
+#ifdef DRM
+        for(i=offset;i<offset+length;i=i+4){
+#endif
         /* This case also applies to intensity stereo encoding */
         coderInfo->data[counter] = 0;
         coderInfo->len[counter++] = 0;
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
+
+#ifdef DRM
+        num_data[coderInfo->cur_cw++] = 1;
+        }
+#endif
         return(bits);
     case 1:
         for(i=offset;i<offset+length;i=i+4){
@@ -381,6 +396,12 @@
             bits += tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw++] = 1;
+            coderInfo->iLenReordSpData += tmp;
+            if (tmp > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = tmp;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -392,6 +413,12 @@
             bits += tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw++] = 1;
+            coderInfo->iLenReordSpData += tmp;
+            if (tmp > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = tmp;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -403,18 +430,37 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw] = 1;
+            cur_cw_len = tmp;
+#endif
             for(j=0;j<4;j++){
                 if(quant[i+j] > 0) {  /* send out '0' if a positive value */
                     data[counter] = 0;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 } else
                 if(quant[i+j] < 0) {  /* send out '1' if a negative value */
                     data[counter] = 1;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 }
             }
+#ifdef DRM
+            coderInfo->iLenReordSpData += cur_cw_len;
+            if (cur_cw_len > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = cur_cw_len;
+
+            coderInfo->cur_cw++;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -426,18 +472,37 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw] = 1;
+            cur_cw_len = tmp;
+#endif
             for(j=0;j<4;j++){
                 if(quant[i+j] > 0) {  /* send out '0' if a positive value */
                     data[counter] = 0;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 } else
                 if(quant[i+j] < 0) {  /* send out '1' if a negative value */
                     data[counter] = 1;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 }
             }
+#ifdef DRM
+            coderInfo->iLenReordSpData += cur_cw_len;
+            if (cur_cw_len > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = cur_cw_len;
+
+            coderInfo->cur_cw++;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -449,6 +514,12 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw++] = 1;
+            coderInfo->iLenReordSpData += tmp;
+            if (tmp > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = tmp;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -460,6 +531,12 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw++] = 1;
+            coderInfo->iLenReordSpData += tmp;
+            if (tmp > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = tmp;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -471,18 +548,37 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw] = 1;
+            cur_cw_len = tmp;
+#endif
             for(j=0;j<2;j++){
                 if(quant[i+j] > 0) {  /* send out '0' if a positive value */
                     data[counter] = 0;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 } else
                 if(quant[i+j] < 0) {  /* send out '1' if a negative value */
                     data[counter] = 1;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 }
             }
+#ifdef DRM
+            coderInfo->iLenReordSpData += cur_cw_len;
+            if (cur_cw_len > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = cur_cw_len;
+
+            coderInfo->cur_cw++;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -494,18 +590,37 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw] = 1;
+            cur_cw_len = tmp;
+#endif
             for(j=0;j<2;j++){
                 if(quant[i+j] > 0) {  /* send out '0' if a positive value */
                     data[counter] = 0;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 } else
                 if(quant[i+j] < 0) {  /* send out '1' if a negative value */
                     data[counter] = 1;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 }
             }
+#ifdef DRM
+            coderInfo->iLenReordSpData += cur_cw_len;
+            if (cur_cw_len > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = cur_cw_len;
+
+            coderInfo->cur_cw++;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -517,19 +632,37 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
-
+#ifdef DRM
+            num_data[coderInfo->cur_cw] = 1;
+            cur_cw_len = tmp;
+#endif
             for(j=0;j<2;j++){
                 if(quant[i+j] > 0) {  /* send out '0' if a positive value */
                     data[counter] = 0;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 } else
                 if(quant[i+j] < 0) {  /* send out '1' if a negative value */
                     data[counter] = 1;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 }
             }
+#ifdef DRM
+            coderInfo->iLenReordSpData += cur_cw_len;
+            if (cur_cw_len > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = cur_cw_len;
+
+            coderInfo->cur_cw++;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -541,19 +674,37 @@
             bits = bits + tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
-
+#ifdef DRM
+            num_data[coderInfo->cur_cw] = 1;
+            cur_cw_len = tmp;
+#endif
             for(j=0;j<2;j++){
                 if(quant[i+j] > 0) {  /* send out '0' if a positive value */
                     data[counter] = 0;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 } else
                 if(quant[i+j] < 0) {  /* send out '1' if a negative value */
                     data[counter] = 1;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 }
             }
+#ifdef DRM
+            coderInfo->iLenReordSpData += cur_cw_len;
+            if (cur_cw_len > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = cur_cw_len;
+
+            coderInfo->cur_cw++;
+#endif
         }
         coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
@@ -581,6 +732,10 @@
             bits += tmp;
             data[counter] = codebook;
             len[counter++] = tmp;
+#ifdef DRM
+            num_data[coderInfo->cur_cw] = 1;
+            cur_cw_len = tmp;
+#endif
 
             /* Take care of the sign bits */
             for(j=0;j<2;j++){
@@ -588,11 +743,19 @@
                     data[counter] = 0;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 } else
                 if(quant[i+j] < 0) {  /* send out '1' if a negative value */
                     data[counter] = 1;
                     len[counter++] = 1;
                     bits += 1;
+#ifdef DRM
+                    num_data[coderInfo->cur_cw]++;
+                    cur_cw_len += 1;
+#endif
                 }
             }
 
@@ -603,6 +766,10 @@
                 bits += len_esc;
                 data[counter] = esc_sequence;
                 len[counter++] = len_esc;
+#ifdef DRM
+                num_data[coderInfo->cur_cw]++;
+                cur_cw_len += len_esc;
+#endif
 
                 /* then code and transmit the second escape_sequence */
                 esc_sequence = CalculateEscSequence(quant[i+1],&len_esc);
@@ -609,6 +776,10 @@
                 bits += len_esc;
                 data[counter] = esc_sequence;
                 len[counter++] = len_esc;
+#ifdef DRM
+                num_data[coderInfo->cur_cw]++;
+                cur_cw_len += len_esc;
+#endif
             }
             else if (ABS(quant[i]) >= 16) {  /* the first codeword was above 16, not the second one */
                 /* code and transmit the escape_sequence */
@@ -616,6 +787,10 @@
                 bits += len_esc;
                 data[counter] = esc_sequence;
                 len[counter++] = len_esc;
+#ifdef DRM
+                num_data[coderInfo->cur_cw]++;
+                cur_cw_len += len_esc;
+#endif
             }
             else if (ABS(quant[i+1]) >= 16) { /* the second codeword was above 16, not the first one */
                 /* code and transmit the escape_sequence */
@@ -623,9 +798,20 @@
                 bits += len_esc;
                 data[counter] = esc_sequence;
                 len[counter++] = len_esc;
+#ifdef DRM
+                num_data[coderInfo->cur_cw]++;
+                cur_cw_len += len_esc;
+#endif
             }
+#ifdef DRM
+            coderInfo->iLenReordSpData += cur_cw_len;
+            if (cur_cw_len > coderInfo->iLenLongestCW)
+                coderInfo->iLenLongestCW = cur_cw_len;
+
+            coderInfo->cur_cw++;
+#endif
         }
-        coderInfo -> spectral_count = counter;  /* send the current count back to the outside world */
+        coderInfo->spectral_count = counter;  /* send the current count back to the outside world */
         return(bits);
     }
     return 0;
@@ -809,10 +995,15 @@
     int previous;
     int max, bit_len/*,sfbs*/;
     int max_sfb,g,band;
+	int sect_cb_bits = 4;
 
     /* Set local pointers to coderInfo elements */
     int* book_vector = coderInfo->book_vector;
 
+#ifdef DRM
+    sect_cb_bits = 5; /* 5 bits in case of VCB11 */
+#endif
+
     if (coderInfo->block_type == ONLY_SHORT_WINDOW){
         max = 7;
         bit_len = 3;
@@ -832,11 +1023,25 @@
 
         previous = book_vector[band];
         if (writeFlag) {
-            PutBit(bitStream,book_vector[band],4);
+            PutBit(bitStream,book_vector[band],sect_cb_bits);
         }
-        bit_count += 4;
+        bit_count += sect_cb_bits;
 
         for (i=band+1;i<band+max_sfb;i++) {
+#ifdef DRM
+            /* sect_len is not transmitted in case the codebook for a */
+            /* section is 11 or in the range of 16 and 31 */
+            if ((previous == 11) ||
+                ((previous >= 16) && (previous <= 32)))
+            {
+                if (writeFlag)
+                    PutBit(bitStream,book_vector[i],sect_cb_bits);
+                bit_count += sect_cb_bits;
+                previous = book_vector[i];
+                repeat_counter=1;
+
+            } else
+#endif
             if( (book_vector[i] != previous)) {
                 if (writeFlag) {
                     PutBit(bitStream,repeat_counter,bit_len);
@@ -850,11 +1055,10 @@
                 }
 
                 if (writeFlag)
-                    PutBit(bitStream,book_vector[i],4);
-                bit_count += 4;
+                    PutBit(bitStream,book_vector[i],sect_cb_bits);
+                bit_count += sect_cb_bits;
                 previous = book_vector[i];
                 repeat_counter=1;
-
             }
             /* if the length of the section is longer than the amount of bits available in */
             /* the bitsream, "max", then start up an escape sequence */
@@ -870,18 +1074,21 @@
             }
         }
 
-        if (writeFlag)
-            PutBit(bitStream,repeat_counter,bit_len);
-        bit_count += bit_len;
-
-        if (repeat_counter == max) {  /* special case if the last section length is an */
-            /* escape sequence */
+#ifdef DRM
+        if (!((previous == 11) || ((previous >= 16) && (previous <= 32))))
+#endif
+        {
             if (writeFlag)
-                PutBit(bitStream,0,bit_len);
+                PutBit(bitStream,repeat_counter,bit_len);
             bit_count += bit_len;
-        }
 
-
+            if (repeat_counter == max) {  /* special case if the last section length is an */
+                /* escape sequence */
+                if (writeFlag)
+                    PutBit(bitStream,0,bit_len);
+                bit_count += bit_len;
+            }
+        }
     }  /* Bottom of group iteration */
 
     return bit_count;