Merge branch 'static_tables'

This commit is contained in:
Ari Koivula 2014-04-16 12:13:25 +03:00
commit 7fd2cc7a52
15 changed files with 872 additions and 657 deletions

View file

@ -106,7 +106,9 @@
<ClCompile Include="..\..\src\picture.c" />
<ClCompile Include="..\..\src\rdo.c" />
<ClCompile Include="..\..\src\sao.c" />
<ClCompile Include="..\..\src\scalinglist.c" />
<ClCompile Include="..\..\src\search.c" />
<ClCompile Include="..\..\src\tables.c" />
<ClCompile Include="..\..\src\transform.c" />
</ItemGroup>
<ItemGroup>
@ -124,7 +126,9 @@
<ClInclude Include="..\..\src\picture.h" />
<ClInclude Include="..\..\src\rdo.h" />
<ClInclude Include="..\..\src\sao.h" />
<ClInclude Include="..\..\src\scalinglist.h" />
<ClInclude Include="..\..\src\search.h" />
<ClInclude Include="..\..\src\tables.h" />
<ClInclude Include="..\..\src\transform.h" />
<ClInclude Include="..\..\src\x86\cpu.h" />
</ItemGroup>

View file

@ -69,6 +69,12 @@
<ClCompile Include="..\..\src\extras\getopt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\scalinglist.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\tables.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\global.h">
@ -122,6 +128,12 @@
<ClInclude Include="..\..\src\extras\getopt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\scalinglist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\tables.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<YASM Include="..\..\src\x86\cpu.asm">

View file

@ -50,7 +50,7 @@ LDFLAGS += -lm
LD = gcc
YASM = yasm
ASMOBJS = cpu.o
OBJS = interface_main.o encmain.o bitstream.o cabac.o config.o context.o encoder.o filter.o inter.o intra.o nal.o picture.o rdo.o sao.o search.o transform.o extras/getopt.o
OBJS = interface_main.o encmain.o bitstream.o cabac.o config.o context.o encoder.o filter.o inter.o intra.o nal.o picture.o rdo.o sao.o scalinglist.o search.o tables.o transform.o extras/getopt.o
PROG = ./kvazaar
PROGS = $(PROG)
@ -71,6 +71,13 @@ cpu.o: x86/cpu.asm
%.d: %.c Makefile
$(CC) $(CCFLAGS) -MF"$@" -MG -MM -MP -MT"$@" -MT"$(<:.c=.o)" "$<"
generate_tables: tables.c global.h
$(CC) $(CCFLAGS) -DMAKE_GENERATE_TABLES=1 $< -o $@
tables_generated.h: generate_tables
./generate_tables > $@
clean:
rm -f $(OBJS) $(PROGS) $(ASMOBJS) $(DEPS)

View file

@ -41,6 +41,7 @@
#include "cabac.h"
#include "picture.h"
#include "transform.h"
#include "scalinglist.h"
// Assembly optimization headers
#include "x86/cpu.h"
@ -392,7 +393,7 @@ int main(int argc, char *argv[])
// Deallocating
config_destroy(cfg);
scalinglist_destroy(encoder);
scalinglist_destroy(&encoder->scaling_list);
picture_list_destroy(encoder->ref);
picture_destroy(encoder->in.cur_pic);
FREE_POINTER(encoder->in.cur_pic);

View file

