Especificação



Baixar 2,81 Mb.
Página9/24
Encontro01.07.2018
Tamanho2,81 Mb.
1   ...   5   6   7   8   9   10   11   12   ...   24

5.5 Codificação por Entropia


O padrão H.264 define dois tipos de codificação por entropia, CAVLC e CABAC. O método utilizado neste trabalho é o CAVLC, por ser o tipo usado pelo perfil Baseline.

O padrão H.264 codifica todas as informações de fatias, macroblocos e blocos usando ou CAVLC, ou CABAC, enquanto as informações acima da camada de fatia são codificadas usando códigos binários de tamanho fixo ou variável.

A classe CAVLC, juntamente com BitOutputStream, são responsáveis por implementar as funções para codificação por entropia CAVLC e Exp-Golomb. Abaixo está um exemplo que codifica o parâmetro profile_idc usando a função u(v)1, onde stream é um objeto da classe CAVLC.

len += stream.write_u_v(8, profile_idc);

A classe CAVLC é responsável por construir os códigos da codificação por entropia, enquanto a classe BitOutputStream é quem escreve os bits na stream de saída, que pode ser um arquivo ou a rede.



      1. 5.5.1 Exp-Golomb



        1. 5.5.1.1 Conceito

Exp-Golomb são códigos de largura variável com construções regulares [1], dispensando o uso de tabelas ou árvores de código. Esse método é usado para codificação da maior parte das informações do vídeo codificado pelo H.264 e é ideal para comprimir dados cujos valores pequenos têm uma freqüência muito grande[4]. O código Exp-Golomb possui a seguinte forma:

[M zeros][1][INFO]

Onde:


M = floor( log2(code_num + 1) )

INFO = code_num + 1 – 2M

Sendo INFO um campo de M bits contendo a informação codificada, a largura do código Exp-Golomb é (2M + 1) bits.

As funções Exp-Golomb recebem um número inteiro v como argumento e o mapeiam para code_num. No padrão H.264 são usadas algumas formas distintas de mapeamento entre v e code_num, dentre as quais estão presentes neste trabalho:



  • ue(v) é a função que codifica inteiros sem sinal (unsigned) usando Exp-Golomb. Essa função utiliza mapeamento direto, ou seja, code_num = v, e é representada no código pelo método CAVLC.write_ue_v(int value);

  • se(v) é uma variação da função ue(v) que codifica inteiros com sinal (signed). Representada pelo método CAVLC.write_se_v(int value). Nela, code_num é mapeado da seguinte forma:

code_num = 2 * |v| (v < 0)

code_num = 2 * |v| - 1 (v > 0)



As tabelas 5.1 e 5.2 ilustram os primeiros códigos Exp-Golomb para ue(v) e se(v), respectivamente.



v

code_num

Código Exp-Golomb

0

0

1

1

1

010

2

2

011

3

3

00100

4

4

00101

5

5

00110

6

6

00111

7

7

0001000

Tabela 5.1 – Oito primeiros códigos Exp_golomb para ue(v).


v

code_num

Código Exp-Golomb

0

0

1

1

1

010

-1

2

011

2

3

00100

-2

4

00101

3

5

00110

-3

6

00111

4

7

0001000

Tabela 5.2 – Oito primeiros códigos Exp_golomb para se(v).
No caso da codificação usando ue(v), é passado um valor v ao método public int write_ue_v(int value) da classe CAVLC. Esse método chama outros dois métodos para (1) criar INFO a partir do argumento v e (2) criar a string de código [M zeros][1][INFO].

        1. 5.5.1.2 Aplicação

Exp-Golomb é a técnica adotada para codificar a maioria dos parâmetros do vídeo H.264. Dentre os quais se destacam aqueles apresentes na tabela 5.3.




Parâmetro

Descrição

Conjunto de Parâmetros de Seqüência e de Figura (Sequence and Picture parameter Sets)

São os cabeçalhos que contém informações sobre todo o vídeo ou um quadro.

Tipo do Macrobloco (mb_type)

O tipo do macrobloco indica qual o método de predição adotado naquele macrobloco.

Blocos Codificados (Coded Block Pattern)

Indica quais blocos de um macrobloco contém coeficientes codificados.

Parâmetro do Quantizador (Quantiser Parameter, QP)

Transmitido como um valor delta a partir do QP anterior.

Tabela 5.3 – Exemplo de parâmetros a serem codificados.
Como regra, tudo que estiver acima da camada de fatia é codificado usando Exp-Golomb ou códigos binários. Enquanto que tudo que estiver na camada de fatia e abaixo é codificado usando CAVLC ou CABAC, dependendo do modo de codificação por entropia.


      1. 5.5.2 CAVLC


A codificação CAVLC do H.264 é usada para codificar os resíduos dos coeficientes da transformada, por meio de modificação em algumas técnicas de codificação por entropia, tal como Huffman e RLE (Run Length Encoding).

A idéia por trás do RLE é: se um símbolo X ocorre N vezes consecutivas, substitua as N ocorrências pelo par de símbolos XN [30]. As N ocorrências consecutivas do símbolo X são chamadas de carreira (run-length) de X. O H.264 herdou do JPEG um conceito onde o RLE é utilizado para codificação de coeficientes consecutivos com valor zero [28][3].

A Codificação de Largura Variável Adaptável ao Contexto (CAVLC) é baseada na codificação VLC, mas ao invés de manter uma tabela de mapeamento de símbolos fixa, como ocorre na VLC tradicional, ela usa a comutação de tabelas explorando a redundância entre o símbolo sendo codificado e os já codificados [36], por isso é chamada de VLC Adaptável ao Contexto.

