Especificação



Baixar 2,81 Mb.
Página14/24
Encontro01.07.2018
Tamanho2,81 Mb.
1   ...   10   11   12   13   14   15   16   17   ...   24

A5 Classes de codificação 2 – Algoritmos




      1. A5.1 Classe IntegerTransform



package br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.impl;
import br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.Transform;

import br.ufsc.inf.guiga.media.codec.video.h264.vcl.block.Block;
/**

* This class implements the transform operations using only integer arithmetic's. The

* transforms are orthogonal approximations of DCT.

*

* @author Guilherme Ferreira



*/

public class IntegerTransform extends Transform {
private int[] tmp; // temporary transformed samples
public IntegerTransform() {

tmp = new int[64];

}
@Override

public void forward4x4(int[][] src, int[][] dst, int pos_y, int pos_x) {

int ii;

int p0, p1, p2, p3;

int t0, t1, t2, t3;

int tmpIdx = 0;
// Horizontal

for (int i = pos_y; i < pos_y + Block.BLOCK_4x4_SIZE; i++) {

p0 = src[i][pos_x + 0];

p1 = src[i][pos_x + 1];

p2 = src[i][pos_x + 2];

p3 = src[i][pos_x + 3];
t0 = p0 + p3;

t1 = p1 + p2;

t2 = p1 - p2;

t3 = p0 - p3;


tmp[tmpIdx++] = t0 + t1;

tmp[tmpIdx++] = (t3 << 1) + t2;

tmp[tmpIdx++] = t0 - t1;

tmp[tmpIdx++] = t3 - (t2 << 1);

}
// Vertical

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

tmpIdx = i;

p0 = tmp[tmpIdx];

p1 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

p2 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

p3 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];


t0 = p0 + p3;

t1 = p1 + p2;

t2 = p1 - p2;

t3 = p0 - p3;


ii = pos_x + i;

dst[pos_y + 0][ii] = t0 + t1;

dst[pos_y + 1][ii] = t2 + (t3 << 1);

dst[pos_y + 2][ii] = t0 - t1;

dst[pos_y + 3][ii] = t3 - (t2 << 1);

}

}


@Override

public void inverse4x4(int[][] src, int[][] dst, int pos_y, int pos_x) {

int ii;

int p0, p1, p2, p3;

int t0, t1, t2, t3;

int tmpIdx = 0;
// Horizontal

for (int i = pos_y; i < pos_y + Block.BLOCK_4x4_SIZE; i++) {

t0 = src[i][pos_x + 0];

t1 = src[i][pos_x + 1];

t2 = src[i][pos_x + 2];

t3 = src[i][pos_x + 3];
p0 = t0 + t2;

p1 = t0 - t2;

p2 = (t1 >> 1) - t3;

p3 = t1 + (t3 >> 1);


tmp[tmpIdx++] = p0 + p3;

tmp[tmpIdx++] = p1 + p2;

tmp[tmpIdx++] = p1 - p2;

tmp[tmpIdx++] = p0 - p3;

}
// Vertical

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

tmpIdx = i;

t0 = tmp[tmpIdx];

t1 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

t2 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

t3 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];


p0 = t0 + t2;

p1 = t0 - t2;

p2 = (t1 >> 1) - t3;

p3 = t1 + (t3 >> 1);


ii = pos_x + i;

dst[pos_y + 0][ii] = p0 + p3;

dst[pos_y + 1][ii] = p1 + p2;

dst[pos_y + 2][ii] = p1 - p2;

dst[pos_y + 3][ii] = p0 - p3;

}

}


@Override

public void hadamard4x4(int[][] src, int[][] dst) {

int p0, p1, p2, p3;

int t0, t1, t2, t3;

int tmpIdx = 0;
// Horizontal

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

p0 = src[i][0];

p1 = src[i][1];

p2 = src[i][2];

p3 = src[i][3];
t0 = p0 + p3;

t1 = p1 + p2;

t2 = p1 - p2;

t3 = p0 - p3;


tmp[tmpIdx++] = t0 + t1;

tmp[tmpIdx++] = t3 + t2;

tmp[tmpIdx++] = t0 - t1;

tmp[tmpIdx++] = t3 - t2;

}
// Vertical

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