@ -29,6 +29,7 @@
#include <string.h>
#include <assert.h>
#include "tables.h"
#include "config.h"
#include "cabac.h"
#include "picture.h"
@ -44,8 +45,6 @@
double g_lambda_cost[55];
double g_cur_lambda_cost;
const uint32_t* g_sig_last_scan[3][5];
int8_t g_convert_to_bit[LCU_WIDTH + 1];
int8_t g_bitdepth = 8;
/* Local functions. */
@ -56,163 +55,6 @@ static void encode_sao(const encoder_control * const encoder,
unsigned x_lcu, uint16_t y_lcu,
sao_info *sao_luma, sao_info *sao_chroma);
/**
* Initialize g_sig_last_scan with scan positions for a transform block of
* size width x height.
*/
static void init_sig_last_scan(uint32_t *buff_d, uint32_t *buff_h,
uint32_t *buff_v,
int32_t width, int32_t height)
{
uint32_t num_scan_pos = width * width;
uint32_t next_scan_pos = 0;
int32_t xx, yy, x, y;
uint32_t scan_line;
uint32_t blk_y, blk_x;
uint32_t blk;
uint32_t cnt = 0;
assert(width == height && width <= 32);
if (width <= 4) {
uint32_t *buff_tmp = buff_d;
for (scan_line = 0; next_scan_pos < num_scan_pos; scan_line++) {
int primary_dim = scan_line;
int second_dim = 0;
while (primary_dim >= width) {
second_dim++;
primary_dim--;
}
while (primary_dim >= 0 && second_dim < width) {
buff_tmp[next_scan_pos] = primary_dim * width + second_dim ;
next_scan_pos++;
second_dim++;
primary_dim--;
}
}
}
if (width > 4 && width <= 32) {
uint32_t num_blk_side = width >> 2;
uint32_t num_blks = num_blk_side * num_blk_side;
uint32_t log2_width = g_to_bits[width];
for (blk = 0; blk < num_blks; blk++) {
uint32_t init_blk_pos = g_sig_last_scan_cg[log2_width][SCAN_DIAG][blk];
next_scan_pos = 0;
{
uint32_t offset_y = init_blk_pos / num_blk_side;
uint32_t offset_x = init_blk_pos - offset_y * num_blk_side;
uint32_t offset_d = 4 * (offset_x + offset_y * width);
uint32_t offset_scan = 16 * blk;
for (scan_line = 0; next_scan_pos < 16; scan_line++) {
int primary_dim = scan_line;
int second_dim = 0;
//TODO: optimize
while (primary_dim >= 4) {
second_dim++;
primary_dim--;
}
while (primary_dim >= 0 && second_dim < 4) {
buff_d[next_scan_pos + offset_scan] = primary_dim * width +
second_dim + offset_d;
next_scan_pos++;
second_dim++;
primary_dim--;
}
}
}
}
}
if (width > 2) {
uint32_t num_blk_side = width >> 2;
for (blk_y = 0; blk_y < num_blk_side; blk_y++) {
for (blk_x = 0; blk_x < num_blk_side; blk_x++) {
uint32_t offset = blk_y * 4 * width + blk_x * 4;
for (y = 0; y < 4; y++) {
for (x = 0; x < 4; x++) {
buff_h[cnt] = y * width + x + offset;
cnt ++;
}
}
}
}
cnt = 0;
for (blk_x = 0; blk_x < num_blk_side; blk_x++) {
for (blk_y = 0; blk_y < num_blk_side; blk_y++) {
uint32_t offset = blk_y * 4 * width + blk_x * 4;
for (x = 0; x < 4; x++) {
for (y = 0; y < 4; y++) {
buff_v[cnt] = y * width + x + offset;
cnt ++;
}
}
}
}
} else {
for (yy = 0; yy < height; yy++) {
for (xx = 0; xx < width; xx++) {
buff_h[cnt] = yy * width + xx;
cnt ++;
}
}
cnt = 0;
for (xx = 0; xx < width; xx++) {
for (yy = 0; yy < height; yy++) {
buff_v[cnt] = yy * width + xx;
cnt ++;
}
}
}
}
void init_tables(void)
{
int i;
int c = 0;
memset( g_convert_to_bit,-1, sizeof( g_convert_to_bit ) );
for (i = 4; i < LCU_WIDTH; i *= 2) {
g_convert_to_bit[i] = (int8_t)c;
c++;
}
g_convert_to_bit[i] = (int8_t)c;
c = 2;
for (i = 0; i < 5; i++) {
uint32_t *sls0, *sls1, *sls2;
sls0 = (uint32_t*)malloc(c*c*sizeof(uint32_t));
sls1 = (uint32_t*)malloc(c*c*sizeof(uint32_t));
sls2 = (uint32_t*)malloc(c*c*sizeof(uint32_t));
init_sig_last_scan(sls0, sls1, sls2, c, c);
g_sig_last_scan[0][i] = sls0;
g_sig_last_scan[1][i] = sls1;
g_sig_last_scan[2][i] = sls2;
c <<= 1;
}
}
/*!
\brief Initializes lambda-value for current QP
@ -243,15 +85,6 @@ void init_lambda(const encoder_control * const encoder)
g_cur_lambda_cost = lambda;
}
void free_tables(void)
{
int i;
for (i = 0; i < 5; i++) {
FREE_POINTER(g_sig_last_scan[0][i]);
FREE_POINTER(g_sig_last_scan[1][i]);
FREE_POINTER(g_sig_last_scan[2][i]);
}
}
encoder_control *init_encoder_control(config *cfg)
{
encoder_control *enc_c = NULL;
@ -306,7 +139,7 @@ encoder_control *init_encoder_control(config *cfg)
}
// Initialize the scaling list
scalinglist_init(enc_c);
scalinglist_init(&enc_c->scaling_list);
pic_list = picture_list_init(MAX_REF_PIC_COUNT);
if(!pic_list) {
@ -322,7 +155,7 @@ encoder_control *init_encoder_control(config *cfg)
FILE* cqmfile;
cqmfile = cfg->cqmfile ? fopen(cfg->cqmfile, "rb") : NULL;
if (cqmfile) {
scalinglist_parse(enc_c, cqmfile);
scalinglist_parse(&enc_c->scaling_list, cqmfile);
fclose(cqmfile);
}
}
@ -478,7 +311,7 @@ void encode_one_frame(encoder_control* encoder)
cabac_start(&cabac);
init_contexts(&cabac, encoder->QP, encoder->in.cur_pic->slicetype);
scalinglist_process(encoder);
scalinglist_process(&encoder->scaling_list);
encode_slice_header(encoder);
bitstream_align(encoder->stream);
@ -864,7 +697,7 @@ static void encode_scaling_list(const encoder_control * const encoder)
uint32_t ref_matrix_id = UINT32_MAX;
for (pred_list_idx = list_id; pred_list_idx >= 0; pred_list_idx--) {
int32_t * const pred_list = (list_id == pred_list_idx) ?
const int32_t * const pred_list = (list_id == pred_list_idx) ?
scalinglist_get_default(size_id, pred_list_idx) :
encoder->scaling_list.scaling_list_coeff[size_id][pred_list_idx];
@ -972,8 +805,8 @@ void encode_seq_parameter_set(const encoder_control * const encoder)
WRITE_UE(encoder->stream, TR_DEPTH_INTRA, "max_transform_hierarchy_depth_intra");
// scaling list
WRITE_U(encoder->stream, encoder->scaling_list_enable, 1, "scaling_list_enable_flag");
if (encoder->scaling_list_enable) {
WRITE_U(encoder->stream, encoder->scaling_list.enable, 1, "scaling_list_enable_flag");
if (encoder->scaling_list.enable) {
WRITE_U(encoder->stream, 1, 1, "sps_scaling_list_data_present_flag");
encode_scaling_list(encoder);
}

View file

@ -30,15 +30,8 @@
#include "bitstream.h"
#include "cabac.h"
#include "config.h"
typedef struct {
int32_t scaling_list_dc [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM];
int32_t* scaling_list_coeff[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM];
int32_t* quant_coeff[4][6][6];
int32_t *de_quant_coeff [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM];
double* error_scale[4][6][6];
} scaling_list;
#include "tables.h"
#include "scalinglist.h"
/* TODO: add ME data */
@ -55,8 +48,8 @@ enum { FORMAT_400 = 0, FORMAT_420, FORMAT_422, FORMAT_444 };
typedef struct
{
FILE *file;
int32_t width; /*!< \brief input picture width */
int32_t height; /*!< \brief input picture height */
int32_t width; /*!< \brief input picture width (divisible by the minimum block size)*/
int32_t height; /*!< \brief input picture height (divisible by the minimum block size) */
int32_t real_width; /*!< \brief real input picture width */
int32_t real_height; /*!< \brief real input picture width */
int32_t height_in_lcu; /*!< \brief input picture width in LCU*/
@ -108,13 +101,10 @@ typedef struct
int8_t aud_enable;
//scaling list
uint8_t scaling_list_enable;
scaling_list scaling_list;
} encoder_control;
void init_tables(void);
void init_lambda(const encoder_control * const encoder);
void free_tables(void);
encoder_control *init_encoder_control(config *cfg);
void init_encoder_input(encoder_input *input, FILE* inputfile,
int32_t width, int32_t height);
@ -144,8 +134,6 @@ void encode_block_residual(const encoder_control * const encoder,
extern double g_lambda_cost[55];
extern double g_cur_lambda_cost;
extern int8_t g_convert_to_bit[LCU_WIDTH + 1];
extern int8_t g_bitdepth;
static const uint8_t g_group_idx[32] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6,
@ -156,86 +144,12 @@ static const uint8_t g_group_idx[32] = {
static const uint8_t g_min_in_group[10] = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24 };
/**
* List of mappings for coefficients within a transform block.
* First index: scan pattern 0 = diagonal, 1 = horizontal, 2 = vertical
* Second index: (log2 - 1) size of transform block. 2x2 .. 32x32
*/
extern const uint32_t* g_sig_last_scan[3][5];
/***
* List of indices for 4x4 coefficient groups within 8x8 transform block.
* First index: 0 = diagonal, 1 = vertical, 2 horizontal scan pattern.
* Second index: (log2 - 2) size of transform block. 4x4 .. 32x32
*/
static const uint32_t g_sig_last_scan_8x8[3][4] =
{ {0, 2, 1, 3},
{0, 1, 2, 3},
{0, 2, 1, 3}
};
/***
* List of indices for 4x4 coefficient groups within 16x16 transform block.
*/
static const uint32_t g_sig_last_scan_16x16[16] = {
0, 4, 1, 8,
5, 2, 12, 9,
6, 3, 13, 10,
7, 14, 11, 15
};
/***
* List of indices for 4x4 coefficient groups within 32x32 transform block.
*/
static const uint32_t g_sig_last_scan_32x32[64] = {
0, 8, 1, 16, 9, 2, 24, 17,
10, 3, 32, 25, 18, 11, 4, 40,
33, 26, 19, 12, 5, 48, 41, 34,
27, 20, 13, 6, 56, 49, 42, 35,
28, 21, 14, 7, 57, 50, 43, 36,
29, 22, 15, 58, 51, 44, 37, 30,
23, 59, 52, 45, 38, 31, 60, 53,
46, 39, 61, 54, 47, 62, 55, 63
};
/**
* List of pointers to coefficient group mappings.
* First index: (log2 - 2) of transform block size
* Second index: scan pattern 0 = diagonal, 1 = horizontal, 2 = vertical
*/
static const uint32_t *const g_sig_last_scan_cg[4][3] = {
{ g_sig_last_scan_8x8[0], g_sig_last_scan_8x8[1], g_sig_last_scan_8x8[2] }, // 4x4, only first element is used
{ g_sig_last_scan_8x8[0], g_sig_last_scan_8x8[1], g_sig_last_scan_8x8[2] },
{ g_sig_last_scan_16x16, 0, 0 },
{ g_sig_last_scan_32x32, 0, 0 }
};
//4 8 16 32 64 128
//0 1 2 3 4 5
static const uint8_t g_to_bits[129] =
{
0,
0,0,0,0,
0,0,0,1,
0,0,0,0,0,0,0,2,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5
};
#define TOBITS(len) g_to_bits[len]
#define C1FLAG_NUMBER 8 // maximum number of largerThan1 flag coded in one chunk
#define C2FLAG_NUMBER 1 // maximum number of largerThan2 flag coded in one chunk
enum COEFF_SCAN_TYPE
{
SCAN_DIAG = 0, // up-right diagonal scan
SCAN_HOR, // horizontal first scan
SCAN_VER // vertical first scan
};
#endif

View file

@ -171,5 +171,9 @@ typedef int16_t coefficient;
#define MAX_MATRIX_COEF_NUM 64
#define SCALING_LIST_REM_NUM 6
#define MAX_TR_DYNAMIC_RANGE 15
//Defined in encoder.c. It's global for now since it affects a lot of functions.
extern int8_t g_bitdepth;
#endif

View file

@ -33,7 +33,6 @@
#define QUANT_SHIFT 14
#define MAX_TR_DYNAMIC_RANGE 15
#define SCAN_SET_SIZE 16
#define LOG2_SCAN_SET_SIZE 4
#define SBH_THRESHOLD 4
@ -404,8 +403,8 @@ void rdoq(const encoder_control * const encoder, cabac_data *cabac, coefficient
{
int32_t q_bits = QUANT_SHIFT + qp_scaled/6 + transform_shift;
int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6];
double *err_scale = encoder->scaling_list.error_scale[log2_tr_size-2][scalinglist_type][qp_scaled%6];
const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6];
const double *err_scale = encoder->scaling_list.error_scale[log2_tr_size-2][scalinglist_type][qp_scaled%6];
double block_uncoded_cost = 0;

407
src/scalinglist.c Normal file
View file

@ -0,0 +1,407 @@
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2014 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Kvazaar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "tables.h"
#include "scalinglist.h"
const uint8_t g_scaling_list_num[4] = { 6, 6, 6, 2};
const uint16_t g_scaling_list_size[4] = { 16, 64, 256,1024};
static const uint8_t g_scaling_list_size_x[4] = { 4, 8,16,32};
static const int32_t g_quant_default_4x4[16] =
{
16,16,16,16,
16,16,16,16,
16,16,16,16,
16,16,16,16
};
static const int32_t g_quant_intra_default_8x8[64] =
{
16,16,16,16,17,18,21,24,
16,16,16,16,17,19,22,25,
16,16,17,18,20,22,25,29,
16,16,18,21,24,27,31,36,
17,17,20,24,30,35,41,47,
18,19,22,27,35,44,54,65,
21,22,25,31,41,54,70,88,
24,25,29,36,47,65,88,115
};
static const int32_t g_quant_inter_default_8x8[64] =
{
16,16,16,16,17,18,20,24,
16,16,16,17,18,20,24,25,
16,16,17,18,20,24,25,28,
16,17,18,20,24,25,28,33,
17,18,20,24,25,28,33,41,
18,20,24,25,28,33,41,54,
20,24,25,28,33,41,54,71,
24,25,28,33,41,54,71,91
};
const int16_t g_quant_scales[6] = { 26214,23302,20560,18396,16384,14564 };
const int16_t g_inv_quant_scales[6] = { 40,45,51,57,64,72 };
/**
* \brief Initialize scaling lists
*
*/
void scalinglist_init(scaling_list * const scaling_list)
{
uint32_t sizeId,listId,qp;
for (sizeId = 0; sizeId < 4; sizeId++) {
for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) {
for (qp = 0; qp < 6; qp++) {
if (!(sizeId == 3 && listId == 3)) {
scaling_list->quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t));
scaling_list->de_quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t));
scaling_list->error_scale[sizeId][listId][qp] = (double*)calloc(g_scaling_list_size[sizeId], sizeof(double));
}
}
scaling_list->scaling_list_coeff[sizeId][listId] = (int32_t*)calloc(MIN(MAX_MATRIX_COEF_NUM, g_scaling_list_size[sizeId]), sizeof(int32_t));
}
}
// alias, assign pointer to an existing array
for (qp = 0; qp < 6; qp++) {
scaling_list->quant_coeff[3][3][qp] = scaling_list->quant_coeff[3][1][qp];
scaling_list->de_quant_coeff[3][3][qp] = scaling_list->de_quant_coeff[3][1][qp];
scaling_list->error_scale[3][3][qp] = scaling_list->error_scale[3][1][qp];
}
//Initialize dc (otherwise we switch on undef in scalinglist_set)
for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; ++sizeId) {
for (listId = 0; listId < SCALING_LIST_NUM; ++listId) {
scaling_list->scaling_list_dc[sizeId][listId] = 0;
}
}
scaling_list->enable = 0;
}
/**
* \brief Destroy scaling list allocated memory
*
*/
void scalinglist_destroy(scaling_list * const scaling_list)
{
uint32_t sizeId,listId,qp;
for (sizeId = 0; sizeId < 4; sizeId++) {
for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) {
for (qp = 0; qp < 6; qp++) {
if (!(sizeId == 3 && listId == 3)) {
FREE_POINTER(scaling_list->quant_coeff[sizeId][listId][qp]);
FREE_POINTER(scaling_list->de_quant_coeff[sizeId][listId][qp]);
FREE_POINTER(scaling_list->error_scale[sizeId][listId][qp]);
}
}
FREE_POINTER(scaling_list->scaling_list_coeff[sizeId][listId]);
}
}
}
int scalinglist_parse(scaling_list * const scaling_list, FILE *fp)
{
#define LINE_BUFSIZE 1024
static const char matrix_type[4][6][20] =
{
{
"INTRA4X4_LUMA",
"INTRA4X4_CHROMAU",
"INTRA4X4_CHROMAV",
"INTER4X4_LUMA",
"INTER4X4_CHROMAU",
"INTER4X4_CHROMAV"
},
{
"INTRA8X8_LUMA",
"INTRA8X8_CHROMAU",
"INTRA8X8_CHROMAV",
"INTER8X8_LUMA",
"INTER8X8_CHROMAU",
"INTER8X8_CHROMAV"
},
{
"INTRA16X16_LUMA",
"INTRA16X16_CHROMAU",
"INTRA16X16_CHROMAV",
"INTER16X16_LUMA",
"INTER16X16_CHROMAU",
"INTER16X16_CHROMAV"
},
{
"INTRA32X32_LUMA",
"INTER32X32_LUMA",
},
};
static const char matrix_type_dc[2][6][22] =
{
{
"INTRA16X16_LUMA_DC",
"INTRA16X16_CHROMAU_DC",
"INTRA16X16_CHROMAV_DC",
"INTER16X16_LUMA_DC",
"INTER16X16_CHROMAU_DC",
"INTER16X16_CHROMAV_DC"
},
{
"INTRA32X32_LUMA_DC",
"INTER32X32_LUMA_DC",
},
};
uint32_t size_id;
for (size_id = 0; size_id < SCALING_LIST_SIZE_NUM; size_id++) {
uint32_t list_id;
uint32_t size = MIN(MAX_MATRIX_COEF_NUM, (int32_t)g_scaling_list_size[size_id]);
//const uint32_t * const scan = (size_id == 0) ? g_sig_last_scan[SCAN_DIAG][1] : g_sig_last_scan_32x32;
for (list_id = 0; list_id < g_scaling_list_num[size_id]; list_id++) {
int found;
uint32_t i;
int32_t data;
//This IS valid (our pointer is dynamically allocated in scalinglist_init)
int32_t *coeff = (int32_t*) scaling_list->scaling_list_coeff[size_id][list_id];
char line[LINE_BUFSIZE + 1] = { 0 }; // +1 for null-terminator
// Go back for each matrix.
fseek(fp, 0, SEEK_SET);
do {
if (!fgets(line, LINE_BUFSIZE, fp) ||
((found = !!strstr(line, matrix_type[size_id][list_id])) == 0 && feof(fp)))
return 0;
} while (!found);
for (i = 0; i < size;) {
char *p;
if (!fgets(line, LINE_BUFSIZE, fp))
return 0;
p = line;
// Read coefficients per line.
// The comma (,) character is used as a separator.
// The coefficients are stored in up-right diagonal order.
do {
int ret = sscanf(p, "%d", &data);
if (ret != 1)
break;
else if (data < 1 || data > 255)
return 0;
coeff[i++] = data;
if (i == size)
break;
// Seek to the next newline, null-terminator or comma.
while (*p != '\n' && *p != '\0' && *p != ',')
++p;
if (*p == ',')
++p;
} while (*p != '\n' && *p != '\0');
}
// Set DC value.
if (size_id >= SCALING_LIST_16x16) {
fseek(fp, 0, SEEK_SET);
do {
if (!fgets(line, LINE_BUFSIZE, fp) ||
((found = !!strstr(line, matrix_type_dc[size_id - SCALING_LIST_16x16][list_id])) == 0 && feof(fp)))
return 0;
} while (!found);
if (1 != fscanf(fp, "%d", &data) || data < 1 || data > 255)
return 0;
scaling_list->scaling_list_dc[size_id][list_id] = data;
} else
scaling_list->scaling_list_dc[size_id][list_id] = coeff[0];
}
}
scaling_list->enable = 1;
return 1;
#undef LINE_BUFSIZE
}
const int32_t *scalinglist_get_default(const uint32_t size_id, const uint32_t list_id)
{
const int32_t *list_ptr = g_quant_intra_default_8x8; // Default to "8x8" intra
switch(size_id) {
case SCALING_LIST_4x4:
list_ptr = g_quant_default_4x4;
break;
case SCALING_LIST_8x8:
case SCALING_LIST_16x16:
if (list_id > 2) list_ptr = g_quant_inter_default_8x8;
break;
case SCALING_LIST_32x32:
if (list_id > 0) list_ptr = g_quant_inter_default_8x8;
break;
}
return list_ptr;
}
/**
* \brief get scaling list for decoder
*
*/
static void scalinglist_process_dec(const int32_t * const coeff, int32_t *dequantcoeff,
int32_t inv_quant_scales, uint32_t height,
uint32_t width, uint32_t ratio,
int32_t size_num, uint32_t dc,
uint8_t flat)
{
uint32_t j,i;
// Flat scaling list
if (flat) {
for (j = 0; j < height * width; j++) {
*dequantcoeff++ = inv_quant_scales<<4;
}
} else {
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
dequantcoeff[j*width + i] = inv_quant_scales * coeff[size_num * (j / ratio) + i / ratio];
}
}
if (ratio > 1) {
dequantcoeff[0] = inv_quant_scales * dc;
}
}
}
/**
* \brief get scaling list for encoder
*
*/
void scalinglist_process_enc(const int32_t * const coeff, int32_t* quantcoeff, const int32_t quant_scales,
const uint32_t height, const uint32_t width, const uint32_t ratio,
const int32_t size_num, const uint32_t dc, const uint8_t flat)
{
uint32_t j,i;
int32_t nsqth = (height < width) ? 4: 1; //!< height ratio for NSQT
int32_t nsqtw = (width < height) ? 4: 1; //!< width ratio for NSQT
// Flat scaling list
if (flat) {
for (j = 0; j < height * width; j++) {
*quantcoeff++ = quant_scales>>4;
}
} else {
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
uint32_t coeffpos = size_num * (j * nsqth / ratio) + i * nsqtw / ratio;
quantcoeff[j*width + i] = quant_scales / ((coeffpos > 63) ? 1 : coeff[coeffpos]);
}
}
if (ratio > 1) {
quantcoeff[0] = quant_scales / dc;
}
}
}
/** set error scale coefficients
* \param list List ID
* \param uiSize Size
* \param uiQP Quantization parameter
*/
void scalinglist_set_err_scale(scaling_list * const scaling_list, uint32_t list,uint32_t size, uint32_t qp)
{
uint32_t log2_tr_size = g_convert_to_bit[ g_scaling_list_size_x[size] ] + 2;
int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - g_bitdepth - log2_tr_size; // Represents scaling through forward transform
uint32_t i,max_num_coeff = g_scaling_list_size[size];
const int32_t *quantcoeff = scaling_list->quant_coeff[size][list][qp];
//This cast is allowed, since error_scale is a malloc'd pointer in scalinglist_init
double *err_scale = (double *) scaling_list->error_scale[size][list][qp];
// Compensate for scaling of bitcount in Lagrange cost function
double scale = (double)(1<<15);
// Compensate for scaling through forward transform
scale = scale*pow(2.0,-2.0*transform_shift);
for(i=0;i<max_num_coeff;i++) {
err_scale[i] = scale / quantcoeff[i] / quantcoeff[i] / (1<<(2*(g_bitdepth-8)));
}
}
/**
* \brief set scaling lists
*
*/
void scalinglist_set(scaling_list * const scaling_list, const int32_t * const coeff, uint32_t listId, uint32_t sizeId, uint32_t qp)
{
const uint32_t width = g_scaling_list_size_x[sizeId];
const uint32_t height = g_scaling_list_size_x[sizeId];
const uint32_t ratio = g_scaling_list_size_x[sizeId] / MIN(8, g_scaling_list_size_x[sizeId]);
const uint32_t dc = scaling_list->scaling_list_dc[sizeId][listId] != 0 ? scaling_list->scaling_list_dc[sizeId][listId] : 16;
//These cast are allowed, since these are pointer's to malloc'd area in scalinglist_init
int32_t *quantcoeff = (int32_t*) scaling_list->quant_coeff[sizeId][listId][qp];
int32_t *dequantcoeff = (int32_t*) scaling_list->de_quant_coeff[sizeId][listId][qp];
// Encoder list
scalinglist_process_enc(coeff, quantcoeff, g_quant_scales[qp]<<4, height, width, ratio,
MIN(8, g_scaling_list_size_x[sizeId]), dc, !scaling_list->enable);
// Decoder list
scalinglist_process_dec(coeff, dequantcoeff, g_inv_quant_scales[qp], height, width, ratio,
MIN(8, g_scaling_list_size_x[sizeId]), dc, !scaling_list->enable);
// TODO: support NSQT
// if(sizeId == /*SCALING_LIST_32x32*/3 || sizeId == /*SCALING_LIST_16x16*/2) { //for NSQT
// quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_VER*/1];
// scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height,width>>2,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0);
// quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_HOR*/2];
// scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height>>2,width,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0);
// }
}
/**
* \brief
*
*/
void scalinglist_process(scaling_list * const scaling_list)
{
uint32_t size,list,qp;
for (size = 0; size < SCALING_LIST_SIZE_NUM; size++) {
for (list = 0; list < g_scaling_list_num[size]; list++) {
const int32_t * const list_ptr = scaling_list->enable ?
scaling_list->scaling_list_coeff[size][list] :
scalinglist_get_default(size, list);
for (qp = 0; qp < SCALING_LIST_REM_NUM; qp++) {
scalinglist_set(scaling_list, list_ptr, list, size, qp);
scalinglist_set_err_scale(scaling_list, list, size, qp);
}
}
}
}