Independente do modo de predição adotado, o H.264 codifica individualmente os blocos de tamanho 4x4, da mesma forma como esse é o tamanho de bloco usado pela transformada e quantização. Por exemplo, na predição Intra 16x16, as funções writeCoeff16x16 e writeChromaCoeff do código de referência [2] são usadas para codificação por entropia dos componentes luma e chroma, respectivamente. Cada uma dessas funções chama uma vez writeCoeff4x4_CAVLC para codificar os coeficientes DC e n vezes para codificar os coeficientes AC.

A CAVLC foi projetada para tirar proveito de muitas características dos blocos quantizados 4x4 [1]:



  • Após a predição, transformada e quantização, os blocos contém muitos zeros. A CAVLC usa RLE para representar seqüências de zeros de forma compacta;

  • Os coeficientes diferentes de zero de mais alta freqüência (mais distantes do coeficiente DC) após a reordenação zig-zag são geralmente ±1. A CAVLC codifica esses coeficientes (trailing ones) de forma compacta;

  • Há uma forte relação entre a quantidade de coeficientes diferentes de zero em blocos vizinhos, dessa forma, o número de coeficientes é codificado usando uma tabela cuja escolha depende do número de coeficientes diferentes de zero nos blocos vizinhos. Daí vem a Context Adaptive da sigla CAVLC;

  • O nível (magnitude) dos coeficientes diferentes de zero tende a ser maior no início do vetor reordenado (próximo ao coeficiente DC) e menor em direção às freqüências mais altas. Assim, a CAVLC tira vantagem disso escolhendo a tabela VLC para o nível de acordo com as magnitudes recém codificadas.

No código desenvolvido neste trabalho, o método writeResidualBlock é responsável pela codificação por entropia dos blocos 4x4 residuais e equivale ao writeCoeff4x4_CAVLC do código de referência.



        1. 5.5.2.1 Codificação do número de coeficientes diferentes de zero e 1s em carreira

Por meio do código coeff_token, no decodificador, é possível obter o número de coeficientes diferentes de zero (TotalCoeffs) e a quantidade de coeficientes de valor 1 no final do vetor (TrailingOnes).

A quantidade de coeficientes diferentes de zero (TotalCoeffs) pode ser de 0 (indicando que não existe nenhum coeficiente diferente de zero no bloco 4x4) a 16 (todos os coeficientes são diferente de zero). E o número de TrailingOnes pode ir de 0 a 3.

Existem quatro tabelas VLC para codificar coeff_token, e a escolha depende do número de coeficientes diferentes de zero nos blocos vizinhos. Cada tabela possui os códigos VLC com menor largura em uma determinada faixa. A tabela 1 dedica seus códigos VLC com menor largura para TotalCoeffs pequenos, ou seja, para blocos com pouco número de coeficientes diferentes de zero, enqunato a tabela 3 dedica seus códigos VLC com menor largura aos blocos com grande quantidade de coeficientes diferentes de zero. A tabela 4 possui códigos VLC de largura fixa.

O método writeCoeffToken da classe CAVLC escreve o coeff_token a partir do TotalCoeffs e do TrailingOnes.

        1. 5.5.2.2 Codificação do sinal de cada 1 em carreira

O sinal de até três coeficientes com valor 1 é codificado, sendo usado um bit para cada sinal. A ordem de codificação desses sinais é invertida, começando pelo último coeficiente 1 e terminando no terceiro, se houver.

Dado o código binária contendo o sinal dos TrailingOnes e a quantidade deles, o método writeTrailingOnesSignFlag da classe CAVLC escreve esse código no fluxo de saída.

        1. 5.5.2.3 Codificação da magnitude dos coeficientes diferentes de zero remanescentes

A magnitude e o sinal dos coeficientes diferentes de zero restantes são codificados em ordem inversa, iniciando pelo coeficiente logo após o último TrailingOnes e indo em direção ao coeficiente DC. Note que os coeficientes com valor 1 que não fazem parte dos TrailingOnes são codificados nesta etapa.

A partir da magnitude (nível) e do tamanho do nível anterior, o método writeLevel da classe CAVLC codifica a magnitude de um coeficiente. Em [1] é descrito o algoritmo para codificação do nível dos coeficientes diferentes de zero remanescentes e em [36] é ilustrado um exemplo da aplicação desse algoritmo.

        1. 5.5.2.4 Codificação do número de zeros antes do último coeficiente

A quantidade de zeros que precedem o coeficiente de mais alta freqüência (mais distante do DC) é codificado por meio do método writeTotalZeros da classe CAVLC. O par totalZeros e totalCoeff define uma palavra de código em uma tabela. A maioria dos blocos contém coeficientes diferentes de zero no começo do vetor ordenado. Dessa forma, a seqüência de zeros que aparecem no início do vetor não precisa ser codificada, sendo indicada nesta etapa.

Esse método recebe ainda um terceiro valor, que indica a quantidade de coeficientes no vetor, pois existem tabelas distintas para codificar vetores com 4 ou 16 coeficientes.

        1. 5.5.2.5 Codificação das seqüências de zeros antes de cada coeficiente diferente de zero

O método writeRunBefore da classe CAVLC é chamado para escrever o número de zeros que precedem cada coeficiente diferente de zero. Esse método aceita um par de argumentos, os quais são os índices dentro de uma tabela VLC, que indicam qual palavra de código será usada para codificar o run before.

Iniciando a partir do coeficiente de mais alta freqüência (mais distante do DC), o método writeRunBefore é chamado recebendo runBefore (o número de zeros entre este e o próximo coeficiente diferente de zero) e zerosLeft (quantos zeros ainda restam no total).




1   ...   5   6   7   8   9   10   11   12   ...   24


©livred.info 2017
enviar mensagem

    Página principal