tmpIdx = i;

p0 = tmp[tmpIdx];

p1 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

p2 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

p3 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];


t0 = p0 + p3;

t1 = p1 + p2;

t2 = p1 - p2;

t3 = p0 - p3;


dst[0][i] = (t0 + t1) >> 1;

dst[1][i] = (t2 + t3) >> 1;

dst[2][i] = (t0 - t1) >> 1;

dst[3][i] = (t3 - t2) >> 1;

}

}
@Override



public void ihadamard4x4(int[][] src, int[][] dst) {

int p0, p1, p2, p3;

int t0, t1, t2, t3;

int tmpIdx = 0;
// Horizontal

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

t0 = src[i][0];

t1 = src[i][1];

t2 = src[i][2];

t3 = src[i][3];
p0 = t0 + t2;

p1 = t0 - t2;

p2 = t1 - t3;

p3 = t1 + t3;


tmp[tmpIdx++] = p0 + p3;

tmp[tmpIdx++] = p1 + p2;

tmp[tmpIdx++] = p1 - p2;

tmp[tmpIdx++] = p0 - p3;

}
// Vertical

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

tmpIdx = i;


t0 = tmp[tmpIdx];

t1 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

t2 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];

t3 = tmp[tmpIdx += Block.BLOCK_4x4_SIZE];


p0 = t0 + t2;

p1 = t0 - t2;

p2 = t1 - t3;

p3 = t1 + t3;


dst[0][i] = p0 + p3;

dst[1][i] = p1 + p2;

dst[2][i] = p1 - p2;

dst[3][i] = p0 - p3;

}

}
@Override



public void hadamard2x2(int[][] src, int[][] dst) {

int p0, p1, p2, p3;
p0 = src[0][0] + src[0][1];

p1 = src[0][0] - src[0][1];

p2 = src[1][0] + src[1][1];

p3 = src[1][0] - src[1][1];


dst[0][0] = (p0 + p2);

dst[0][1] = (p1 + p3);

dst[1][0] = (p0 - p2);

dst[1][1] = (p1 - p3);

}
@Override

public void ihadamard2x2(int[][] src, int[][] dst) {

int t0, t1, t2, t3;
t0 = src[0][0] + src[0][1];

t1 = src[0][0] - src[0][1];

t2 = src[1][0] + src[1][1];

t3 = src[1][0] - src[1][1];


dst[0][0] = (t0 + t2);

dst[0][1] = (t1 + t3);

dst[1][0] = (t0 - t2);

dst[1][1] = (t1 - t3);

}
}

      1. A5.2 Classe ZigZagFrameScanner



package br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.impl;
import br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.Scanner;
public class ZigZagFrameScanner implements Scanner {
private int[][] scanOrder = { // [coeff: one out of 16 coefficients][comp: x or y]

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

{ 0, 3 }, { 1, 3 }, { 2, 2 }, { 3, 1 }, { 3, 2 }, { 2, 3 }, { 3, 3 } };
public void reorder4x4(

int[][] srcCoeff, int[] dstLevel, int[] dstRun, int start, int length,

int yOffset, int xOffset)

{

int level;



int run = -1;

int scanPos = 0;
for (int coeff = start; coeff < length; coeff++) {

int i = positionToCoordinateX(coeff) + xOffset;

int j = positionToCoordinateY(coeff) + yOffset;
run++;

level = srcCoeff[j][i];


if (level != 0) {

dstLevel[scanPos] = level;

dstRun[scanPos] = run;
scanPos++;
run = -1;

}

}


}
public void reorder2x2(

int[][] srcCoeff, int[] dstLevel, int[] dstRun, int start, int length,

int yOffset, int xOffset)

{

int level;



int run = -1;

int scanPos = 0;
for (int coeff = start; coeff < length; coeff++) {

int i = (coeff % 2) + xOffset;

int j = (coeff / 2) + yOffset;
run++;

level = srcCoeff[j][i];


if (level != 0) {

dstLevel[scanPos] = level;

dstRun[scanPos] = run;
scanPos++;
run = -1;

}

}



}
public int positionToCoordinateX(int pos) {

return scanOrder[pos][0];

}
public int positionToCoordinateY(int pos) {



return scanOrder[pos][1];

}
}


      1. A5.3 Classe IntegerRoundQuantizer