57
src/scalinglist.h Normal file
View file

@ -0,0 +1,57 @@
#ifndef SCALINGLIST_H_
#define SCALINGLIST_H_
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2014 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Kvazaar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
/*
* \file
* \brief Coding Unit (CU) and picture data related functions.
*/
#include "global.h"
typedef struct {
int8_t enable;
int32_t scaling_list_dc [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM];
const int32_t *scaling_list_coeff[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM];
const int32_t *quant_coeff[4][6][6];
const int32_t *de_quant_coeff [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM];
const double *error_scale[4][6][6];
} scaling_list;
extern const uint8_t g_scaling_list_num[4];
extern const uint16_t g_scaling_list_size[4];
const int32_t *scalinglist_get_default(const uint32_t size_id, const uint32_t list_id);
void scalinglist_init(scaling_list * const scaling_list);
void scalinglist_destroy(scaling_list * const scaling_list);
int scalinglist_parse(scaling_list * const scaling_list, FILE *fp);
void scalinglist_process(scaling_list * const scaling_list);
//void scalinglist_set(scaling_list * const scaling_list, const int32_t * const coeff, uint32_t listId, uint32_t sizeId, uint32_t qp);
//void scalinglist_set_err_scale(scaling_list * const scaling_list, uint32_t list, uint32_t size, uint32_t qp);
#endif

