func: static int read_sbr_grid(AACContext *ac, SpectralBandReplication *sbr,
  
                           GetBitContext *gb, SBRData *ch_data)
  
  {
  
      int i;
  
      unsigned bs_pointer = 0;
  
      // frameLengthFlag ? 15 : 16; 960 sample length frames unsupported; this value is numTimeSlots
  
      int abs_bord_trail = 16;
  
      int num_rel_lead, num_rel_trail;
  
      unsigned bs_num_env_old = ch_data->bs_num_env;
  
  
  
      ch_data->bs_freq_res[0] = ch_data->bs_freq_res[ch_data->bs_num_env];
  
      ch_data->bs_amp_res = sbr->bs_amp_res_header;
  
      ch_data->t_env_num_env_old = ch_data->t_env[bs_num_env_old];
  
  
  
      switch (ch_data->bs_frame_class = get_bits(gb, 2)) {
  
      case FIXFIX:
  
          ch_data->bs_num_env                 = 1 << get_bits(gb, 2);
  
          num_rel_lead                        = ch_data->bs_num_env - 1;
  
          if (ch_data->bs_num_env == 1)
  
              ch_data->bs_amp_res = 0;
  
  
  
          if (ch_data->bs_num_env > 4) {
  
              av_log(ac->avccontext, AV_LOG_ERROR,
  
                     "Invalid bitstream, too many SBR envelopes in FIXFIX type SBR frame: %d\n",
  
                     ch_data->bs_num_env);
  
              return -1;
  
          }
  
  
  
          ch_data->t_env[0]                   = 0;
  
          ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail;
  
  
  
          abs_bord_trail = (abs_bord_trail + (ch_data->bs_num_env >> 1)) /
  
                     ch_data->bs_num_env;
  
          for (i = 0; i < num_rel_lead; i++)
  
              ch_data->t_env[i + 1] = ch_data->t_env[i] + abs_bord_trail;
  
  
  
          ch_data->bs_freq_res[1] = get_bits1(gb);
  
          for (i = 1; i < ch_data->bs_num_env; i++)
  
              ch_data->bs_freq_res[i + 1] = ch_data->bs_freq_res[1];
  
          break;
  
      case FIXVAR:
  
          abs_bord_trail                     += get_bits(gb, 2);
  
          num_rel_trail                       = get_bits(gb, 2);
  
          ch_data->bs_num_env                 = num_rel_trail + 1;
  
          ch_data->t_env[0]                   = 0;
  
          ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail;
  
  
  
          for (i = 0; i < num_rel_trail; i++)
  
              ch_data->t_env[ch_data->bs_num_env - 1 - i] =
  
                  ch_data->t_env[ch_data->bs_num_env - i] - 2 * get_bits(gb, 2) - 2;
  
  
  
          bs_pointer = get_bits(gb, ceil_log2[ch_data->bs_num_env]);
  
  
  
          for (i = 0; i < ch_data->bs_num_env; i++)
  
              ch_data->bs_freq_res[ch_data->bs_num_env - i] = get_bits1(gb);
  
          break;
  
      case VARFIX:
  
          ch_data->t_env[0]                   = get_bits(gb, 2);
  
          num_rel_lead                        = get_bits(gb, 2);
  
          ch_data->bs_num_env                 = num_rel_lead + 1;
  
          ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail;
  
  
  
          for (i = 0; i < num_rel_lead; i++)
  
              ch_data->t_env[i + 1] = ch_data->t_env[i] + 2 * get_bits(gb, 2) + 2;
  
  
  
          bs_pointer = get_bits(gb, ceil_log2[ch_data->bs_num_env]);
  
  
  
          get_bits1_vector(gb, ch_data->bs_freq_res + 1, ch_data->bs_num_env);
  
          break;
  
      case VARVAR:
  
          ch_data->t_env[0]                   = get_bits(gb, 2);
  
          abs_bord_trail                     += get_bits(gb, 2);
  
          num_rel_lead                        = get_bits(gb, 2);
  
          num_rel_trail                       = get_bits(gb, 2);
  
          ch_data->bs_num_env                 = num_rel_lead + num_rel_trail + 1;
  
          ch_data->t_env[ch_data->bs_num_env] = abs_bord_trail;
  
  
  
          if (ch_data->bs_num_env > 5) {
  
              av_log(ac->avccontext, AV_LOG_ERROR,
  
                     "Invalid bitstream, too many SBR envelopes in VARVAR type SBR frame: %d\n",
  
                     ch_data->bs_num_env);
  
              return -1;
  
          }
  
  
  
          for (i = 0; i < num_rel_lead; i++)
  
              ch_data->t_env[i + 1] = ch_data->t_env[i] + 2 * get_bits(gb, 2) + 2;
  
          for (i = 0; i < num_rel_trail; i++)
  
              ch_data->t_env[ch_data->bs_num_env - 1 - i] =
  
                  ch_data->t_env[ch_data->bs_num_env - i] - 2 * get_bits(gb, 2) - 2;
  
  
  
          bs_pointer = get_bits(gb, ceil_log2[ch_data->bs_num_env]);
  
  
  
          get_bits1_vector(gb, ch_data->bs_freq_res + 1, ch_data->bs_num_env);
  
          break;
  
      }
  
  
  
      if (bs_pointer > ch_data->bs_num_env + 1) {
  
          av_log(ac->avccontext, AV_LOG_ERROR,
  
                 "Invalid bitstream, bs_pointer points to a middle noise border outside the time borders table: %d\n",
  
                 bs_pointer);
  
          return -1;
  
      }
  
  
  
      ch_data->bs_num_noise = (ch_data->bs_num_env > 1) + 1;
  
  
  
      ch_data->t_q[0]                     = ch_data->t_env[0];
  
      ch_data->t_q[ch_data->bs_num_noise] = ch_data->t_env[ch_data->bs_num_env];
  
      if (ch_data->bs_num_noise > 1) {
  
          unsigned int idx;
  
          if (ch_data->bs_frame_class == FIXFIX) {
  
              idx = ch_data->bs_num_env >> 1;
  
          } else if (ch_data->bs_frame_class & 1) { // FIXVAR or VARVAR
  
              idx = ch_data->bs_num_env - FFMAX(bs_pointer - 1, 1);
  
          } else { // VARFIX
  
              if (!bs_pointer)
  
                  idx = 1;
  
              else if (bs_pointer == 1)
  
                  idx = ch_data->bs_num_env - 1;
  
              else // bs_pointer > 1
  
                  idx = bs_pointer - 1;
  
          }
  
          ch_data->t_q[1] = ch_data->t_env[idx];
  
      }
  
  
  
      ch_data->e_a[0] = -(ch_data->e_a[1] != bs_num_env_old); // l_APrev
  
      ch_data->e_a[1] = -1;
  
      if ((ch_data->bs_frame_class & 1) && bs_pointer) { // FIXVAR or VARVAR and bs_pointer != 0
  
          ch_data->e_a[1] = ch_data->bs_num_env + 1 - bs_pointer;
  
      } else if ((ch_data->bs_frame_class == 2) && (bs_pointer > 1)) // VARFIX and bs_pointer > 1
  
          ch_data->e_a[1] = bs_pointer - 1;
  
  
  
      return 0;
  
  }
  