package br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.impl;
import br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.Quantizer;

import br.ufsc.inf.guiga.media.codec.video.h264.vcl.algorithm.Scanner;

import br.ufsc.inf.guiga.media.codec.video.h264.vcl.block.Block;

import br.ufsc.inf.guiga.media.codec.video.h264.vcl.entropy.CAVLC;

import br.ufsc.inf.guiga.media.util.SupportMath;
public class IntegerRoundingQuantizer extends Quantizer {
// -------------------------------------------------------------------------

// Definitions

// -------------------------------------------------------------------------
private static final int MAX_QP = 51;

private static final int Q_BITS = 15;
// Multiplication Factor, quantizer coefficients [QP][j][i] <-> [6][4][4]

private static final int quantCoeff[][][] = {

{ { 13107, 8066, 13107, 8066 }, { 8066, 5243, 8066, 5243 },

{ 13107, 8066, 13107, 8066 }, { 8066, 5243, 8066, 5243 } },

{ { 11916, 7490, 11916, 7490 }, { 7490, 4660, 7490, 4660 },

{ 11916, 7490, 11916, 7490 }, { 7490, 4660, 7490, 4660 } },

{ { 10082, 6554, 10082, 6554 }, { 6554, 4194, 6554, 4194 },

{ 10082, 6554, 10082, 6554 }, { 6554, 4194, 6554, 4194 } },

{ { 9362, 5825, 9362, 5825 }, { 5825, 3647, 5825, 3647 },

{ 9362, 5825, 9362, 5825 }, { 5825, 3647, 5825, 3647 } },

{ { 8192, 5243, 8192, 5243 }, { 5243, 3355, 5243, 3355 },

{ 8192, 5243, 8192, 5243 }, { 5243, 3355, 5243, 3355 } },

{ { 7282, 4559, 7282, 4559 }, { 4559, 2893, 4559, 2893 },

{ 7282, 4559, 7282, 4559 }, { 4559, 2893, 4559, 2893 } } };
// Scaling factor, dequantizer coefficients [QP][j][i] <-> [6][4][4]

private static final int dequantCoeff[][][] = {

{ { 10, 13, 10, 13 }, { 13, 16, 13, 16 }, { 10, 13, 10, 13 },

{ 13, 16, 13, 16 } },

{ { 11, 14, 11, 14 }, { 14, 18, 14, 18 }, { 11, 14, 11, 14 },

{ 14, 18, 14, 18 } },

{ { 13, 16, 13, 16 }, { 16, 20, 16, 20 }, { 13, 16, 13, 16 },

{ 16, 20, 16, 20 } },

{ { 14, 18, 14, 18 }, { 18, 23, 18, 23 }, { 14, 18, 14, 18 },

{ 18, 23, 18, 23 } },

{ { 16, 20, 16, 20 }, { 20, 25, 20, 25 }, { 16, 20, 16, 20 },

{ 20, 25, 20, 25 } },

{ { 18, 23, 18, 23 }, { 23, 29, 23, 29 }, { 18, 23, 18, 23 },

{ 23, 29, 23, 29 } } };
private static final short offset4x4Intra[][] = {

{ 682, 682, 682, 682 },

{ 682, 682, 682, 682 },

{ 682, 682, 682, 682 },

{ 682, 682, 682, 682 } };

private int[] COEFF_COST4x4 = { 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private static final int MAX_VALUE = 999999;
// -------------------------------------------------------------------------

// Attributes

// -------------------------------------------------------------------------
private int[] qp_per_matrix; // Pre-calculated floor(QP/6) for qbits

private int[] qp_rem_matrix; // Multiplication Factor indexer

private int[][][] levelOffset4x4Intra; // Pre-calculated offset for each QP

private int[][] invLevelScale4x4;

private Scanner scanner;
// -------------------------------------------------------------------------

// Methods

// -------------------------------------------------------------------------
public IntegerRoundingQuantizer(int qp, Scanner scanner) {

super(qp);
this.scanner = scanner;
initQMatrix();

calculateQuantParam();

calculateOffsetParam();

}
private void initQMatrix() {

qp_per_matrix = new int[MAX_QP + 1];

qp_rem_matrix = new int[MAX_QP + 1];


for (int i = 0; i < MAX_QP + 1; i++) {

qp_per_matrix[i] = i / 6;

qp_rem_matrix[i] = i % 6;

}

}


private void calculateQuantParam() {

invLevelScale4x4 = new int[Block.BLOCK_4x4_SIZE][Block.BLOCK_4x4_SIZE];



int qp_rem = qp_rem_matrix[qp];
for (int j = 0; j < Block.BLOCK_4x4_SIZE; j++) {

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

invLevelScale4x4[j][i] = dequantCoeff[qp_rem][j][i] << 4;

}

}
}
private void calculateOffsetParam() {



levelOffset4x4Intra = new int[MAX_QP + 1][Block.BLOCK_4x4_SIZE][Block.BLOCK_4x4_SIZE];

int OffsetBits = 11;
int k = qp_per_matrix[qp];

int qp_per = Q_BITS + k - OffsetBits;
for (int qp = 0; qp < MAX_QP + 1; qp++) {

for (int j = 0; j < Block.BLOCK_4x4_SIZE; j++) {

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

levelOffset4x4Intra[qp][j][i] = offset4x4Intra[j][i] << qp_per;

}

}

}



}
public QuantizerSummary quantization4x4DC(int[][] src, int[][] dst) {

int level = 0;

int run = 0;

int nonZeroCoeff = 0;

int coeffCost = 0;

int qp_per = qp_per_matrix[qp];

int qp_rem = qp_rem_matrix[qp];

int qbits = Q_BITS + qp_per; // qbits = 15 + floor(QP/6)

int[][] mf = quantCoeff[qp_rem]; // MF = (2^qbits * PF) / Qstep

int[][] f = levelOffset4x4Intra[qp]; // f = 2^qbits/3 for Intra
for (int j = 0; j < Block.BLOCK_4x4_SIZE; j++) {

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

// |Z(i,j)| = (|Y(i,j)|*MF(0,0) + 2*f) >> (qbits + 1)

level = (Math.abs(src[j][i]) * mf[0][0] + (f[0][0] << 1)) >> (qbits + 1);
if (level != 0) {

nonZeroCoeff++;


if (qp < 10) {

level = Math.min(level, CAVLC.CAVLC_LEVEL_LIMIT);

}
coeffCost += (level > 1) ? MAX_VALUE : COEFF_COST4x4[run];
// sign(Z(i,j)) = sign(Y(i,j))

dst[j][i] = level * (int) (Math.signum(src[j][i]));

run = 0;

} else {

dst[j][i] = 0;

run++;


}

}

}