252
src/tables.c Normal file
View file

@ -0,0 +1,252 @@
#if MAKE_GENERATE_TABLES
#define DONT_USE_GENERATED_TABLES 1
#endif
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "global.h"
#include "tables.h"
#ifndef USING_GENERATED_TABLES
const uint32_t* g_sig_last_scan[3][5];
int8_t g_convert_to_bit[LCU_WIDTH + 1];
/**
* Initialize g_sig_last_scan with scan positions for a transform block of
* size width x height.
*/
static void init_sig_last_scan(uint32_t *buff_d, uint32_t *buff_h,
uint32_t *buff_v,
int32_t width, int32_t height)
{
uint32_t num_scan_pos = width * width;
uint32_t next_scan_pos = 0;
int32_t xx, yy, x, y;
uint32_t scan_line;
uint32_t blk_y, blk_x;
uint32_t blk;
uint32_t cnt = 0;
assert(width == height && width <= 32);
if (width <= 4) {
uint32_t *buff_tmp = buff_d;
for (scan_line = 0; next_scan_pos < num_scan_pos; scan_line++) {
int primary_dim = scan_line;
int second_dim = 0;
while (primary_dim >= width) {
second_dim++;
primary_dim--;
}
while (primary_dim >= 0 && second_dim < width) {
buff_tmp[next_scan_pos] = primary_dim * width + second_dim ;
next_scan_pos++;
second_dim++;
primary_dim--;
}
}
}
if (width > 4 && width <= 32) {
uint32_t num_blk_side = width >> 2;
uint32_t num_blks = num_blk_side * num_blk_side;
uint32_t log2_width = g_to_bits[width];
for (blk = 0; blk < num_blks; blk++) {
uint32_t init_blk_pos = g_sig_last_scan_cg[log2_width][SCAN_DIAG][blk];
next_scan_pos = 0;
{
uint32_t offset_y = init_blk_pos / num_blk_side;
uint32_t offset_x = init_blk_pos - offset_y * num_blk_side;
uint32_t offset_d = 4 * (offset_x + offset_y * width);
uint32_t offset_scan = 16 * blk;
for (scan_line = 0; next_scan_pos < 16; scan_line++) {
int primary_dim = scan_line;
int second_dim = 0;
//TODO: optimize
while (primary_dim >= 4) {
second_dim++;
primary_dim--;
}
while (primary_dim >= 0 && second_dim < 4) {
buff_d[next_scan_pos + offset_scan] = primary_dim * width +
second_dim + offset_d;
next_scan_pos++;
second_dim++;
primary_dim--;
}
}
}
}
}
if (width > 2) {
uint32_t num_blk_side = width >> 2;
for (blk_y = 0; blk_y < num_blk_side; blk_y++) {
for (blk_x = 0; blk_x < num_blk_side; blk_x++) {
uint32_t offset = blk_y * 4 * width + blk_x * 4;
for (y = 0; y < 4; y++) {
for (x = 0; x < 4; x++) {
buff_h[cnt] = y * width + x + offset;
cnt ++;
}
}
}
}
cnt = 0;
for (blk_x = 0; blk_x < num_blk_side; blk_x++) {
for (blk_y = 0; blk_y < num_blk_side; blk_y++) {
uint32_t offset = blk_y * 4 * width + blk_x * 4;
for (x = 0; x < 4; x++) {
for (y = 0; y < 4; y++) {
buff_v[cnt] = y * width + x + offset;
cnt ++;
}
}
}
}
} else {
for (yy = 0; yy < height; yy++) {
for (xx = 0; xx < width; xx++) {
buff_h[cnt] = yy * width + xx;
cnt ++;
}
}
cnt = 0;
for (xx = 0; xx < width; xx++) {
for (yy = 0; yy < height; yy++) {
buff_v[cnt] = yy * width + xx;
cnt ++;
}
}
}
}
void init_tables(void)
{
int i;
int c = 0;
memset( g_convert_to_bit,-1, sizeof( g_convert_to_bit ) );
for (i = 4; i < LCU_WIDTH; i *= 2) {
g_convert_to_bit[i] = (int8_t)c;
c++;
}
g_convert_to_bit[i] = (int8_t)c;
c = 2;
for (i = 0; i < 5; i++) {
uint32_t *sls0, *sls1, *sls2;
sls0 = (uint32_t*)malloc(c*c*sizeof(uint32_t));
sls1 = (uint32_t*)malloc(c*c*sizeof(uint32_t));
sls2 = (uint32_t*)malloc(c*c*sizeof(uint32_t));
init_sig_last_scan(sls0, sls1, sls2, c, c);
g_sig_last_scan[0][i] = sls0;
g_sig_last_scan[1][i] = sls1;
g_sig_last_scan[2][i] = sls2;
c <<= 1;
}
}
void free_tables(void)
{
int i;
for (i = 0; i < 5; i++) {
FREE_POINTER(g_sig_last_scan[0][i]);
FREE_POINTER(g_sig_last_scan[1][i]);
FREE_POINTER(g_sig_last_scan[2][i]);
}
}
#else //USING_GENERATED_TABLES
//do nothing (precomputed)
void init_tables(void) {}
void free_tables(void) {}
#endif
#if MAKE_GENERATE_TABLES == 1 && DONT_USE_GENERATED_TABLES == 1
int main() {
int i, c, j, h;
printf("//This file is automatically generated by generate_tables, do not edit.\n\n");
printf("#ifndef TABLES_GENERATED_H_\n");
printf("#define TABLES_GENERATED_H_\n\n");
printf("#include \"global.h\"\n\n");
printf("#if LCU_WIDTH==%d && !DONT_USE_GENERATED_TABLES\n", LCU_WIDTH);
printf("#define USING_GENERATED_TABLES\n\n");
init_tables();
printf("static const int8_t g_convert_to_bit[LCU_WIDTH + 1] = {");
for (i=0; i < LCU_WIDTH + 1; ++i) {
if (i!=LCU_WIDTH) {
printf("%d, ", g_convert_to_bit[i]);
} else {
printf("%d", g_convert_to_bit[i]);
}
}
printf("};\n\n");
c = 2;
for (i = 0; i < 5; i++) {
for (h = 0; h < 3; h++) {
printf("static const uint32_t g_sig_last_scan_%d_%d[%d] = {",h,i,c*c);
for (j = 0; j < c*c; ++j) {
if (j!=c*c-1) {
printf("%u, ", g_sig_last_scan[h][i][j]);
} else {
printf("%u", g_sig_last_scan[h][i][j]);
}
}
printf("};\n");
}
printf("\n");
c <<= 1;
}
printf("static const uint32_t* const g_sig_last_scan[3][5] = {\n");
for (h = 0; h < 3; h++) {
printf(" {");
for (i = 0; i < 5; i++) {
if (i!=4) {
printf("g_sig_last_scan_%d_%d, ", h, i);
} else {
printf("g_sig_last_scan_%d_%d", h, i);
}
}
if (h<2) {
printf("},\n");
} else {
printf("}\n");
}
}
printf("};\n");
printf("#endif //LCU_WIDTH==%d\n", LCU_WIDTH);
printf("#endif //TABLES_GENERATED_H_\n");
return 0;
}
#endif

