func: static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc)
  
  {
  
      unsigned cb;
  
      uint8_t  *tmp_vlc_bits;
  
      uint32_t *tmp_vlc_codes;
  
      GetBitContext *gb = &vc->gb;
  
      uint16_t *codebook_multiplicands;
  
      int ret = 0;
  
  
  
      vc->codebook_count = get_bits(gb, 8) + 1;
  
  
  
      av_dlog(NULL, " Codebooks: %d \n", vc->codebook_count);
  
  
  
      vc->codebooks = av_mallocz(vc->codebook_count * sizeof(*vc->codebooks));
  
      tmp_vlc_bits  = av_mallocz(V_MAX_VLCS * sizeof(*tmp_vlc_bits));
  
      tmp_vlc_codes = av_mallocz(V_MAX_VLCS * sizeof(*tmp_vlc_codes));
  
      codebook_multiplicands = av_malloc(V_MAX_VLCS * sizeof(*codebook_multiplicands));
  
  
  
      for (cb = 0; cb < vc->codebook_count; ++cb) {
  
          vorbis_codebook *codebook_setup = &vc->codebooks[cb];
  
          unsigned ordered, t, entries, used_entries = 0;
  
  
  
          av_dlog(NULL, " %u. Codebook\n", cb);
  
  
  
          if (get_bits(gb, 24) != 0x564342) {
  
              av_log(vc->avctx, AV_LOG_ERROR,
  
                     " %u. Codebook setup data corrupt.\n", cb);
  
              ret = AVERROR_INVALIDDATA;
  
              goto error;
  
          }
  
  
  
          codebook_setup->dimensions=get_bits(gb, 16);
  
          if (codebook_setup->dimensions > 16 || codebook_setup->dimensions == 0) {
  
              av_log(vc->avctx, AV_LOG_ERROR,
  
                     " %u. Codebook's dimension is invalid (%d).\n",
  
                     cb, codebook_setup->dimensions);
  
              ret = AVERROR_INVALIDDATA;
  
              goto error;
  
          }
  
          entries = get_bits(gb, 24);
  
          if (entries > V_MAX_VLCS) {
  
              av_log(vc->avctx, AV_LOG_ERROR,
  
                     " %u. Codebook has too many entries (%u).\n",
  
                     cb, entries);
  
              ret = AVERROR_INVALIDDATA;
  
              goto error;
  
          }
  
  
  
          ordered = get_bits1(gb);
  
  
  
          av_dlog(NULL, " codebook_dimensions %d, codebook_entries %u\n",
  
                  codebook_setup->dimensions, entries);
  
  
  
          if (!ordered) {
  
              unsigned ce, flag;
  
              unsigned sparse = get_bits1(gb);
  
  
  
              av_dlog(NULL, " not ordered \n");
  
  
  
              if (sparse) {
  
                  av_dlog(NULL, " sparse \n");
  
  
  
                  used_entries = 0;
  
                  for (ce = 0; ce < entries; ++ce) {
  
                      flag = get_bits1(gb);
  
                      if (flag) {
  
                          tmp_vlc_bits[ce] = get_bits(gb, 5) + 1;
  
                          ++used_entries;
  
                      } else
  
                          tmp_vlc_bits[ce] = 0;
  
                  }
  
              } else {
  
                  av_dlog(NULL, " not sparse \n");
  
  
  
                  used_entries = entries;
  
                  for (ce = 0; ce < entries; ++ce)
  
                      tmp_vlc_bits[ce] = get_bits(gb, 5) + 1;
  
              }
  
          } else {
  
              unsigned current_entry  = 0;
  
              unsigned current_length = get_bits(gb, 5) + 1;
  
  
  
              av_dlog(NULL, " ordered, current length: %u\n", current_length);  //FIXME
  
  
  
              used_entries = entries;
  
              for (; current_entry < used_entries && current_length <= 32; ++current_length) {
  
                  unsigned i, number;
  
  
  
                  av_dlog(NULL, " number bits: %u ", ilog(entries - current_entry));
  
  
  
                  number = get_bits(gb, ilog(entries - current_entry));
  
  
  
                  av_dlog(NULL, " number: %u\n", number);
  
  
  
                  for (i = current_entry; i < number+current_entry; ++i)
  
                      if (i < used_entries)
  
                          tmp_vlc_bits[i] = current_length;
  
  
  
                  current_entry+=number;
  
              }
  
              if (current_entry>used_entries) {
  
                  av_log(vc->avctx, AV_LOG_ERROR, " More codelengths than codes in codebook. \n");
  
                  ret = AVERROR_INVALIDDATA;
  
                  goto error;
  
              }
  
          }
  
  
  
          codebook_setup->lookup_type = get_bits(gb, 4);
  
  
  
          av_dlog(NULL, " lookup type: %d : %s \n", codebook_setup->lookup_type,
  
                  codebook_setup->lookup_type ? "vq" : "no lookup");
  
  
  
  // If the codebook is used for (inverse) VQ, calculate codevectors.
  
  
  
          if (codebook_setup->lookup_type == 1) {
  
              unsigned i, j, k;
  
              unsigned codebook_lookup_values = ff_vorbis_nth_root(entries, codebook_setup->dimensions);
  
  
  
              float codebook_minimum_value = vorbisfloat2float(get_bits_long(gb, 32));
  
              float codebook_delta_value   = vorbisfloat2float(get_bits_long(gb, 32));
  
              unsigned codebook_value_bits = get_bits(gb, 4) + 1;
  
              unsigned codebook_sequence_p = get_bits1(gb);
  
  
  
              av_dlog(NULL, " We expect %d numbers for building the codevectors. \n",
  
                      codebook_lookup_values);
  
              av_dlog(NULL, "  delta %f minmum %f \n",
  
                      codebook_delta_value, codebook_minimum_value);
  
  
  
              for (i = 0; i < codebook_lookup_values; ++i) {
  
                  codebook_multiplicands[i] = get_bits(gb, codebook_value_bits);
  
  
  
                  av_dlog(NULL, " multiplicands*delta+minmum : %e \n",
  
                          (float)codebook_multiplicands[i] * codebook_delta_value + codebook_minimum_value);
  
                  av_dlog(NULL, " multiplicand %u\n", codebook_multiplicands[i]);
  
              }
  
  
  
  // Weed out unused vlcs and build codevector vector
  
              codebook_setup->codevectors = used_entries ? av_mallocz(used_entries *
  
                                                                      codebook_setup->dimensions *
  
                                                                      sizeof(*codebook_setup->codevectors))
  
                                                         : NULL;
  
              for (j = 0, i = 0; i < entries; ++i) {
  
                  unsigned dim = codebook_setup->dimensions;
  
  
  
                  if (tmp_vlc_bits[i]) {
  
                      float last = 0.0;
  
                      unsigned lookup_offset = i;
  
  
  
                      av_dlog(vc->avctx, "Lookup offset %u ,", i);
  
  
  
                      for (k = 0; k < dim; ++k) {
  
                          unsigned multiplicand_offset = lookup_offset % codebook_lookup_values;
  
                          codebook_setup->codevectors[j * dim + k] = codebook_multiplicands[multiplicand_offset] * codebook_delta_value + codebook_minimum_value + last;
  
                          if (codebook_sequence_p)
  
                              last = codebook_setup->codevectors[j * dim + k];
  
                          lookup_offset/=codebook_lookup_values;
  
                      }
  
                      tmp_vlc_bits[j] = tmp_vlc_bits[i];
  
  
  
                      av_dlog(vc->avctx, "real lookup offset %u, vector: ", j);
  
                      for (k = 0; k < dim; ++k)
  
                          av_dlog(vc->avctx, " %f ",
  
                                  codebook_setup->codevectors[j * dim + k]);
  
                      av_dlog(vc->avctx, "\n");
  
  
  
                      ++j;
  
                  }
  
              }
  
              if (j != used_entries) {
  
                  av_log(vc->avctx, AV_LOG_ERROR, "Bug in codevector vector building code. \n");
  
                  ret = AVERROR_INVALIDDATA;
  
                  goto error;
  
              }
  
              entries = used_entries;
  
          } else if (codebook_setup->lookup_type >= 2) {
  
              av_log(vc->avctx, AV_LOG_ERROR, "Codebook lookup type not supported. \n");
  
              ret = AVERROR_INVALIDDATA;
  
              goto error;
  
          }
  
  
  
  // Initialize VLC table
  
          if (ff_vorbis_len2vlc(tmp_vlc_bits, tmp_vlc_codes, entries)) {
  
              av_log(vc->avctx, AV_LOG_ERROR, " Invalid code lengths while generating vlcs. \n");
  
              ret = AVERROR_INVALIDDATA;
  
              goto error;
  
          }
  
          codebook_setup->maxdepth = 0;
  
          for (t = 0; t < entries; ++t)
  
              if (tmp_vlc_bits[t] >= codebook_setup->maxdepth)
  
                  codebook_setup->maxdepth = tmp_vlc_bits[t];
  
  
  
          if (codebook_setup->maxdepth > 3 * V_NB_BITS)
  
              codebook_setup->nb_bits = V_NB_BITS2;
  
          else
  
              codebook_setup->nb_bits = V_NB_BITS;
  
  
  
          codebook_setup->maxdepth = (codebook_setup->maxdepth+codebook_setup->nb_bits - 1) / codebook_setup->nb_bits;
  
  
  
          if ((ret = init_vlc(&codebook_setup->vlc, codebook_setup->nb_bits,
  
                              entries, tmp_vlc_bits, sizeof(*tmp_vlc_bits),
  
                              sizeof(*tmp_vlc_bits), tmp_vlc_codes,
  
                              sizeof(*tmp_vlc_codes), sizeof(*tmp_vlc_codes),
  
                              INIT_VLC_LE))) {
  
              av_log(vc->avctx, AV_LOG_ERROR, " Error generating vlc tables. \n");
  
              goto error;
  
          }
  
      }
  
  
  
      av_free(tmp_vlc_bits);
  
      av_free(tmp_vlc_codes);
  
      av_free(codebook_multiplicands);
  
      return 0;
  
  
  
  // Error:
  
  error:
  
      av_free(tmp_vlc_bits);
  
      av_free(tmp_vlc_codes);
  
      av_free(codebook_multiplicands);
  
      return ret;
  
  }
  