de265_error read_scaling_list(bitreader* br, const seq_parameter_set* sps,
                              scaling_list_data* sclist, bool inPPS)
{
  int dc_coeff[4][6];

  for (int sizeId=0;sizeId<4;sizeId++) {
    //int n = ((sizeId==3) ? 2 : 6);
    uint8_t scaling_list[6][32*32];

    for (int matrixId=0 ; matrixId<6 ; matrixId += (sizeId==3 ? 3 : 1)) {
      uint8_t* curr_scaling_list = scaling_list[matrixId];
      int scaling_list_dc_coef;

      int canonicalMatrixId = matrixId;
      if (sizeId==3 && matrixId==1) { canonicalMatrixId=3; }


      //printf("----- matrix %d\n",matrixId);

      char scaling_list_pred_mode_flag = get_bits(br,1);
      if (!scaling_list_pred_mode_flag) {
        int scaling_list_pred_matrix_id_delta = get_uvlc(br);
        if (scaling_list_pred_matrix_id_delta == UVLC_ERROR ||
            scaling_list_pred_matrix_id_delta > matrixId) {
          return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
        }

        //printf("scaling_list_pred_matrix_id_delta=%d\n", scaling_list_pred_matrix_id_delta);

        dc_coeff[sizeId][matrixId] = 16;
        scaling_list_dc_coef       = 16;

        if (scaling_list_pred_matrix_id_delta==0) {
          if (sizeId==0) {
            memcpy(curr_scaling_list, default_ScalingList_4x4, 16);
          }
          else {
            if (canonicalMatrixId<3)
              { memcpy(curr_scaling_list, default_ScalingList_8x8_intra,64); }
            else
              { memcpy(curr_scaling_list, default_ScalingList_8x8_inter,64); }
          }
        }
        else {
          // TODO: CHECK: for sizeID=3 and the second matrix, should we have delta=1 or delta=3 ?
          if (sizeId==3) { assert(scaling_list_pred_matrix_id_delta==1); }

          int mID = matrixId - scaling_list_pred_matrix_id_delta;

          int len = (sizeId == 0 ? 16 : 64);
          memcpy(curr_scaling_list, scaling_list[mID], len);

          scaling_list_dc_coef       = dc_coeff[sizeId][mID];
          dc_coeff[sizeId][matrixId] = dc_coeff[sizeId][mID];
        }
      }
      else {
        int nextCoef=8;
        int coefNum = (sizeId==0 ? 16 : 64);
        if (sizeId>1) {
          scaling_list_dc_coef = get_svlc(br);
          if (scaling_list_dc_coef < -7 ||
              scaling_list_dc_coef > 247) {
            return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
          }

          scaling_list_dc_coef += 8;
          nextCoef=scaling_list_dc_coef;
          dc_coeff[sizeId][matrixId] = scaling_list_dc_coef;
        }
        else {
          scaling_list_dc_coef = 16;
        }
        //printf("DC = %d\n",scaling_list_dc_coef);

        for (int i=0;i<coefNum;i++) {
          int scaling_list_delta_coef = get_svlc(br);
          if (scaling_list_delta_coef < -128 ||
              scaling_list_delta_coef >  127) {
            return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
          }

          nextCoef = (nextCoef + scaling_list_delta_coef + 256) % 256;
          curr_scaling_list[i] = nextCoef;
          //printf("curr %d = %d\n",i,nextCoef);
        }
      }


      // --- generate ScalingFactor arrays ---

      switch (sizeId) {
      case 0:
        fill_scaling_factor(&sclist->ScalingFactor_Size0[matrixId][0][0], curr_scaling_list, 0);
        break;

      case 1:
        fill_scaling_factor(&sclist->ScalingFactor_Size1[matrixId][0][0], curr_scaling_list, 1);
        break;

      case 2:
        fill_scaling_factor(&sclist->ScalingFactor_Size2[matrixId][0][0], curr_scaling_list, 2);
        sclist->ScalingFactor_Size2[matrixId][0][0] = scaling_list_dc_coef;
        //printf("DC coeff: %d\n", scaling_list_dc_coef);
        break;

      case 3:
        fill_scaling_factor(&sclist->ScalingFactor_Size3[matrixId][0][0], curr_scaling_list, 3);
        sclist->ScalingFactor_Size3[matrixId][0][0] = scaling_list_dc_coef;
        //printf("DC coeff: %d\n", scaling_list_dc_coef);
        break;
      }
    }
  }


  // --- fill 32x32 matrices for chroma

  const position* scan = get_scan_order(3, 0 /* diag */);
	
  for (int matrixId=0;matrixId<6;matrixId++)
    if (matrixId!=0 && matrixId!=3) {
      for (int i=0;i<64;i++) {
	int x = scan[i].x;
	int y = scan[i].y;
	int v = sclist->ScalingFactor_Size1[matrixId][y][x];

	for (int dy=0;dy<4;dy++)
	  for (int dx=0;dx<4;dx++) {
	    sclist->ScalingFactor_Size3[matrixId][4*y+dy][4*x+dx] = v;
	  }
      }

      sclist->ScalingFactor_Size3[matrixId][0][0] = sclist->ScalingFactor_Size1[matrixId][0][0];
    }
  
  return DE265_OK;
}
de265_error read_scaling_list(bitreader* br, const seq_parameter_set* sps,
                              scaling_list_data* sclist, bool inPPS)
{
  int dc_coeff[4][6];

  for (int sizeId=0;sizeId<4;sizeId++) {
     
    uint8_t scaling_list[6][32*32];

    for (int matrixId=0 ; matrixId<6 ; matrixId += (sizeId==3 ? 3 : 1)) {
      uint8_t* curr_scaling_list = scaling_list[matrixId];
      int scaling_list_dc_coef;

      int canonicalMatrixId = matrixId;
      if (sizeId==3 && matrixId==1) { canonicalMatrixId=3; }


       

      char scaling_list_pred_mode_flag = get_bits(br,1);
      if (!scaling_list_pred_mode_flag) {
        int scaling_list_pred_matrix_id_delta = get_uvlc(br);
        if (scaling_list_pred_matrix_id_delta == UVLC_ERROR ||
            scaling_list_pred_matrix_id_delta > matrixId) {
          return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
        }

         

        dc_coeff[sizeId][matrixId] = 16;
        scaling_list_dc_coef       = 16;

        if (scaling_list_pred_matrix_id_delta==0) {
          if (sizeId==0) {
            memcpy(curr_scaling_list, default_ScalingList_4x4, 16);
          }
          else {
            if (canonicalMatrixId<3)
              { memcpy(curr_scaling_list, default_ScalingList_8x8_intra,64); }
            else
              { memcpy(curr_scaling_list, default_ScalingList_8x8_inter,64); }
          }
        }
        else {
           
          if (sizeId==3) { assert(scaling_list_pred_matrix_id_delta==1); }

          int mID = matrixId - scaling_list_pred_matrix_id_delta;

          int len = (sizeId == 0 ? 16 : 64);
          memcpy(curr_scaling_list, scaling_list[mID], len);

          scaling_list_dc_coef       = dc_coeff[sizeId][mID];
          dc_coeff[sizeId][matrixId] = dc_coeff[sizeId][mID];
        }
      }
      else {
        int nextCoef=8;
        int coefNum = (sizeId==0 ? 16 : 64);
        if (sizeId>1) {
          scaling_list_dc_coef = get_svlc(br);
          if (scaling_list_dc_coef < -7 ||
              scaling_list_dc_coef > 247) {
            return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
          }

          scaling_list_dc_coef += 8;
          nextCoef=scaling_list_dc_coef;
          dc_coeff[sizeId][matrixId] = scaling_list_dc_coef;
        }
        else {
          scaling_list_dc_coef = 16;
        }
         

        for (int i=0;i<coefNum;i++) {
          int scaling_list_delta_coef = get_svlc(br);
          if (scaling_list_delta_coef < -128 ||
              scaling_list_delta_coef >  127) {
            return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE;
          }

          nextCoef = (nextCoef + scaling_list_delta_coef + 256) % 256;
          curr_scaling_list[i] = nextCoef;
           
        }
      }


       

      switch (sizeId) {
      case 0:
        fill_scaling_factor(&sclist->ScalingFactor_Size0[matrixId][0][0], curr_scaling_list, 0);
        break;

      case 1:
        fill_scaling_factor(&sclist->ScalingFactor_Size1[matrixId][0][0], curr_scaling_list, 1);
        break;

      case 2:
        fill_scaling_factor(&sclist->ScalingFactor_Size2[matrixId][0][0], curr_scaling_list, 2);
        sclist->ScalingFactor_Size2[matrixId][0][0] = scaling_list_dc_coef;
         
        break;

      case 3:
        fill_scaling_factor(&sclist->ScalingFactor_Size3[matrixId][0][0], curr_scaling_list, 3);
        sclist->ScalingFactor_Size3[matrixId][0][0] = scaling_list_dc_coef;
         
        break;
      }
    }
  }


   

  const position* scan = get_scan_order(3, 0  );
	
  for (int matrixId=0;matrixId<6;matrixId++)
    if (matrixId!=0 && matrixId!=3) {
      for (int i=0;i<64;i++) {
	int x = scan[i].x;
	int y = scan[i].y;
	int v = sclist->ScalingFactor_Size1[matrixId][y][x];

	for (int dy=0;dy<4;dy++)
	  for (int dx=0;dx<4;dx++) {
	    sclist->ScalingFactor_Size3[matrixId][4*y+dy][4*x+dx] = v;
	  }
      }

      sclist->ScalingFactor_Size3[matrixId][0][0] = sclist->ScalingFactor_Size1[matrixId][0][0];
    }
  
  return DE265_OK;
}