109
src/tables.h Normal file
View file

@ -0,0 +1,109 @@
#ifndef TABLES_H_
#define TABLES_H_
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2014 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Kvazaar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "global.h"
#include "tables_generated.h"
void init_tables(void);
void free_tables(void);
//4 8 16 32 64 128
//0 1 2 3 4 5
static const uint8_t g_to_bits[129] =
{
0,
0,0,0,0,
0,0,0,1,
0,0,0,0,0,0,0,2,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5
};
#define TOBITS(len) g_to_bits[len]
/***
* List of indices for 4x4 coefficient groups within 8x8 transform block.
* First index: 0 = diagonal, 1 = vertical, 2 horizontal scan pattern.
* Second index: (log2 - 2) size of transform block. 4x4 .. 32x32
*/
static const uint32_t g_sig_last_scan_8x8[3][4] =
{ {0, 2, 1, 3},
{0, 1, 2, 3},
{0, 2, 1, 3}
};
/***
* List of indices for 4x4 coefficient groups within 16x16 transform block.
*/
static const uint32_t g_sig_last_scan_16x16[16] = {
0, 4, 1, 8,
5, 2, 12, 9,
6, 3, 13, 10,
7, 14, 11, 15
};
/***
* List of indices for 4x4 coefficient groups within 32x32 transform block.
*/
static const uint32_t g_sig_last_scan_32x32[64] = {
0, 8, 1, 16, 9, 2, 24, 17,
10, 3, 32, 25, 18, 11, 4, 40,
33, 26, 19, 12, 5, 48, 41, 34,
27, 20, 13, 6, 56, 49, 42, 35,
28, 21, 14, 7, 57, 50, 43, 36,
29, 22, 15, 58, 51, 44, 37, 30,
23, 59, 52, 45, 38, 31, 60, 53,
46, 39, 61, 54, 47, 62, 55, 63
};
/**
* List of pointers to coefficient group mappings.
* First index: (log2 - 2) of transform block size
* Second index: scan pattern 0 = diagonal, 1 = horizontal, 2 = vertical
*/
static const uint32_t *const g_sig_last_scan_cg[4][3] = {
{ g_sig_last_scan_8x8[0], g_sig_last_scan_8x8[1], g_sig_last_scan_8x8[2] }, // 4x4, only first element is used
{ g_sig_last_scan_8x8[0], g_sig_last_scan_8x8[1], g_sig_last_scan_8x8[2] },
{ g_sig_last_scan_16x16, 0, 0 },
{ g_sig_last_scan_32x32, 0, 0 }
};
enum COEFF_SCAN_TYPE
{
SCAN_DIAG = 0, // up-right diagonal scan
SCAN_HOR, // horizontal first scan
SCAN_VER // vertical first scan
};
#ifndef USING_GENERATED_TABLES
/**
* List of mappings for coefficients within a transform block.
* First index: scan pattern 0 = diagonal, 1 = horizontal, 2 = vertical
* Second index: (log2 - 1) size of transform block. 2x2 .. 32x32
*/
extern const uint32_t* g_sig_last_scan[3][5];
extern int8_t g_convert_to_bit[LCU_WIDTH + 1];
#endif
#endif //TABLES_H_