return new QuantizerSummary(nonZeroCoeff, coeffCost);

}
public void iquantization4x4DC(int[][] src, int[][] dst) {



int qp_per = qp_per_matrix[qp];

int[][] v = invLevelScale4x4; // V = Qstep * PF * 64
for (int j = 0; j < Block.BLOCK_4x4_SIZE; j++) {

for (int i = 0; i < Block.BLOCK_4x4_SIZE; i++) {

// W'(i,j) = Z(i,j) * V(i,j) * 2^floor(QP/6)

dst[j][i] = SupportMath.rshiftRound(((src[j][i] * v[0][0]) << qp_per), 6);

}

}



}
public QuantizerSummary quantization2x2DC(int[][] src, int[][] dst) {

int level;

int nonZeroCoeff = 0;

int coeffCost = 0;

int qp_per = qp_per_matrix[qp];

int qp_rem = qp_rem_matrix[qp];

int qbits = Q_BITS + qp_per; // qbits = 15 + floor(QP/6)

int[][] mf = quantCoeff[qp_rem]; // MF = (2^qbits * PF) / Qstep

int[][] f = levelOffset4x4Intra[qp]; // f = 2^qbits/3 for Intra
for (int j = 0; j < Block.BLOCK_2x2_SIZE; j++) {

for (int i = 0; i < Block.BLOCK_2x2_SIZE; i++) {

// |Z(i,j)| = (|Y(i,j)|*MF(0,0) + 2*f) >> (qbits + 1)

level = (Math.abs(src[j][i]) * mf[0][0] + (f[0][0] << 1)) >> (qbits + 1);
if (level != 0) {

nonZeroCoeff++;


if (qp < 4) {

level = Math.min(level, CAVLC.CAVLC_LEVEL_LIMIT);

}
// sign(Z(i,j)) = sign(Y(i,j))

dst[j][i] = level * (int) (Math.signum(src[j][i]));

} else {

dst[j][i] = 0;

}

}

}


return new QuantizerSummary(nonZeroCoeff, coeffCost);

}
public void iquantization2x2DC(int[][] src, int[][] dst) {



int qp_per = qp_per_matrix[qp];

int[][] v = invLevelScale4x4; // V = Qstep * PF * 64
for (int j = 0; j < Block.BLOCK_2x2_SIZE; j++) {

for (int i = 0; i < Block.BLOCK_2x2_SIZE; i++) {

// W'(i,j) = Z(i,j) * V(i,j) * 2^floor(QP/6)

dst[j][i] = ((src[j][i] * v[0][0]) << qp_per) >> 5;

}

}



}
public QuantizerSummary quantization4x4AC(int[][] src, int[][] dst, int pos_y, int pos_x) {

int level = 0;

int run = 0;

int nonZeroCoeff = 0;

int coeffCost = 0;

int qp_per = qp_per_matrix[qp];

int qp_rem = qp_rem_matrix[qp];

int qbits = Q_BITS + qp_per; // qbits = 15 + floor(QP/6)

int[][] mf = quantCoeff[qp_rem]; // MF = (2^qbits * PF) / Qstep

int[][] f = levelOffset4x4Intra[qp]; // f = 2^qbits/3 for Intra
for (int coeff = 1; coeff < 16; coeff++) {

// The order the coefficients are quantized matters, so it's required the scanner

// to provide the right position

int j = scanner.positionToCoordinateX(coeff);

int i = scanner.positionToCoordinateY(coeff);

int jj = pos_y + j;

int ii = pos_x + i;

// |Z(i,j)| = (|Y(i,j)|*MF(0,0) + 2*f) >> (qbits + 1)

level = (Math.abs(src[jj][ii]) * mf[j][i] + f[j][i]) >> qbits;
if (level != 0) {

nonZeroCoeff++;


if (qp < 10) {

level = Math.min(level, CAVLC.CAVLC_LEVEL_LIMIT);

}
coeffCost += (level > 1) ? MAX_VALUE : COEFF_COST4x4[run];
// sign(Z(i,j)) = sign(Y(i,j))

dst[jj][ii] = level * (int) (Math.signum(src[jj][ii]));

run = 0;

} else {

dst[jj][ii] = 0;

run++;


}

}
return new QuantizerSummary(nonZeroCoeff, coeffCost);

}
public void iquantization4x4AC(int[][] src, int[][] dst, int pos_y, int pos_x) {

int qp_per = qp_per_matrix[qp];

int[][] v = invLevelScale4x4; // V = Qstep * PF * 64
for (int coeff = 1; coeff < 16; coeff++) {

int j = coeff / Block.BLOCK_4x4_SIZE;

int i = coeff % Block.BLOCK_4x4_SIZE;

int jj = pos_y + j;

int ii = pos_x + i;

// inverse scale

// W'(i,j) = Z(i,j) * V(i,j) * 2^floor(QP/4)

dst[jj][ii] = SupportMath.rshiftRound((src[jj][ii] * v[j][i]) << qp_per, 4);

}
}
}




1   ...   10   11   12   13   14   15   16   17   ...   24


©livred.info 2017
enviar mensagem

    Página principal