Especificação



Baixar 2,81 Mb.
Página16/24
Encontro01.07.2018
Tamanho2,81 Mb.
1   ...   12   13   14   15   16   17   18   19   ...   24

A7 Classes para medição de distorção




      1. A7.1 Interface DistortionMetric



package br.ufsc.inf.guiga.media.codec.video.h264.vcl.mode.decision;
/**

* Error Metric measures the energy of the residual transform coefficients after

* quantization.

*

* @author Guilherme Ferreira



*/

public interface DistortionMetric {
/**

* Computes the distortion between two 16x16 blocks.

*

* @param orig the original block.



* @param pred the predicted block.

* @return an integer number representing the distortion between the two

* blocks. The number magnitude tends to be lower as the two blocks

* match closer.

*/

public int getDistortion16x16(int[][] orig, int[][] pred);
/**

* Computes the distortion between two 4x4 blocks.

*

* @param orig the original block.



* @param pred the predicted block.

* @param pos_y a vertical offset shall be provide if the blocks height is

* wider than 4 elements.

* @param pos_x a horizontal offset shall be provide if the blocks width is

* wider than 4 elements.

* @return an integer number representing the distortion between the two

* blocks. The number magnitude tends to be lower as the two blocks

* match closer.

*/

public int getDistortion4x4(int[][] orig, int[][] pred, int pos_y, int pos_x);
}

      1. A7.1 Classe SATD



package br.ufsc.inf.guiga.media.codec.video.h264.vcl.mode.decision;
import br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.Transform;
/**

* SA(T)D, the Sum of Absolute Differences of the Transformed residual data.

*

* @author Guilherme Ferreira



*/

public class SATD implements DistortionMetric {
private Transform transform;
public SATD(Transform transform) {

this.transform = transform;

}
public int getDistortion16x16(int[][] orig, int[][] pred) {



int satd = 0;

int ii, jj, i, j;

int[][][][] M0 = new int[4][4][4][4];

int[][] M4 = new int[4][4];

int[][] M7 = new int[4][4];
// calculate the difference (residual)

for (j = 0; j < 16; j++) {

for (i = 0; i < 16; i++) {

M0[j >> 2][i >> 2][j & 0x03][i & 0x03] = orig[j][i] - pred[j][i];

}

}
for (jj = 0; jj < 4; jj++) {



for (ii = 0; ii < 4; ii++) {

M7 = M0[jj][ii];

transform.hadamard4x4(M7, M7);

for (j = 0; j < 4; j++) {

for (i = 0; i < 4; i++) {

if ((i + j) != 0)

satd += Math.abs(M7[j][i]);

}

}

}



}
for (j = 0; j < 4; j++) {

for (i = 0; i < 4; i++)

M4[j][i] = (M0[j][i][0][0] >> 1);

}

// Hadamard of DC coeff



transform.hadamard4x4(M4, M4);
// sum SATD

for (j = 0; j < 4; j++) {

for (i = 0; i < 4; i++) {

satd += Math.abs(M4[j][i]);

}

}
return satd;



}
// Calculate 4x4 Hadamard-Transformed SAD

public int getDistortion4x4(int[][] orig, int[][] pred, int pos_y, int pos_x) {
int satd = 0;

int[][] diff = new int[4][4];

int[] d = new int[16];

int[] m = new int[16];
// calculate the difference (residual)

for (int j = 0; j < 4; j++) {

int jj = pos_y + j;

for (int i = 0; i < 4; i++) {

int ii = pos_x + i;

diff[j][i] = orig[jj][ii] - pred[jj][ii];

}

}
// TODO why the code bellow isn't equivalent to



// transform.hadamard4x4(diff, diff)?
// hadamard transform

m[0] = diff[0][0] + diff[3][0];

m[1] = diff[0][1] + diff[3][1];

m[2] = diff[0][2] + diff[3][2];

m[3] = diff[0][3] + diff[3][3];

m[4] = diff[1][0] + diff[2][0];

m[5] = diff[1][1] + diff[2][1];

m[6] = diff[1][2] + diff[2][2];

m[7] = diff[1][3] + diff[2][3];

m[8] = diff[1][0] - diff[2][0];

m[9] = diff[1][1] - diff[2][1];

m[10] = diff[1][2] - diff[2][2];

m[11] = diff[1][3] - diff[2][3];

m[12] = diff[0][0] - diff[3][0];

m[13] = diff[0][1] - diff[3][1];

m[14] = diff[0][2] - diff[3][2];

m[15] = diff[0][3] - diff[3][3];
d[0] = m[0] + m[4];

d[1] = m[1] + m[5];

d[2] = m[2] + m[6];

d[3] = m[3] + m[7];

d[4] = m[8] + m[12];

d[5] = m[9] + m[13];

d[6] = m[10] + m[14];

d[7] = m[11] + m[15];

d[8] = m[0] - m[4];

d[9] = m[1] - m[5];

d[10] = m[2] - m[6];

d[11] = m[3] - m[7];

d[12] = m[12] - m[8];

d[13] = m[13] - m[9];

d[14] = m[14] - m[10];

d[15] = m[15] - m[11];


m[0] = d[0] + d[3];

m[1] = d[1] + d[2];

m[2] = d[1] - d[2];

m[3] = d[0] - d[3];

m[4] = d[4] + d[7];

m[5] = d[5] + d[6];

m[6] = d[5] - d[6];

m[7] = d[4] - d[7];

m[8] = d[8] + d[11];

m[9] = d[9] + d[10];

m[10] = d[9] - d[10];

m[11] = d[8] - d[11];

m[12] = d[12] + d[15];

m[13] = d[13] + d[14];

m[14] = d[13] - d[14];

m[15] = d[12] - d[15];


d[0] = m[0] + m[1];

d[1] = m[0] - m[1];

d[2] = m[2] + m[3];

d[3] = m[3] - m[2];

d[4] = m[4] + m[5];

d[5] = m[4] - m[5];

d[6] = m[6] + m[7];

d[7] = m[7] - m[6];

d[8] = m[8] + m[9];

d[9] = m[8] - m[9];

d[10] = m[10] + m[11];

d[11] = m[11] - m[10];

d[12] = m[12] + m[13];

d[13] = m[12] - m[13];

d[14] = m[14] + m[15];

d[15] = m[15] - m[14];


// sum SATD

for (int k = 0; k < 16; ++k) {

satd += Math.abs(d[k]);

}
return ((satd + 1) >> 1);

}
}



    1. A8 Classes para codificação de entropia




      1. A8.1 Classe VLCTable



