From 9bfd542b73133de935eeceee54b595c917d25791 Mon Sep 17 00:00:00 2001 From: Marko Viitanen Date: Mon, 11 Jun 2012 18:43:29 +0300 Subject: [PATCH] Started digging into the intra prediction stuff --- build/VS2010/HEVC_encoder.vcxproj | 4 + build/VS2010/HEVC_encoder.vcxproj.filters | 12 + src/encoder.c | 164 +++++++----- src/encoder.h | 34 ++- src/intra.c | 13 + src/intra.h | 17 ++ src/nal.c | 17 +- src/picture.h | 7 +- src/transform.c | 291 ++++++++++++++++++++++ src/transform.h | 17 ++ 10 files changed, 505 insertions(+), 71 deletions(-) create mode 100644 src/intra.c create mode 100644 src/intra.h create mode 100644 src/transform.c create mode 100644 src/transform.h diff --git a/build/VS2010/HEVC_encoder.vcxproj b/build/VS2010/HEVC_encoder.vcxproj index 5f88b961..bfc173f0 100644 --- a/build/VS2010/HEVC_encoder.vcxproj +++ b/build/VS2010/HEVC_encoder.vcxproj @@ -84,8 +84,10 @@ + + @@ -93,8 +95,10 @@ + + diff --git a/build/VS2010/HEVC_encoder.vcxproj.filters b/build/VS2010/HEVC_encoder.vcxproj.filters index dae96b0e..bc5fb769 100644 --- a/build/VS2010/HEVC_encoder.vcxproj.filters +++ b/build/VS2010/HEVC_encoder.vcxproj.filters @@ -36,6 +36,12 @@ Source Files + + Source Files + + + Source Files + @@ -59,5 +65,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/src/encoder.c b/src/encoder.c index ff028b27..edbd46f4 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -52,6 +52,11 @@ void init_encoder_input(encoder_input* input,FILE* inputfile, uint32_t width, ui input->cur_pic.uData = (uint8_t *)malloc((width*height)>>2); input->cur_pic.vData = (uint8_t *)malloc((width*height)>>2); + /* Reconstruction buffers */ + input->cur_pic.yRecData = (uint8_t *)malloc(width*height); + input->cur_pic.uRecData = (uint8_t *)malloc((width*height)>>2); + input->cur_pic.vRecData = (uint8_t *)malloc((width*height)>>2); + /* Allocate memory for CU info 2D array */ //ToDo: we don't need this much space on LCU...MAX_DEPTH-1 input->cur_pic.CU = (CU_info**)malloc((MAX_DEPTH+1)*sizeof(CU_info*)); @@ -68,12 +73,14 @@ void encode_one_frame(encoder_control* encoder) /* output parameters before first frame */ if(encoder->frame == 0) { + /* Sequence Parameter Set (SPS) */ encode_seq_parameter_set(encoder); bitstream_align(encoder->stream); bitstream_flush(encoder->stream); nal_write(encoder->output, encoder->stream->buffer, encoder->stream->buffer_pos, 1, NAL_SEQ_PARAMETER_SET, 1); bitstream_clear_buffer(encoder->stream); + /* Picture Parameter Set (PPS) */ encode_pic_parameter_set(encoder); bitstream_align(encoder->stream); bitstream_flush(encoder->stream); @@ -94,6 +101,7 @@ void encode_one_frame(encoder_control* encoder) } else if(encoder->frame < 3) { + /* Non-IDR slice */ cabac_start(&cabac); encoder->in.cur_pic.type = NAL_NONIDR_SLICE; encode_slice_header(encoder); @@ -143,6 +151,7 @@ void encode_seq_parameter_set(encoder_control* encoder) #ifdef _DEBUG printf("=========== Sequence Parameter Set ID: 0 ===========\n"); #endif + /* ToDo: profile IDC and level IDC should be defined later on */ WRITE_U(encoder->stream, 0, 8, "profile_idc"); WRITE_U(encoder->stream, 0, 8, "reserved_zero_8bits"); WRITE_U(encoder->stream, 0, 8, "level_idc"); @@ -152,12 +161,13 @@ void encode_seq_parameter_set(encoder_control* encoder) WRITE_UE(encoder->stream, encoder->in.width, "pic_width_in_luma_samples"); WRITE_UE(encoder->stream, encoder->in.height, "pic_height_in_luma_samples"); WRITE_U(encoder->stream, 0, 1, "pic_cropping_flag"); + /* ToDo: 10bit support? */ WRITE_UE(encoder->stream, 0, "bit_depth_luma_minus8"); WRITE_UE(encoder->stream, 0, "bit_depth_chroma_minus8"); WRITE_U(encoder->stream, ENABLE_PCM, 1, "pcm_enabled_flag"); #if ENABLE_PCM == 1 - WRITE_U(encoder->stream, 7, 4, "pcm_bit_depth_luma_minus1"); - WRITE_U(encoder->stream, 7, 4, "pcm_bit_depth_chroma_minus1"); + WRITE_U(encoder->stream, 7, 4, "pcm_bit_depth_luma_minus1"); + WRITE_U(encoder->stream, 7, 4, "pcm_bit_depth_chroma_minus1"); #endif WRITE_U(encoder->stream, 0, 1, "qpprime_y_zero_transquant_bypass_flag"); WRITE_UE(encoder->stream, 4, "log2_max_pic_order_cnt_lsb_minus4"); @@ -166,7 +176,7 @@ void encode_seq_parameter_set(encoder_control* encoder) WRITE_UE(encoder->stream, 0, "max_latency_increase"); WRITE_U(encoder->stream, 0, 1, "restricted_ref_pic_lists_flag"); WRITE_UE(encoder->stream, 1, "log2_min_coding_block_size_minus3"); - WRITE_UE(encoder->stream, 2, "log2_diff_max_min_coding_block_size"); + WRITE_UE(encoder->stream, MAX_DEPTH, "log2_diff_max_min_coding_block_size"); WRITE_UE(encoder->stream, 0, "log2_min_transform_block_size_minus2"); WRITE_UE(encoder->stream, 3, "log2_diff_max_min_transform_block_size"); @@ -198,8 +208,7 @@ void encode_seq_parameter_set(encoder_control* encoder) WRITE_UE(encoder->stream, 0, "num_short_term_ref_pic_sets"); WRITE_U(encoder->stream, 0, 1, "long_term_ref_pics_present_flag"); WRITE_U(encoder->stream, 0, 2, "tiles_or_entropy_coding_sync_idc"); - WRITE_U(encoder->stream, 0, 1, "sps_extension_flag"); - //WRITE_U(encoder->stream, 0, 8, "stuffing"); + WRITE_U(encoder->stream, 0, 1, "sps_extension_flag"); } void encode_slice_header(encoder_control* encoder) @@ -228,34 +237,53 @@ void encode_slice_header(encoder_control* encoder) WRITE_U(encoder->stream, encoder->frame, 8, "pic_order_cnt_lsb"); WRITE_U(encoder->stream, 1, 1, "short_term_ref_pic_set_sps_flag"); WRITE_UE(encoder->stream, 0, "short_term_ref_pic_set_idx"); - } //end if //end if - /* - Skip unpresent flags */ + /* Skip flags that are not present */ // if !entropy_slice_flag WRITE_UE(encoder->stream, 0, "slice_qp_delta"); WRITE_UE(encoder->stream, 0, "5_minus_max_num_merge_cand"); } +/* CONTEXTS */ +/* ToDo: move somewhere else */ cabac_ctx *SplitFlagSCModel; -cabac_ctx g_SplitFlagSCModel[3]; -cabac_ctx PCMFlagSCModel; +cabac_ctx g_SplitFlagSCModel[3]; /*QP, INIT_SPLIT_FLAG[SLICE_I][0]); cxt_init(&g_SplitFlagSCModel[1], encoder->QP, INIT_SPLIT_FLAG[SLICE_I][1]); cxt_init(&g_SplitFlagSCModel[2], encoder->QP, INIT_SPLIT_FLAG[SLICE_I][2]); - cxt_init(&PartSizeSCModel, encoder->QP, 154); - //g_SplitFlagSCModel[1].ucState = 47; - //g_SplitFlagSCModel[2].ucState = 36; + cxt_init(&g_IntraModeSCModel, encoder->QP, INIT_INTRA_PRED_MODE[SLICE_I]); + cxt_init(&g_ChromaPredSCModel[0], encoder->QP, INIT_CHROMA_PRED_MODE[SLICE_I][0]); + cxt_init(&g_ChromaPredSCModel[1], encoder->QP, INIT_CHROMA_PRED_MODE[SLICE_I][1]); + + + for(i = 0; i < 4; i++) + { + cxt_init(&g_TransSubdivSCModel[i], encoder->QP, INIT_TRANS_SUBDIV_FLAG[SLICE_I][i]); + } + for(i = 0; i < 8; i++) + { + cxt_init(&g_QtCbfSCModel[i], encoder->QP, INIT_QT_CBF[SLICE_I][i]); + } + + encoder->in.cur_pic.CU[1][0].type = CU_INTRA; + encoder->in.cur_pic.CU[1][2].type = CU_INTRA; + + /* Loop through every LCU in the slice */ for(yCtb = 0; yCtb < encoder->in.height_in_LCU; yCtb++) { uint8_t lastCUy = (yCtb == (encoder->in.height_in_LCU-1))?1:0; @@ -263,17 +291,15 @@ void encode_slice_data(encoder_control* encoder) { uint8_t lastCUx = (xCtb == (encoder->in.width_in_LCU-1))?1:0; uint8_t depth = 0; - - encode_coding_tree(encoder, xCtb<<2,yCtb<<2, depth); - //Terminating bit + + /* Recursive function for looping through all the sub-blocks */ + encode_coding_tree(encoder, xCtb< 0 && GET_SPLITDATA(&(encoder->in.cur_pic.CU[depth][(xCtb>>(MAX_DEPTH-depth))-1+(yCtb>>(MAX_DEPTH-depth))*(encoder->in.width_in_LCU<in.cur_pic.yData[xCtb*16 + (yCtb*16)*encoder->in.width]; - uint8_t *baseCb = &encoder->in.cur_pic.uData[(xCtb*8 + (yCtb*8)*encoder->in.width/2)]; - uint8_t *baseCr = &encoder->in.cur_pic.vData[(xCtb*8 + (yCtb*8)*encoder->in.width/2)]; - for(y = 0; y < 32; y++) + /* Code IPCM block */ + if(encoder->in.cur_pic.CU[depth][(xCtb>>(MAX_DEPTH-depth))+(yCtb>>(MAX_DEPTH-depth))*(encoder->in.width_in_LCU<in.width], 8); - } - } - //Cb - for(y = 0; y < 16; y++) - { - for(x = 0; x < 16; x++) + uint8_t *base = &encoder->in.cur_pic.yData[xCtb*(LCU_WIDTH>>(depth+1)) + (yCtb*(LCU_WIDTH>>(depth+1)))*encoder->in.width]; + uint8_t *baseCb = &encoder->in.cur_pic.uData[(xCtb*(LCU_WIDTH>>(depth+2)) + (yCtb*(LCU_WIDTH>>(depth+2)))*encoder->in.width/2)]; + uint8_t *baseCr = &encoder->in.cur_pic.vData[(xCtb*(LCU_WIDTH>>(depth+2)) + (yCtb*(LCU_WIDTH>>(depth+2)))*encoder->in.width/2)]; + for(y = 0; y < LCU_WIDTH>>depth; y++) { - bitstream_put(cabac.stream, baseCb[x+y*(encoder->in.width>>1)], 8); + for(x = 0; x < LCU_WIDTH>>depth; x++) + { + bitstream_put(cabac.stream, base[x+y*encoder->in.width], 8); + } + } + //Cb + for(y = 0; y < LCU_WIDTH>>(depth+1); y++) + { + for(x = 0; x < LCU_WIDTH>>(depth+1); x++) + { + bitstream_put(cabac.stream, baseCb[x+y*(encoder->in.width>>1)], 8); + } } - } - //Cr - for(y = 0; y < 16; y++) - { - for(x = 0; x < 16; x++) + //Cr + for(y = 0; y < LCU_WIDTH>>(depth+1); y++) { - bitstream_put(cabac.stream, baseCr[x+y*(encoder->in.width>>1)], 8); + for(x = 0; x < LCU_WIDTH>>(depth+1); x++) + { + bitstream_put(cabac.stream, baseCr[x+y*(encoder->in.width>>1)], 8); + } } } - } - /* end PCM sample */ - cabac_start(&cabac); - //endif - - /* end prediction unit */ + /* end PCM sample */ + cabac_start(&cabac); + + } /* end Code IPCM block */ + else + { + cabac_encodeBinTrm(&cabac, 0); /* IPCMFlag == 0 */ + + cabac.ctx = &g_IntraModeSCModel; + CABAC_BIN(&cabac,0,"IntraPred"); + + cabac.ctx = &g_ChromaPredSCModel[0]; + CABAC_BIN(&cabac,0,"IntraPredChroma"); + + cabac.ctx = &g_TransSubdivSCModel[1]; /* //uiLog2TransformBlockSize */ + CABAC_BIN(&cabac,0,"TransformSubdivFlag"); + + /* Transform tree */ + + /* end Transform tree */ + + } + //endif + /* end prediction unit */ + //cabac_encodeBin(&cabac, 0); //prev_intra_luma_pred_flag //cabac_encodeBin(&cabac, 1); //rem_intra_luma_pred_mode diff --git a/src/encoder.h b/src/encoder.h index 1173e5a3..341b3545 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -10,8 +10,8 @@ Structures for encoding */ -#ifndef _ENCODER_H -#define _ENCODER_H +#ifndef __ENCODER_H +#define __ENCODER_H #include "picture.h" #include "bitstream.h" @@ -62,12 +62,28 @@ void encode_slice_header(encoder_control* encoder); void encode_coding_tree(encoder_control* encoder,uint16_t xCtb,uint16_t yCtb, uint8_t depth); -static const uint8_t - INIT_SPLIT_FLAG[3][3] = - { - { 107, 139, 126, }, - { 107, 139, 126, }, - { 139, 141, 157, } - }; +static const uint8_t INIT_SPLIT_FLAG[3][3] = + { { 107, 139, 126 }, { 107, 139, 126 }, { 139, 141, 157 } }; + +static const uint8_t INIT_INTRA_PRED_MODE[3] = { 183,154,184 }; + +static const uint8_t INIT_CHROMA_PRED_MODE[3][2] = { { 152, 139 }, { 152, 139 }, { 63, 139 } }; + +#define CNU 154 +static const uint8_t INIT_TRANS_SUBDIV_FLAG[3][4] = +{ + { CNU, 153, 138, 138 }, + { CNU, 124, 138, 94 }, + { CNU, 224, 167, 122 } +}; + +static const uint8_t INIT_QT_CBF[3][8] = +{ + { 153, 111, CNU, CNU, CNU, 149, 92, 167 }, + { 153, 111, CNU, CNU, CNU, 149, 107, 167 }, + { 111, 141, CNU, CNU, CNU, 94, 138, 182 } +}; + + #endif \ No newline at end of file diff --git a/src/intra.c b/src/intra.c new file mode 100644 index 00000000..a9a5eb72 --- /dev/null +++ b/src/intra.c @@ -0,0 +1,13 @@ +/** + * HEVC Encoder + * - Marko Viitanen ( fador at iki.fi ), Tampere University of Technology, Department of Computer Systems. + */ + +/*! \file intra.c + \brief Intra functions + \author Marko Viitanen + \date 2012-06 + + Intra functions +*/ + diff --git a/src/intra.h b/src/intra.h new file mode 100644 index 00000000..1dc26fbf --- /dev/null +++ b/src/intra.h @@ -0,0 +1,17 @@ +/** + * HEVC Encoder + * - Marko Viitanen ( fador at iki.fi ), Tampere University of Technology, Department of Computer Systems. + */ + +/*! \file intra.h + \brief Intra functions + \author Marko Viitanen + \date 2012-06 + + Intra functions +*/ +#ifndef __INTRA_H +#define __INTRA_H + + +#endif diff --git a/src/nal.c b/src/nal.c index 287cf79b..59354a73 100644 --- a/src/nal.c +++ b/src/nal.c @@ -30,21 +30,22 @@ void nal_write(FILE* output, uint8_t* buffer, uint32_t buffer_len, uint8_t nal_r uint8_t byte; uint32_t i; uint8_t zerocount=0; + + /* Some useful constants */ const uint8_t emulation_prevention_three_byte = 0x03; const uint8_t start_code_prefix_one_3bytes = 0x01; const uint8_t zero = 0x00; - //start_code_prefix_one_3bytes - //fwrite(&zero, 1, 1, output); + /*start_code_prefix_one_3bytes */ fwrite(&zero, 1, 1, output); fwrite(&zero, 1, 1, output); fwrite(&start_code_prefix_one_3bytes, 1, 1, output); - //forbidden_zero_flag(1) + nal_ref_flag(1) + nal_unit_type(6) + /* forbidden_zero_flag(1) + nal_ref_flag(1) + nal_unit_type(6) */ byte = nal_ref<<6 | nal_type; fwrite(&byte, 1, 1, output); - //Temporal_id(3) + reserved_one_5bits(5) + /* Temporal_id(3) + reserved_one_5bits(5) */ byte = temporal_id << 5 | 1; fwrite(&byte, 1, 1, output); @@ -58,16 +59,22 @@ void nal_write(FILE* output, uint8_t* buffer, uint32_t buffer_len, uint8_t nal_r zerocount = 0; } if(buffer[i] == 0) + { zerocount++; + } else + { zerocount = 0; + } /* Write the actual data */ fwrite(&buffer[i], 1, 1, output); } - //If last byte was 0, add emulation_prevention_three_byte + /* If last byte was 0, add emulation_prevention_three_byte */ if(buffer[buffer_len-1] == 0) + { fwrite(&emulation_prevention_three_byte, 1, 1, output); + } } \ No newline at end of file diff --git a/src/picture.h b/src/picture.h index 995a6b6f..4f74199b 100644 --- a/src/picture.h +++ b/src/picture.h @@ -20,7 +20,7 @@ * @{ */ -enum { CU_NOTSET = 0, CU_SKIP, CU_SPLIT, CU_INTRA, CU_INTER}; +enum { CU_NOTSET = 0,CU_PCM, CU_SKIP, CU_SPLIT, CU_INTRA, CU_INTER }; #define GET_SPLITDATA(CU) ((CU)->split) #define SET_SPLITDATA(CU,flag) { (CU)->split=(flag); } @@ -53,6 +53,11 @@ typedef struct uint8_t* yData; /*!< \brief Pointer to Y-data */ uint8_t* uData; /*!< \brief Pointer to U-data */ uint8_t* vData; /*!< \brief Pointer to V-data */ + + uint8_t* yRecData; /*!< \brief Pointer to reconstructed Y-data */ + uint8_t* uRecData; /*!< \brief Pointer to reconstructed U-data */ + uint8_t* vRecData; /*!< \brief Pointer to reconstructed V-data */ + int width; /*!< \brief Picture width */ int height; /*!< \brief Picture height */ uint8_t referenced; /*!< \brief Is this picture referenced */ diff --git a/src/transform.c b/src/transform.c new file mode 100644 index 00000000..31cc89c9 --- /dev/null +++ b/src/transform.c @@ -0,0 +1,291 @@ +/** + * HEVC Encoder + * - Marko Viitanen ( fador at iki.fi ), Tampere University of Technology, Department of Computer Systems. + */ + +/*! \file transform.c + \brief Transform functions + \author Marko Viitanen + \date 2012-06 + + Transform functions +*/ +#include +#include +#include +#include "global.h" + + +const int16_t g_aiT4[4][4] = +{ + { 64, 64, 64, 64}, + { 83, 36,-36,-83}, + { 64,-64,-64, 64}, + { 36,-83, 83,-36} +}; + +const int16_t g_aiT8[8][8] = +{ + { 64, 64, 64, 64, 64, 64, 64, 64}, + { 89, 75, 50, 18,-18,-50,-75,-89}, + { 83, 36,-36,-83,-83,-36, 36, 83}, + { 75,-18,-89,-50, 50, 89, 18,-75}, + { 64,-64,-64, 64, 64,-64,-64, 64}, + { 50,-89, 18, 75,-75,-18, 89,-50}, + { 36,-83, 83,-36,-36, 83,-83, 36}, + { 18,-50, 75,-89, 89,-75, 50,-18} +}; + +const int16_t g_aiT16[16][16] = +{ + { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + { 90, 87, 80, 70, 57, 43, 25, 9, -9,-25,-43,-57,-70,-80,-87,-90}, + { 89, 75, 50, 18,-18,-50,-75,-89,-89,-75,-50,-18, 18, 50, 75, 89}, + { 87, 57, 9,-43,-80,-90,-70,-25, 25, 70, 90, 80, 43, -9,-57,-87}, + { 83, 36,-36,-83,-83,-36, 36, 83, 83, 36,-36,-83,-83,-36, 36, 83}, + { 80, 9,-70,-87,-25, 57, 90, 43,-43,-90,-57, 25, 87, 70, -9,-80}, + { 75,-18,-89,-50, 50, 89, 18,-75,-75, 18, 89, 50,-50,-89,-18, 75}, + { 70,-43,-87, 9, 90, 25,-80,-57, 57, 80,-25,-90, -9, 87, 43,-70}, + { 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64}, + { 57,-80,-25, 90, -9,-87, 43, 70,-70,-43, 87, 9,-90, 25, 80,-57}, + { 50,-89, 18, 75,-75,-18, 89,-50,-50, 89,-18,-75, 75, 18,-89, 50}, + { 43,-90, 57, 25,-87, 70, 9,-80, 80, -9,-70, 87,-25,-57, 90,-43}, + { 36,-83, 83,-36,-36, 83,-83, 36, 36,-83, 83,-36,-36, 83,-83, 36}, + { 25,-70, 90,-80, 43, 9,-57, 87,-87, 57, -9,-43, 80,-90, 70,-25}, + { 18,-50, 75,-89, 89,-75, 50,-18,-18, 50,-75, 89,-89, 75,-50, 18}, + { 9,-25, 43,-57, 70,-80, 87,-90, 90,-87, 80,-70, 57,-43, 25, -9} +}; + +const int16_t g_aiT32[32][32] = +{ + { 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + { 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4, -4,-13,-22,-31,-38,-46,-54,-61,-67,-73,-78,-82,-85,-88,-90,-90}, + { 90, 87, 80, 70, 57, 43, 25, 9, -9,-25,-43,-57,-70,-80,-87,-90,-90,-87,-80,-70,-57,-43,-25, -9, 9, 25, 43, 57, 70, 80, 87, 90}, + { 90, 82, 67, 46, 22, -4,-31,-54,-73,-85,-90,-88,-78,-61,-38,-13, 13, 38, 61, 78, 88, 90, 85, 73, 54, 31, 4,-22,-46,-67,-82,-90}, + { 89, 75, 50, 18,-18,-50,-75,-89,-89,-75,-50,-18, 18, 50, 75, 89, 89, 75, 50, 18,-18,-50,-75,-89,-89,-75,-50,-18, 18, 50, 75, 89}, + { 88, 67, 31,-13,-54,-82,-90,-78,-46, -4, 38, 73, 90, 85, 61, 22,-22,-61,-85,-90,-73,-38, 4, 46, 78, 90, 82, 54, 13,-31,-67,-88}, + { 87, 57, 9,-43,-80,-90,-70,-25, 25, 70, 90, 80, 43, -9,-57,-87,-87,-57, -9, 43, 80, 90, 70, 25,-25,-70,-90,-80,-43, 9, 57, 87}, + { 85, 46,-13,-67,-90,-73,-22, 38, 82, 88, 54, -4,-61,-90,-78,-31, 31, 78, 90, 61, 4,-54,-88,-82,-38, 22, 73, 90, 67, 13,-46,-85}, + { 83, 36,-36,-83,-83,-36, 36, 83, 83, 36,-36,-83,-83,-36, 36, 83, 83, 36,-36,-83,-83,-36, 36, 83, 83, 36,-36,-83,-83,-36, 36, 83}, + { 82, 22,-54,-90,-61, 13, 78, 85, 31,-46,-90,-67, 4, 73, 88, 38,-38,-88,-73, -4, 67, 90, 46,-31,-85,-78,-13, 61, 90, 54,-22,-82}, + { 80, 9,-70,-87,-25, 57, 90, 43,-43,-90,-57, 25, 87, 70, -9,-80,-80, -9, 70, 87, 25,-57,-90,-43, 43, 90, 57,-25,-87,-70, 9, 80}, + { 78, -4,-82,-73, 13, 85, 67,-22,-88,-61, 31, 90, 54,-38,-90,-46, 46, 90, 38,-54,-90,-31, 61, 88, 22,-67,-85,-13, 73, 82, 4,-78}, + { 75,-18,-89,-50, 50, 89, 18,-75,-75, 18, 89, 50,-50,-89,-18, 75, 75,-18,-89,-50, 50, 89, 18,-75,-75, 18, 89, 50,-50,-89,-18, 75}, + { 73,-31,-90,-22, 78, 67,-38,-90,-13, 82, 61,-46,-88, -4, 85, 54,-54,-85, 4, 88, 46,-61,-82, 13, 90, 38,-67,-78, 22, 90, 31,-73}, + { 70,-43,-87, 9, 90, 25,-80,-57, 57, 80,-25,-90, -9, 87, 43,-70,-70, 43, 87, -9,-90,-25, 80, 57,-57,-80, 25, 90, 9,-87,-43, 70}, + { 67,-54,-78, 38, 85,-22,-90, 4, 90, 13,-88,-31, 82, 46,-73,-61, 61, 73,-46,-82, 31, 88,-13,-90, -4, 90, 22,-85,-38, 78, 54,-67}, + { 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64, 64,-64,-64, 64}, + { 61,-73,-46, 82, 31,-88,-13, 90, -4,-90, 22, 85,-38,-78, 54, 67,-67,-54, 78, 38,-85,-22, 90, 4,-90, 13, 88,-31,-82, 46, 73,-61}, + { 57,-80,-25, 90, -9,-87, 43, 70,-70,-43, 87, 9,-90, 25, 80,-57,-57, 80, 25,-90, 9, 87,-43,-70, 70, 43,-87, -9, 90,-25,-80, 57}, + { 54,-85, -4, 88,-46,-61, 82, 13,-90, 38, 67,-78,-22, 90,-31,-73, 73, 31,-90, 22, 78,-67,-38, 90,-13,-82, 61, 46,-88, 4, 85,-54}, + { 50,-89, 18, 75,-75,-18, 89,-50,-50, 89,-18,-75, 75, 18,-89, 50, 50,-89, 18, 75,-75,-18, 89,-50,-50, 89,-18,-75, 75, 18,-89, 50}, + { 46,-90, 38, 54,-90, 31, 61,-88, 22, 67,-85, 13, 73,-82, 4, 78,-78, -4, 82,-73,-13, 85,-67,-22, 88,-61,-31, 90,-54,-38, 90,-46}, + { 43,-90, 57, 25,-87, 70, 9,-80, 80, -9,-70, 87,-25,-57, 90,-43,-43, 90,-57,-25, 87,-70, -9, 80,-80, 9, 70,-87, 25, 57,-90, 43}, + { 38,-88, 73, -4,-67, 90,-46,-31, 85,-78, 13, 61,-90, 54, 22,-82, 82,-22,-54, 90,-61,-13, 78,-85, 31, 46,-90, 67, 4,-73, 88,-38}, + { 36,-83, 83,-36,-36, 83,-83, 36, 36,-83, 83,-36,-36, 83,-83, 36, 36,-83, 83,-36,-36, 83,-83, 36, 36,-83, 83,-36,-36, 83,-83, 36}, + { 31,-78, 90,-61, 4, 54,-88, 82,-38,-22, 73,-90, 67,-13,-46, 85,-85, 46, 13,-67, 90,-73, 22, 38,-82, 88,-54, -4, 61,-90, 78,-31}, + { 25,-70, 90,-80, 43, 9,-57, 87,-87, 57, -9,-43, 80,-90, 70,-25,-25, 70,-90, 80,-43, -9, 57,-87, 87,-57, 9, 43,-80, 90,-70, 25}, + { 22,-61, 85,-90, 73,-38, -4, 46,-78, 90,-82, 54,-13,-31, 67,-88, 88,-67, 31, 13,-54, 82,-90, 78,-46, 4, 38,-73, 90,-85, 61,-22}, + { 18,-50, 75,-89, 89,-75, 50,-18,-18, 50,-75, 89,-89, 75,-50, 18, 18,-50, 75,-89, 89,-75, 50,-18,-18, 50,-75, 89,-89, 75,-50, 18}, + { 13,-38, 61,-78, 88,-90, 85,-73, 54,-31, 4, 22,-46, 67,-82, 90,-90, 82,-67, 46,-22, -4, 31,-54, 73,-85, 90,-88, 78,-61, 38,-13}, + { 9,-25, 43,-57, 70,-80, 87,-90, 90,-87, 80,-70, 57,-43, 25, -9, -9, 25,-43, 57,-70, 80,-87, 90,-90, 87,-80, 70,-57, 43,-25, 9}, + { 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} +}; + + +void partialButterfly4(short *src,short *dst,int shift, int line) +{ + int j; + int E[2],O[2]; + int add = 1<<(shift-1); + + for (j=0; j>shift; + dst[2*line] = (g_aiT4[2][0]*E[0] + g_aiT4[2][1]*E[1] + add)>>shift; + dst[line] = (g_aiT4[1][0]*O[0] + g_aiT4[1][1]*O[1] + add)>>shift; + dst[3*line] = (g_aiT4[3][0]*O[0] + g_aiT4[3][1]*O[1] + add)>>shift; + + src += 4; + dst ++; + } +} + +// Fast DST Algorithm. Full matrix multiplication for DST and Fast DST algorithm +// give identical results +void fastForwardDst(short *block,short *coeff,int shift) // input block, output coeff +{ + int i, c[4]; + int rnd_factor = 1<<(shift-1); + for (i=0; i<4; i++) + { + // Intermediate Variables + c[0] = block[4*i+0] + block[4*i+3]; + c[1] = block[4*i+1] + block[4*i+3]; + c[2] = block[4*i+0] - block[4*i+1]; + c[3] = 74* block[4*i+2]; + + coeff[ i] = ( 29 * c[0] + 55 * c[1] + c[3] + rnd_factor ) >> shift; + coeff[ 4+i] = ( 74 * (block[4*i+0]+ block[4*i+1] - block[4*i+3]) + rnd_factor ) >> shift; + coeff[ 8+i] = ( 29 * c[2] + 55 * c[0] - c[3] + rnd_factor ) >> shift; + coeff[12+i] = ( 55 * c[2] - 29 * c[1] + c[3] + rnd_factor ) >> shift; + } +} + + + +void partialButterfly8(short *src,short *dst,int shift, int line) +{ + int j,k; + int E[4],O[4]; + int EE[2],EO[2]; + int add = 1<<(shift-1); + + for (j=0; j>shift; + dst[4*line] = (g_aiT8[4][0]*EE[0] + g_aiT8[4][1]*EE[1] + add)>>shift; + dst[2*line] = (g_aiT8[2][0]*EO[0] + g_aiT8[2][1]*EO[1] + add)>>shift; + dst[6*line] = (g_aiT8[6][0]*EO[0] + g_aiT8[6][1]*EO[1] + add)>>shift; + + dst[line] = (g_aiT8[1][0]*O[0] + g_aiT8[1][1]*O[1] + g_aiT8[1][2]*O[2] + g_aiT8[1][3]*O[3] + add)>>shift; + dst[3*line] = (g_aiT8[3][0]*O[0] + g_aiT8[3][1]*O[1] + g_aiT8[3][2]*O[2] + g_aiT8[3][3]*O[3] + add)>>shift; + dst[5*line] = (g_aiT8[5][0]*O[0] + g_aiT8[5][1]*O[1] + g_aiT8[5][2]*O[2] + g_aiT8[5][3]*O[3] + add)>>shift; + dst[7*line] = (g_aiT8[7][0]*O[0] + g_aiT8[7][1]*O[1] + g_aiT8[7][2]*O[2] + g_aiT8[7][3]*O[3] + add)>>shift; + + src += 8; + dst ++; + } +} + + + +void partialButterfly16(short *src,short *dst,int shift, int line) +{ + int j,k; + int E[8],O[8]; + int EE[4],EO[4]; + int EEE[2],EEO[2]; + int add = 1<<(shift-1); + + for (j=0; j>shift; + dst[ 8*line ] = (g_aiT16[ 8][0]*EEE[0] + g_aiT16[ 8][1]*EEE[1] + add)>>shift; + dst[ 4*line ] = (g_aiT16[ 4][0]*EEO[0] + g_aiT16[ 4][1]*EEO[1] + add)>>shift; + dst[ 12*line] = (g_aiT16[12][0]*EEO[0] + g_aiT16[12][1]*EEO[1] + add)>>shift; + + for (k=2;k<16;k+=4) + { + dst[ k*line ] = (g_aiT16[k][0]*EO[0] + g_aiT16[k][1]*EO[1] + g_aiT16[k][2]*EO[2] + g_aiT16[k][3]*EO[3] + add)>>shift; + } + + for (k=1;k<16;k+=2) + { + dst[ k*line ] = (g_aiT16[k][0]*O[0] + g_aiT16[k][1]*O[1] + g_aiT16[k][2]*O[2] + g_aiT16[k][3]*O[3] + + g_aiT16[k][4]*O[4] + g_aiT16[k][5]*O[5] + g_aiT16[k][6]*O[6] + g_aiT16[k][7]*O[7] + add)>>shift; + } + + src += 16; + dst ++; + + } +} + + + +void partialButterfly32(short *src,short *dst,int shift, int line) +{ + int j,k; + int E[16],O[16]; + int EE[8],EO[8]; + int EEE[4],EEO[4]; + int EEEE[2],EEEO[2]; + int add = 1<<(shift-1); + + for (j=0; j>shift; + dst[ 16*line ] = (g_aiT32[16][0]*EEEE[0] + g_aiT32[16][1]*EEEE[1] + add)>>shift; + dst[ 8*line ] = (g_aiT32[ 8][0]*EEEO[0] + g_aiT32[ 8][1]*EEEO[1] + add)>>shift; + dst[ 24*line ] = (g_aiT32[24][0]*EEEO[0] + g_aiT32[24][1]*EEEO[1] + add)>>shift; + for (k=4;k<32;k+=8) + { + dst[ k*line ] = (g_aiT32[k][0]*EEO[0] + g_aiT32[k][1]*EEO[1] + g_aiT32[k][2]*EEO[2] + g_aiT32[k][3]*EEO[3] + add)>>shift; + } + for (k=2;k<32;k+=4) + { + dst[ k*line ] = (g_aiT32[k][0]*EO[0] + g_aiT32[k][1]*EO[1] + g_aiT32[k][2]*EO[2] + g_aiT32[k][3]*EO[3] + + g_aiT32[k][4]*EO[4] + g_aiT32[k][5]*EO[5] + g_aiT32[k][6]*EO[6] + g_aiT32[k][7]*EO[7] + add)>>shift; + } + for (k=1;k<32;k+=2) + { + dst[ k*line ] = (g_aiT32[k][ 0]*O[ 0] + g_aiT32[k][ 1]*O[ 1] + g_aiT32[k][ 2]*O[ 2] + g_aiT32[k][ 3]*O[ 3] + + g_aiT32[k][ 4]*O[ 4] + g_aiT32[k][ 5]*O[ 5] + g_aiT32[k][ 6]*O[ 6] + g_aiT32[k][ 7]*O[ 7] + + g_aiT32[k][ 8]*O[ 8] + g_aiT32[k][ 9]*O[ 9] + g_aiT32[k][10]*O[10] + g_aiT32[k][11]*O[11] + + g_aiT32[k][12]*O[12] + g_aiT32[k][13]*O[13] + g_aiT32[k][14]*O[14] + g_aiT32[k][15]*O[15] + add)>>shift; + } + src += 32; + dst ++; + } +} diff --git a/src/transform.h b/src/transform.h new file mode 100644 index 00000000..7fb9197e --- /dev/null +++ b/src/transform.h @@ -0,0 +1,17 @@ +/** + * HEVC Encoder + * - Marko Viitanen ( fador at iki.fi ), Tampere University of Technology, Department of Computer Systems. + */ + +/*! \file transform.h + \brief Transform functions + \author Marko Viitanen + \date 2012-06 + + Transform functions +*/ +#ifndef __TRANSFORM_H +#define __TRANSFORM_H + + +#endif