1
src/tables_generated.h Normal file
View file

@ -0,0 +1 @@
//This file will be autogenerated by generate_tables

View file

@ -110,37 +110,6 @@ const int16_t g_t32[32][32] =
{ 4,-13, 22,-31, 38,-46, 54,-61, 67,-73, 78,-82, 85,-88, 90,-90, 90,-90, 88,-85, 82,-78, 73,-67, 61,-54, 46,-38, 31,-22, 13, -4}
};
const int32_t g_quant_default_4x4[16] =
{
16,16,16,16,
16,16,16,16,
16,16,16,16,
16,16,16,16
};
const int32_t g_quant_intra_default_8x8[64] =
{
16,16,16,16,17,18,21,24,
16,16,16,16,17,19,22,25,
16,16,17,18,20,22,25,29,
16,16,18,21,24,27,31,36,
17,17,20,24,30,35,41,47,
18,19,22,27,35,44,54,65,
21,22,25,31,41,54,70,88,
24,25,29,36,47,65,88,115
};
const int32_t g_quant_inter_default_8x8[64] =
{
16,16,16,16,17,18,20,24,
16,16,16,17,18,20,24,25,
16,16,17,18,20,24,25,28,
16,17,18,20,24,25,28,33,
17,18,20,24,25,28,33,41,
18,20,24,25,28,33,41,54,
20,24,25,28,33,41,54,71,
24,25,28,33,41,54,71,91
};
const uint8_t g_chroma_scale[58]=
{
@ -150,12 +119,6 @@ const uint8_t g_chroma_scale[58]=
45,46,47,48,49,50,51
};
const uint8_t g_scaling_list_num[4] = { 6, 6, 6, 2};
const uint16_t g_scaling_list_size[4] = { 16, 64, 256,1024};
const uint8_t g_scaling_list_size_x[4] = { 4, 8,16,32};
const int16_t g_quant_scales[6] = { 26214,23302,20560,18396,16384,14564 };
const int16_t g_inv_quant_scales[6] = { 40,45,51,57,64,72 };
//////////////////////////////////////////////////////////////////////////
// FUNCTIONS
//
@ -180,200 +143,7 @@ int32_t get_scaled_qp(int8_t type, int8_t qp, int8_t qp_offset)
return qp_scaled;
}
/**
* \brief Initialize scaling lists
*
*/
void scalinglist_init(encoder_control * const encoder)
{
uint32_t sizeId,listId,qp;
for (sizeId = 0; sizeId < 4; sizeId++) {
for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) {
for (qp = 0; qp < 6; qp++) {
if (!(sizeId == 3 && listId == 3)) {
encoder->scaling_list.quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t));
encoder->scaling_list.de_quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t));
encoder->scaling_list.error_scale[sizeId][listId][qp] = (double*)calloc(g_scaling_list_size[sizeId], sizeof(double));
}
}
encoder->scaling_list.scaling_list_coeff[sizeId][listId] = (int32_t*)calloc(MIN(MAX_MATRIX_COEF_NUM, g_scaling_list_size[sizeId]), sizeof(int32_t));
}
}
// alias, assign pointer to an existing array
for (qp = 0; qp < 6; qp++) {
encoder->scaling_list.quant_coeff[3][3][qp] = encoder->scaling_list.quant_coeff[3][1][qp];
encoder->scaling_list.de_quant_coeff[3][3][qp] = encoder->scaling_list.de_quant_coeff[3][1][qp];
encoder->scaling_list.error_scale[3][3][qp] = encoder->scaling_list.error_scale[3][1][qp];
}
//Initialize dc (otherwise we switch on undef in scalinglist_set)
for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; ++sizeId) {
for (listId = 0; listId < SCALING_LIST_NUM; ++listId) {
encoder->scaling_list.scaling_list_dc[sizeId][listId] = 0;
}
}
encoder->scaling_list_enable = 0;
}
/**
* \brief Destroy scaling list allocated memory
*
*/
void scalinglist_destroy(encoder_control * const encoder)
{
uint32_t sizeId,listId,qp;
for (sizeId = 0; sizeId < 4; sizeId++) {
for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) {
for (qp = 0; qp < 6; qp++) {
if (!(sizeId == 3 && listId == 3)) {
FREE_POINTER( encoder->scaling_list.quant_coeff[sizeId][listId][qp]);
FREE_POINTER(encoder->scaling_list.de_quant_coeff[sizeId][listId][qp]);
FREE_POINTER( encoder->scaling_list.error_scale[sizeId][listId][qp]);
}
}
FREE_POINTER(encoder->scaling_list.scaling_list_coeff[sizeId][listId]);
}
}
}
/**
* \brief
*
*/
void scalinglist_process(const encoder_control * const encoder)
{
uint32_t size,list,qp;
for (size = 0; size < SCALING_LIST_SIZE_NUM; size++) {
for (list = 0; list < g_scaling_list_num[size]; list++) {
const int32_t * const list_ptr = encoder->scaling_list_enable ?
encoder->scaling_list.scaling_list_coeff[size][list] :
scalinglist_get_default(size, list);
for (qp = 0; qp < SCALING_LIST_REM_NUM; qp++) {
scalinglist_set(encoder, list_ptr, list, size, qp);
scalinglist_set_err_scale(encoder, list, size, qp);
}
}
}
}
/** set error scale coefficients
* \param list List ID
* \param uiSize Size
* \param uiQP Quantization parameter
*/
#define MAX_TR_DYNAMIC_RANGE 15
void scalinglist_set_err_scale(const encoder_control * const encoder, uint32_t list,uint32_t size, uint32_t qp)
{
uint32_t log2_tr_size = g_convert_to_bit[ g_scaling_list_size_x[size] ] + 2;
int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - g_bitdepth - log2_tr_size; // Represents scaling through forward transform
uint32_t i,max_num_coeff = g_scaling_list_size[size];
int32_t *quantcoeff = encoder->scaling_list.quant_coeff[size][list][qp];
double *err_scale = encoder->scaling_list.error_scale[size][list][qp];
// Compensate for scaling of bitcount in Lagrange cost function
double scale = (double)(1<<15);
// Compensate for scaling through forward transform
scale = scale*pow(2.0,-2.0*transform_shift);
for(i=0;i<max_num_coeff;i++) {
err_scale[i] = scale / quantcoeff[i] / quantcoeff[i] / (1<<(2*(g_bitdepth-8)));
}
}
/**
* \brief get scaling list for encoder
*
*/
void scalinglist_process_enc(const int32_t * const coeff, int32_t* quantcoeff, int32_t quant_scales, uint32_t height, uint32_t width, uint32_t ratio, int32_t size_num, uint32_t dc, uint8_t flat)
{
uint32_t j,i;
int32_t nsqth = (height < width) ? 4: 1; //!< height ratio for NSQT
int32_t nsqtw = (width < height) ? 4: 1; //!< width ratio for NSQT
// Flat scaling list
if (flat) {
for (j = 0; j < height * width; j++) {
*quantcoeff++ = quant_scales>>4;
}
} else {
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
uint32_t coeffpos = size_num * (j * nsqth / ratio) + i * nsqtw / ratio;
quantcoeff[j*width + i] = quant_scales / ((coeffpos > 63) ? 1 : coeff[coeffpos]);
}
}
if (ratio > 1) {
quantcoeff[0] = quant_scales / dc;
}
}
}
/**
* \brief get scaling list for decoder
*
*/
static void scalinglist_process_dec(const int32_t * const coeff, int32_t *dequantcoeff,
int32_t inv_quant_scales, uint32_t height,
uint32_t width, uint32_t ratio,
int32_t size_num, uint32_t dc,
uint8_t flat)
{
uint32_t j,i;
// Flat scaling list
if (flat) {
for (j = 0; j < height * width; j++) {
*dequantcoeff++ = inv_quant_scales<<4;
}
} else {
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
dequantcoeff[j*width + i] = inv_quant_scales * coeff[size_num * (j / ratio) + i / ratio];
}
}
if (ratio > 1) {
dequantcoeff[0] = inv_quant_scales * dc;
}
}
}
/**
* \brief set scaling lists
*
*/
void scalinglist_set(const encoder_control * const encoder, const int32_t * const coeff, uint32_t listId, uint32_t sizeId, uint32_t qp)
{
uint32_t width = g_scaling_list_size_x[sizeId];
uint32_t height = g_scaling_list_size_x[sizeId];
uint32_t ratio = g_scaling_list_size_x[sizeId] / MIN(8, g_scaling_list_size_x[sizeId]);
int32_t *quantcoeff = encoder->scaling_list.quant_coeff[sizeId][listId][qp];
int32_t *dequantcoeff = encoder->scaling_list.de_quant_coeff[sizeId][listId][qp];
uint32_t dc = encoder->scaling_list.scaling_list_dc[sizeId][listId] != 0 ? encoder->scaling_list.scaling_list_dc[sizeId][listId] : 16;
// Encoder list
scalinglist_process_enc(coeff, quantcoeff, g_quant_scales[qp]<<4, height, width, ratio,
MIN(8, g_scaling_list_size_x[sizeId]), dc, !encoder->scaling_list_enable);
// Decoder list
scalinglist_process_dec(coeff, dequantcoeff, g_inv_quant_scales[qp], height, width, ratio,
MIN(8, g_scaling_list_size_x[sizeId]), dc, !encoder->scaling_list_enable);
// TODO: support NSQT
// if(sizeId == /*SCALING_LIST_32x32*/3 || sizeId == /*SCALING_LIST_16x16*/2) { //for NSQT
// quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_VER*/1];
// scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height,width>>2,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0);
// quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_HOR*/2];
// scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height>>2,width,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0);
// }
}
static void partial_butterfly_4(short *src, short *dst,
@ -849,7 +619,6 @@ void itransform2d(int16_t *block,int16_t *coeff, int8_t block_size, int32_t mode
#define QUANT_SHIFT 14
#define MAX_TR_DYNAMIC_RANGE 15
/**
* \brief quantize transformed coefficents
*
@ -872,7 +641,7 @@ void quant(const encoder_control * const encoder, int16_t *coef, int16_t *q_coef
uint32_t log2_tr_size = g_convert_to_bit[ width ] + 2;
int32_t scalinglist_type = (block_type == CU_INTRA ? 0 : 3) + (int8_t)("\0\3\1\2"[type]);
int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6];
const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6];
int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - g_bitdepth - log2_tr_size; //!< Represents scaling through forward transform
int32_t q_bits = QUANT_SHIFT + qp_scaled/6 + transform_shift;
@ -995,12 +764,12 @@ void dequant(const encoder_control * const encoder, int16_t *q_coef, int16_t *co
shift = 20 - QUANT_SHIFT - transform_shift;
if (encoder->scaling_list_enable)
if (encoder->scaling_list.enable)
{
uint32_t log2_tr_size = g_convert_to_bit[ width ] + 2;
int32_t scalinglist_type = (block_type == CU_INTRA ? 0 : 3) + (int8_t)("\0\3\1\2"[type]);
int32_t *dequant_coef = encoder->scaling_list.de_quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6];
const int32_t *dequant_coef = encoder->scaling_list.de_quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6];
shift += 4;
if (shift >qp_scaled / 6) {
@ -1031,143 +800,3 @@ void dequant(const encoder_control * const encoder, int16_t *q_coef, int16_t *co
}
}
int32_t *scalinglist_get_default(uint32_t size_id, uint32_t list_id)
{
int32_t *list_ptr = (int32_t *)g_quant_intra_default_8x8; // Default to "8x8" intra
switch(size_id) {
case SCALING_LIST_4x4:
list_ptr = (int32_t *)g_quant_default_4x4;
break;
case SCALING_LIST_8x8:
case SCALING_LIST_16x16:
if (list_id > 2) list_ptr = (int32_t *)g_quant_inter_default_8x8;
break;
case SCALING_LIST_32x32:
if (list_id > 0) list_ptr = (int32_t *)g_quant_inter_default_8x8;
break;
}
return list_ptr;
}
int scalinglist_parse(encoder_control * const encoder, FILE *fp)
{
#define LINE_BUFSIZE 1024
static const char matrix_type[4][6][20] =
{
{
"INTRA4X4_LUMA",
"INTRA4X4_CHROMAU",
"INTRA4X4_CHROMAV",
"INTER4X4_LUMA",
"INTER4X4_CHROMAU",
"INTER4X4_CHROMAV"
},
{
"INTRA8X8_LUMA",
"INTRA8X8_CHROMAU",
"INTRA8X8_CHROMAV",
"INTER8X8_LUMA",
"INTER8X8_CHROMAU",
"INTER8X8_CHROMAV"
},
{
"INTRA16X16_LUMA",
"INTRA16X16_CHROMAU",
"INTRA16X16_CHROMAV",
"INTER16X16_LUMA",
"INTER16X16_CHROMAU",
"INTER16X16_CHROMAV"
},
{
"INTRA32X32_LUMA",
"INTER32X32_LUMA",
},
};
static const char matrix_type_dc[2][6][22] =
{
{
"INTRA16X16_LUMA_DC",
"INTRA16X16_CHROMAU_DC",
"INTRA16X16_CHROMAV_DC",
"INTER16X16_LUMA_DC",
"INTER16X16_CHROMAU_DC",
"INTER16X16_CHROMAV_DC"
},
{
"INTRA32X32_LUMA_DC",
"INTER32X32_LUMA_DC",
},
};
uint32_t size_id;
for (size_id = 0; size_id < SCALING_LIST_SIZE_NUM; size_id++) {
uint32_t list_id;
uint32_t size = MIN(MAX_MATRIX_COEF_NUM, (int32_t)g_scaling_list_size[size_id]);
//const uint32_t * const scan = (size_id == 0) ? g_sig_last_scan[SCAN_DIAG][1] : g_sig_last_scan_32x32;
for (list_id = 0; list_id < g_scaling_list_num[size_id]; list_id++) {
int found;
uint32_t i;
int32_t data;
int32_t *coeff = encoder->scaling_list.scaling_list_coeff[size_id][list_id];
char line[LINE_BUFSIZE + 1] = { 0 }; // +1 for null-terminator
// Go back for each matrix.
fseek(fp, 0, SEEK_SET);
do {
if (!fgets(line, LINE_BUFSIZE, fp) ||
((found = !!strstr(line, matrix_type[size_id][list_id])) == 0 && feof(fp)))
return 0;
} while (!found);
for (i = 0; i < size;) {
char *p;
if (!fgets(line, LINE_BUFSIZE, fp))
return 0;
p = line;
// Read coefficients per line.
// The comma (,) character is used as a separator.
// The coefficients are stored in up-right diagonal order.
do {
int ret = sscanf(p, "%d", &data);
if (ret != 1)
break;
else if (data < 1 || data > 255)
return 0;
coeff[i++] = data;
if (i == size)
break;
// Seek to the next newline, null-terminator or comma.
while (*p != '\n' && *p != '\0' && *p != ',')
++p;
if (*p == ',')
++p;
} while (*p != '\n' && *p != '\0');
}
// Set DC value.
if (size_id >= SCALING_LIST_16x16) {
fseek(fp, 0, SEEK_SET);
do {
if (!fgets(line, LINE_BUFSIZE, fp) ||
((found = !!strstr(line, matrix_type_dc[size_id - SCALING_LIST_16x16][list_id])) == 0 && feof(fp)))
return 0;
} while (!found);
if (1 != fscanf(fp, "%d", &data) || data < 1 || data > 255)
return 0;
encoder->scaling_list.scaling_list_dc[size_id][list_id] = data;
} else
encoder->scaling_list.scaling_list_dc[size_id][list_id] = coeff[0];
}
}
encoder->scaling_list_enable = 1;
return 1;
#undef LINE_BUFSIZE
}

View file

@ -30,9 +30,6 @@
#include <math.h>
extern const uint8_t g_scaling_list_num[4];
extern const uint16_t g_scaling_list_size[4];
extern const int32_t g_quant_intra_default_8x8[64];
extern const uint8_t g_chroma_scale[58];
extern const int16_t g_inv_quant_scales[6];
@ -47,17 +44,6 @@ void itransformskip(int16_t *block,int16_t *coeff, int8_t block_size);
void transform2d(int16_t *block,int16_t *coeff, int8_t block_size, int32_t mode);
void itransform2d(int16_t *block,int16_t *coeff, int8_t block_size, int32_t mode);
void scalinglist_init(encoder_control*const encoder);
void scalinglist_process_enc(const int32_t * const coeff, int32_t *quant_coeff, int32_t quant_scales,
uint32_t height,uint32_t width, uint32_t ratio, int32_t size_num, uint32_t dc, uint8_t flat);
void scalinglist_process(const encoder_control * const encoder);
void scalinglist_set(const encoder_control * const encoder, const int32_t * const coeff, uint32_t listId, uint32_t sizeId, uint32_t qp);
void scalinglist_set_err_scale(const encoder_control * const encoder, uint32_t list, uint32_t size, uint32_t qp);
void scalinglist_destroy(encoder_control * const encoder);
int32_t *scalinglist_get_default(uint32_t size_id, uint32_t list_id);
int scalinglist_parse(encoder_control * const encoder, FILE *fp);
int32_t get_scaled_qp(int8_t type, int8_t qp, int8_t qp_offset);
#endif