package br.ufsc.inf.guiga.media.codec.video.h264.vcl.entropy;
public class VLCTable {

// [Tables 1, 2, 3, 5 and 6][TrailingOnes][TotalCoeff]



protected static final int[][][] coeffTokenCodeLength = {

{

{ 1, 6, 8, 9,10,11,13,13,13,14,14,15,15,16,16,16,16},



{ 0, 2, 6, 8, 9,10,11,13,13,14,14,15,15,15,16,16,16},

{ 0, 0, 3, 7, 8, 9,10,11,13,13,14,14,15,15,16,16,16},

{ 0, 0, 0, 5, 6, 7, 8, 9,10,11,13,14,14,15,15,16,16},

},

{ { 2, 6, 6, 7, 8, 8, 9,11,11,12,12,12,13,13,13,14,14},



{ 0, 2, 5, 6, 6, 7, 8, 9,11,11,12,12,13,13,14,14,14},

{ 0, 0, 3, 6, 6, 7, 8, 9,11,11,12,12,13,13,13,14,14},

{ 0, 0, 0, 4, 4, 5, 6, 6, 7, 9,11,11,12,13,13,13,14},

},

{ { 4, 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 9,10,10,10,10},



{ 0, 4, 5, 5, 5, 5, 6, 6, 7, 8, 8, 9, 9, 9,10,10,10},

{ 0, 0, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,10},

{ 0, 0, 0, 4, 4, 4, 4, 4, 5, 6, 7, 8, 8, 9,10,10,10},

},

{//Table 4: Fixed Length



{ },

},

{//Table 5: YUV 4:2:0



{ 2, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 1, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 3, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

},

{//Table 6: YUV 4:2:2



{ 1, 7, 7, 9, 9,10,11,12,13, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 2, 7, 7, 9,10,11,12,12, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 3, 7, 7, 9,10,11,12, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 0, 5, 6, 7, 7,10,11, 0, 0, 0, 0, 0, 0, 0, 0}

}

};

protected static final int[][][] coeffTokenCodeValue = {



{ { 1, 5, 7, 7, 7, 7,15,11, 8,15,11,15,11,15,11, 7,4},

{ 0, 1, 4, 6, 6, 6, 6,14,10,14,10,14,10, 1,14,10,6},

{ 0, 0, 1, 5, 5, 5, 5, 5,13, 9,13, 9,13, 9,13, 9,5},

{ 0, 0, 0, 3, 3, 4, 4, 4, 4, 4,12,12, 8,12, 8,12,8},

},

{ { 3,11, 7, 7, 7, 4, 7,15,11,15,11, 8,15,11, 7, 9,7},



{ 0, 2, 7,10, 6, 6, 6, 6,14,10,14,10,14,10,11, 8,6},

{ 0, 0, 3, 9, 5, 5, 5, 5,13, 9,13, 9,13, 9, 6,10,5},

{ 0, 0, 0, 5, 4, 6, 8, 4, 4, 4,12, 8,12,12, 8, 1,4},

},

{ {15,15,11, 8,15,11, 9, 8,15,11,15,11, 8,13, 9, 5,1},



{ 0,14,15,12,10, 8,14,10,14,14,10,14,10, 7,12, 8,4},

{ 0, 0,13,14,11, 9,13, 9,13,10,13, 9,13, 9,11, 7,3},

{ 0, 0, 0,12,11,10, 9, 8,13,12,12,12, 8,12,10, 6,2},

},

{//Table 4: Fixed Length



{ },

},

{//Table 5: YUV 4:2:0



{ 1, 7, 4, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 1, 6, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

},

{//Table 6: YUV 4:2:2



{ 1,15,14, 7, 6, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 1,13,12, 5, 6, 6, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 1,11,10, 4, 5, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0},

{ 0, 0, 0, 1, 1, 9, 8, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0}

}

};

// [tzVlcIndex (VLC Table)][total_zeros]



protected static final int[][] totalZeros4x4CodeLength =

{ { 1,3,3,4,4,5,5,6,6,7,7,8,8,9,9,9},

{ 3,3,3,3,3,4,4,4,4,5,5,6,6,6,6},

{ 4,3,3,3,4,4,3,3,4,5,5,6,5,6},

{ 5,3,4,4,3,3,3,4,3,4,5,5,5},

{ 4,4,4,3,3,3,3,3,4,5,4,5},

{ 6,5,3,3,3,3,3,3,4,3,6},

{ 6,5,3,3,3,2,3,4,3,6},

{ 6,4,5,3,2,2,3,3,6},

{ 6,6,4,2,2,3,2,5},

{ 5,5,3,2,2,2,4},

{ 4,4,3,3,1,3},

{ 4,4,2,1,3},

{ 3,3,1,2},

{ 2,2,1},

{ 1,1}


};

protected static final int[][] totalZeros4x4CodeValue =

{ {1,3,2,3,2,3,2,3,2,3,2,3,2,3,2,1},

{7,6,5,4,3,5,4,3,2,3,2,3,2,1,0},

{5,7,6,5,4,3,4,3,2,3,2,1,1,0},

{3,7,5,4,6,5,4,3,3,2,2,1,0},

{5,4,3,7,6,5,4,3,2,1,1,0},

{1,1,7,6,5,4,3,2,1,1,0},

{1,1,5,4,3,3,2,1,1,0},

{1,1,1,3,3,2,2,1,0},

{1,0,1,3,2,1,1,1,},

{1,0,1,3,2,1,1,},

{0,1,1,2,1,3},

{0,1,1,1,1},

{0,1,1,1},

{0,1,1},

{0,1}


};

// [tzVlcIndex (VLC Table)][total_zeros]



protected static final int[][] totalZeros2x2CodeLength =

{ { 1,2,3,3},

{ 1,2,2},

{ 1,1}


};

protected static final int[][] totalZeros2x2CodeValue =

{ { 1,1,1,0},

{ 1,1,0},

{ 1,0}


};

// [zerosLeft][run_before]



protected static final int[][] runBeforeCodeLength =

{ {1,1},


{1,2,2},

{2,2,2,2},

{2,2,2,3,3},

{2,2,3,3,3,3},

{2,3,3,3,3,3,3},

{3,3,3,3,3,3,3,4,5,6,7,8,9,10,11},

};

protected static final int[][] runBeforeCodeValue =

{ {1,0},


{1,1,0},

{3,2,1,0},

{3,2,1,1,0},

{3,2,3,2,1,0},

{3,0,1,3,2,5,4},

{7,6,5,4,3,2,1,1,1,1,1,1,1,1,1},

};

}

      1. A8.2 Classe CAVLC



package br.ufsc.inf.guiga.media.codec.video.h264.vcl.entropy;
import br.ufsc.inf.guiga.media.codec.video.h264.vcl.block.ResidualBlockInfo;

import br.ufsc.inf.guiga.media.codec.video.h264.vcl.datatype.ResidualBlockType;

import br.ufsc.inf.guiga.media.util.io.BitOutputStream;
/**

* (CA)VLC coding methods.

*

* @author Guilherme Ferreira



*/

public class CAVLC extends VLCTable implements EntropyOutputStream {
public static final int CAVLC_LEVEL_LIMIT = 2063;

private static final int RUNBEFORE_NUM_M1 = 6;
private BitOutputStream bitStream;
/**

* Creates an output stream that writes CAVLC coded values.

*

* @param bitStream the target bit stream that all values should be coded into.



*/

public CAVLC(BitOutputStream bitStream) {

this.bitStream = bitStream;

}
// -------------------------------------------------------------------------

// FIXED LENGTH

// -------------------------------------------------------------------------


public int write_u_v(int n, int value) {

SyntaxElement se = new SyntaxElement();


se.bitpattern = value;

se.length = n;

se.value1 = value;
writeUVLC2buffer(se, bitStream);
return se.length;

}
public int write_u_1(boolean value) {

SyntaxElement se = new SyntaxElement();
se.bitpattern = value ? 1 : 0;

se.length = 1;

se.value1 = value ? 1 : 0;
writeUVLC2buffer(se, bitStream);
return se.length;

}
// -------------------------------------------------------------------------

// EXP-GOLOMB

// -------------------------------------------------------------------------


public int write_ue_v(int value) {

SyntaxElement se = new SyntaxElement();


se.value1 = value;

se.value2 = 0;


ue_linfo(se);

symbol2uvlc(se);


writeUVLC2buffer(se, bitStream);
return se.length;

}
public int write_se_v(int value) {

SyntaxElement se = new SyntaxElement();
se.value1 = value;

se.value2 = 0;


se_linfo(se);

symbol2uvlc(se);


writeUVLC2buffer(se, bitStream);
return se.length;

}
/**

* Mapping for ue(v) syntax elements.

* {@link SyntaxElement#length}: returns total mapped value length, including leading

* zeros

* (i.e., the length of the string 0 0 .. 0 1 Xn .. X1 X0 )


* {@link SyntaxElement#info}: returns mapped value Xn..X2 X1 X0

*

* @param se


* SyntaxElement.value1: value to be mapped

*/

private void ue_linfo(SyntaxElement se) {

int nn = (se.value1 + 1) >> 1;

int i;

for (i = 0; i < 33 && nn != 0; i++) {

nn >>= 1;

}

se.length = (i << 1) + 1;



// read_bits( leadingZeroBits ) = codeNum - 2^leadingZeroBits (page 154)

se.info = se.value1 + 1 - (1 << i);

}
/**

* Mapping for se(v) syntax elements.


* {@link SyntaxElement#length}: returns total mapped value length, including leading

* zeros

* (i.e., the length of the string 0 0 .. 0 1 Xn .. X1 X0 )


* {@link SyntaxElement#info}: returns mapped value Xn..X2 X1 X0

*

* @param se


* {@link SyntaxElement#value1}: value to be mapped

*/

private void se_linfo(SyntaxElement se) {

int sign = (se.value1 <= 0) ? 1 : 0;

// n+1 is the number in the code table. Based on this we find length and

// info

int n = Math.abs(se.value1) << 1;

int nn = (n >> 1);

int i;

for (i = 0; i < 33 && nn != 0; i++) {

nn >>= 1;

}

se.length = (i << 1) + 1;



se.info = n - (1 << i) + sign;

}
/**

* Makes code word and passes it back through the attribute

* {@link SyntaxElement#bitpattern}, which receives a code word in the following

* format:

* 0 0 0 ... 1 Xn ...X2 X1 X0.

*

* @param se


* {@link SyntaxElement#info}: Xn..X2 X1 X0


* {@link SyntaxElement#length}: Total number of bits in the codeword

*/

private int symbol2uvlc(SyntaxElement se) {

int suffix_len = se.length >> 1;
assert (suffix_len < 32);

se.bitpattern = (1 << suffix_len) | (se.info & ((1 << suffix_len) - 1));


return 0;

}
// -------------------------------------------------------------------------

// CAVLC

// -------------------------------------------------------------------------


/**

* Makes code word and passes it back.

*

* @param se


* {@link SyntaxElement#info}: Xn..X2 X1 X0


* {@link SyntaxElement#length}: Total number of bits in the codeword

*/

private int symbol2vlc(SyntaxElement se) {

int info_len = se.length;
// Convert info into a bit pattern integer

se.bitpattern = 0;


// VLC coding

while (--info_len >= 0) {

se.bitpattern <<= 1;

se.bitpattern |= (0x01 & (se.info >> info_len));

}

return 0;

}
// -------------------------------------------------------------------------

// PRE-DEFINED SYMBOLS WRITING FUNCTIONS

// -------------------------------------------------------------------------
public int writeMacroblockType(int value) {

return write_ue_v(value);

}
public int writeIntraChromaPredMode(int value) {



return write_ue_v(value);

}
public int writeMackoblockQpDelta(int value) {



return write_se_v(value);

}
public int writeResidualBlock(



int[] coeffLevel, int[] coeffRun, ResidualBlockType type,

ResidualBlockInfo residualBlock)

{

// Maximum number of coefficients of this block



int maxNumCoeff = getMaxNumCoeff(type);

int totalCoeff = 0; // Number of non-zero coefficients of this block

int trailingOnes = 0; // Number of +-1s

int totalZeros = 0; // Total number of zero coefficients

int vlcTableIdx = 0; // VLC Table Index

int lastCoeff = 0; // Last non-zero coefficient

int numBits = 0; // Amount of bits used to code this residual block
// Count the amount of non-zero coefficients and the trailing ones to build

// coeff_token.



for (int k = 0; k < maxNumCoeff; k++) {

int level = coeffLevel[k];

int run = coeffRun[k];
if (level != 0) {

totalZeros += run;


if (Math.abs(level) == 1) {

trailingOnes++;

trailingOnes = Math.min(trailingOnes, 3); // clip to 3

} else {

trailingOnes = 0;

}
totalCoeff++;

lastCoeff = k;

}

}


// Select coeff_token VLC Table.

vlcTableIdx = selectVlcTableIndex(type, residualBlock);


// Write coeff_token: the count of TrailingOnes and TotalCoeff.

numBits += writeCoeffToken(totalCoeff, trailingOnes, vlcTableIdx);


if (totalCoeff > 0) {

// Write trailing_ones_sign_flags: an integer with the signal of

// each trailing ones in reverse order, from highest frequency

// coefficient to DC coefficient.



int trailingOnesSignFlags = 0;

for (int k = lastCoeff; k > (lastCoeff - trailingOnes); k--) {

int level = coeffLevel[k];

trailingOnesSignFlags <<= 1;



if (level < 0) {

trailingOnesSignFlags |= 0x1;

}

}

if (trailingOnes > 0)



numBits += writeTrailingOnesSignFlag(trailingOnesSignFlags, trailingOnes);
// Write level_prefix and level_sufix: the remaining non-zero coefficients.

int suffixLength = ((totalCoeff > 10) && (trailingOnes < 3)) ? 1 : 0;

// Threshold to increment suffixLength: ( 3 << ( suffixLength – 1 ) )



int incVlc[] = { 0, 3, 6, 12, 24, 48, 32768 };

// TODO what is this level two or higher?



int levelTwoOrHigher = (totalCoeff > 3 && trailingOnes == 3) ? 0 : 1;
for (int k = (lastCoeff - trailingOnes); k >= 0; k--) {

int level = coeffLevel[k];

int levelTmp = level;
if (levelTwoOrHigher != 0) {

levelTwoOrHigher = 0;



if (levelTmp > 0)

levelTmp--;



else

levelTmp++;

}
numBits += writeLevel(levelTmp, suffixLength);
// update VLC table

if (Math.abs(level) > incVlc[suffixLength])

suffixLength++;


if ((k == (lastCoeff - trailingOnes)) && (Math.abs(level) > 3))

suffixLength = 2;


}
// Write total_zeros: the quantity of zeros that precede the highest

// frequency coefficient.

numBits += writeTotalZeros(totalZeros, totalCoeff, maxNumCoeff);
// Write run_before: the zeroLeft/runBefore pair for each

// coefficient, where zeroLeft is the total amount of zeros on the

// left of the coefficient and runBefore is the amount of zeros

// immediately on the left of the coefficient.



int zerosLeft = totalZeros;

int numCoeff = totalCoeff;

for (int k = lastCoeff; k >= 0; k--) {

int runBefore = coeffRun[k];
// For last coefficient, run is remaining total zeros.

// When zerosLeft is zero, remaining coefficients have 0 run.



if ((zerosLeft == 0) || (numCoeff <= 1))

break;
numBits += writeRunBefore(runBefore, zerosLeft);
zerosLeft -= runBefore;

numCoeff--;

}
}
return numBits;

}
private int getMaxNumCoeff(ResidualBlockType type) {



int maxNumCoeff = 0;
switch (type) {

case Intra16x16LumaDCLevel:

maxNumCoeff = 16; // 16 DCs from the sixteen 4x4 blocks



break;

case Intra16x16LumaACLevel:

maxNumCoeff = 15; // the first level/coefficient of each AC block is the DC



break;

case CbIntra8x8ChromaDCLevel:

case CrIntra8x8ChromaDCLevel:

maxNumCoeff = 4; // 4 DCs from the four 4x4 blocks



break;

case CbIntra8x8ChromaACLevel:

case CrIntra8x8ChromaACLevel:

maxNumCoeff = 15; // the first level of each AC block is the DC



break;

}
return maxNumCoeff;

}
private int selectVlcTableIndex(

ResidualBlockType type, ResidualBlockInfo residualBlock)

{

int nC = residualBlock.getMacroblockInfo().getPredictedNonZeroCoeff(type,

residualBlock);


int vlcTableIdx = 0;
if ((type == ResidualBlockType.CbIntra8x8ChromaDCLevel)

|| (type == ResidualBlockType.CrIntra8x8ChromaDCLevel))

{

// chroma DC (has its own VLC, Table 5) if nC == -1 for 4:2:0



vlcTableIdx = 4;

} else {

// selects VLC table based on nC

if (nC < 2) {

vlcTableIdx = 0;

} else if (nC < 4) {

vlcTableIdx = 1;

} else if (nC < 8) {

vlcTableIdx = 2;

} else {

vlcTableIdx = 3;

}

}
return vlcTableIdx;



}
private int writeCoeffToken(int totalCoeff, int trailingOnes, int vlcTableIdx) {

SyntaxElement se = new SyntaxElement();


if (vlcTableIdx == 3) { // Table 4: Fixed Length
se.length = 6; // 4 + 2 bit FLC
if (totalCoeff > 0) {

se.info = ((totalCoeff - 1) << 2) | trailingOnes;

} else {

se.info = 3;

}
} else { // Tables 1, 2, 3, 5 and 6: Variable Length.

// Table 1, 2 and 3: Luma

// Table 5: Chroma YUV 4:2:0

// Table 6: Chroma YUV 4:2:2

se.length = coeffTokenCodeLength[vlcTableIdx][trailingOnes][totalCoeff];

se.info = coeffTokenCodeValue[vlcTableIdx][trailingOnes][totalCoeff];

}
symbol2vlc(se);

writeUVLC2buffer(se, bitStream);


return se.length;

}
private int writeTrailingOnesSignFlag(int trailingOnesSignFlags, int trailingOnes) {



int numBits = 0;
if (trailingOnes >= 0) {

SyntaxElement se = new SyntaxElement();


se.length = trailingOnes;

se.info = trailingOnesSignFlags;


symbol2vlc(se);

writeUVLC2buffer(se, bitStream);


numBits = se.length;

}
return numBits;

}
private int writeLevel(int level, int levelSuffixSize) {

if (levelSuffixSize == 0)

return writeLevelVLC1(level);

else

return writeLevelVLCN(level, levelSuffixSize);

}
private int writeLevelVLC1(int level) {

SyntaxElement se = new SyntaxElement();

int levabs = Math.abs(level);

int sign = (level < 0 ? 1 : 0);
if (levabs < 8) {

se.length = levabs * 2 + sign - 1;

se.info = 1;
} else if (levabs < 16) {

// escape code1

se.length = 19;

se.info = (1 << 4) | ((levabs - 8) << 1) | sign;


} else {

int iLength = 28, numPrefix = 15;

int iCodeword, addbit;

int levabsm16 = levabs - 16;
// escape code2

if ((levabsm16) >= 2048) {

numPrefix++;



while ((levabsm16) >= (1 << (numPrefix - 3)) - 4096) {

numPrefix++;

}

}
addbit = numPrefix - 15;



iLength += (addbit << 1);

iCodeword = (1 << (12 + addbit)) | ((levabsm16) << 1) | sign;


// Assert to make sure that the code fits in the VLC

// TODO make sure that we are in High Profile to represent level_prefix > 15



if (numPrefix > 15) {

se.length = 0x0000FFFF; // This can be some other big number

se.info = iCodeword;

}
se.length = iLength;

se.info = iCodeword;

}
symbol2vlc(se);

writeUVLC2buffer(se, bitStream);
return se.length;

}
private int writeLevelVLCN(int level, int vlc) {

SyntaxElement se = new SyntaxElement();

int iCodeword;

int iLength;
int sign = (level < 0 ? 1 : 0);

int levabs = Math.abs(level) - 1;
int shift = vlc - 1;

int escape = (15 << shift);
if (levabs < escape) {

int sufmask = ~((0xffffffff) << shift);

int suffix = (levabs) & sufmask;

int numPrefix = (levabs) >> shift;
iLength = numPrefix + vlc + 1;

iCodeword = (1 << (shift + 1)) | (suffix << 1) | sign;

} else {

int addbit, offset;

int levabsesc = levabs - escape;

int numPrefix = 15;
iLength = 28;
if ((levabsesc) >= 2048) {

numPrefix++;



while ((levabsesc) >= (1 << (numPrefix - 3)) - 4096) {

numPrefix++;

}

}
addbit = numPrefix - 15;


iLength += (addbit << 1);

offset = (2048 << addbit) - 2048;


iCodeword = (1 << (12 + addbit)) | ((levabsesc - offset) << 1) | sign;
// Assert to make sure that the code fits in the VLC

// TODO make sure that we are in High Profile to represent level_prefix > 15



if (numPrefix > 15) {

se.length = 0x0000FFFF; // This can be some other big number

se.info = iCodeword;

}

}



se.length = iLength;

se.info = iCodeword;


symbol2vlc(se);

writeUVLC2buffer(se, bitStream);


return se.length;

}
private int writeTotalZeros(int totalZeros, int totalCoeff, int maxNumCoeff) {



int numBits = 0;
if (totalCoeff < maxNumCoeff) {

SyntaxElement se = new SyntaxElement();


int vlcTable = totalCoeff - 1;

if (maxNumCoeff == 4) {// YUV 4:2:0

se.length = totalZeros2x2CodeLength[vlcTable][totalZeros];

se.info = totalZeros2x2CodeValue[vlcTable][totalZeros];

} else {// Luma, YUV 4:4:4

se.length = totalZeros4x4CodeLength[vlcTable][totalZeros];

se.info = totalZeros4x4CodeValue[vlcTable][totalZeros];

}
symbol2vlc(se);

writeUVLC2buffer(se, bitStream);


numBits = se.length;

}
return numBits;

}
private int writeRunBefore(int runBefore, int zerosLeft) {

int numBits = 0;
if (zerosLeft > 0) {

SyntaxElement se = new SyntaxElement();



int vlcTable = Math.min(zerosLeft - 1, RUNBEFORE_NUM_M1);
se.length = runBeforeCodeLength[vlcTable][runBefore];

se.info = runBeforeCodeValue[vlcTable][runBefore];


symbol2vlc(se);

writeUVLC2buffer(se, bitStream);

}
return numBits;

}
// --------------------------------------------------------------------------

// HELPER

// --------------------------------------------------------------------------


/**

* Writes UVLC code to the appropriate buffer.

*

* @param se the syntax element to write in the stream.


* {@link SyntaxElement#length}: number of bits to write.


* {@link SyntaxElement#bitpattern}: the bits to write.

* @param currStream the stream in which the syntax element will be write.

*/

private void writeUVLC2buffer(SyntaxElement se, BitOutputStream currStream) {

currStream.write(se.bitpattern, se.length);

}
}





1   ...   12   13   14   15   16   17   18   19   ...   24


©livred.info 2017
enviar mensagem

    Página principal