Optimización del algoritmo SAO para codificación H.265
El nombre completo de SAO es Sample adaptiveoffset, que es un desplazamiento adaptativo de muestreo. Es una tecnología de compresión importante en la especificación de codificación H.265 y se originó a partir de JCTVC-A124 propuesta por Samsung. Los resultados de las pruebas experimentales muestran que la ganancia de compresión de SAO es mucho mayor que la de Deblock y ALF.
La posición del módulo SAO en la estructura del codificador es la siguiente (parte roja):
Figura 1 La posición de SAO en el codificador
SAO en del decodificador La posición es la siguiente (parte roja):
Figura 2 La posición de SAO en el decodificador
Figura 2 La posición de SAO en el codificador
Figura 2 Posición de SAO en el decodificador
Figura 2 Posición de SAO en el decodificador
Figura 2 Posición de SAO en el decodificador es la siguiente:
Desde el flujo En el gráfico se puede ver que SAO y ALF son operaciones en el bucle. Están conectadas a la parte posterior de Deblock. La entrada incluye la imagen YUV original y la salida de Deblock. Los parámetros generados deben estar codificados en entropía. Consulte la Figura 3:
Figura 3 Descripción general del algoritmo SAO
II Introducción al algoritmo SAO
Después de comprimir y descomprimir la imagen, la precisión disminuirá. La fórmula psnr muestra que el cuadrado de la diferencia entre los datos reconstruidos y los datos originales YUV determina psnr. SAO analiza los datos originales y los datos reconstruidos, y realiza operaciones de compensación de compensación en los datos desbloqueados para acercarlos lo más posible al valor de píxel original, logrando así el propósito de mejorar psnr.
Error cuadrático medio:
Relación señal-ruido máxima:
Cómo mejorar el valor PSNR, una idea directa es agregar Los datos reconstruidos desbloqueados se procesa diferencialmente con los datos YUV originales y luego la diferencia se pasa al decodificador para restaurar completamente el YUV. En aplicaciones prácticas, esto dará como resultado una tasa de bits muy alta, que es insuficiente para la compresión.
Para mejorar psnr con sólo un pequeño aumento en la tasa de bits, H.265 crea un equilibrio entre la tasa de bits y psnr. El método específico es el siguiente.
H.265 realiza SAO basado en CTB Al analizar los datos originales y los datos reconstruidos desbloqueados, los píxeles se dividen en tres modos SAO:
La banda de SaoTypeIdx tiene tres píxeles. Los valores de píxeles son: 32, 35, 35: 32, 35, 35, por lo que podemos saber que el valor de píxel promedio de esta banda de frecuencia es (32 35 35)/3 = 34; El desbloqueo contiene tres píxeles, que son 30, 32, 34 y 32 respectivamente. La banda desbloqueada correspondiente contiene tres píxeles, 30, 32 y 34 respectivamente, y su promedio es (30 32 34) /3 = 32, por lo que el promedio de los píxeles originales es 34-32 = 2 más grande que los píxeles reconstruidos, por lo que Puede asignar desplazamiento = 2 a esta banda y agregar 2 a cada valor de píxel de esta banda en el lado del decodificador. Esto garantiza que los píxeles reconstruidos sean los mismos que los originales. Esto garantiza que los píxeles reconstruidos que aparecen en la banda sean iguales al promedio de los píxeles originales. Haga esto para los 32 píxeles y seleccione 4 píxeles consecutivos.
Para el modo de compensación de banda y el modo de compensación de borde, si los parámetros SAO del CTB actual son los mismos que los del CTB izquierdo o superior, los parámetros SAO del CTB actual no se transmiten, sino el izquierdo. o CTB superior se utilizan los parámetros SAO para el CTB anterior.
3. Optimización del algoritmo SAO
1. Algoritmos comúnmente utilizados antes de la optimización:
Para cada píxel dentro del CTB, es necesario calcular: p>
1. Primero, calcule la diferencia entre el valor del píxel original y el valor del píxel reconstruido. La diferencia de cada píxel está representada por la variable offset_value
2. Calcule la diferencia entre el original. valor de píxel y el valor de píxel reconstruido respectivamente, la diferencia de cada píxel está representada por la variable offset_value;
2. De acuerdo con el valor de píxel reconstruido, necesitamos calcular el valor de desplazamiento de cada píxel en. los cinco tipos de BO, EO0, EO1, EO2 y EO3. El valor del subtipo se denomina sao_class, por lo que la matriz cuadrada de 64*64 CTB debe recorrerse 5 veces y el número de visitas es de aproximadamente 5*64*. 64
3. Luego podemos hacer la matriz cuadrada CTB de 64*64. Se cuentan 4096 píxeles de cada tipo en la matriz y el número de visitas es de aproximadamente 5*64*64
> 4. 4096 píxeles cuentan la suma de offset_value de cada tipo y el número de píxeles de cada tipo cnt_of_class. Algoritmo de optimización:
La característica de este algoritmo es desplazar el valor de desplazamiento de cada píxel hacia la izquierda en 12 bits, que es un entero de 32 bits. Los 20 bits superiores son valor de desplazamiento y los 12 bits inferiores son. valor_desplazamiento. _value, un entero de 32 bits, los 20 bits superiores representan el valor de desplazamiento y los 12 bits inferiores representan el número de píxeles. Para cada píxel, los 12 bits inferiores se inicializan a 1. Un bloque CTB de 64*64 con el mismo subtipo SAO tiene como máximo 2^12 píxeles, por lo que los 12 bits inferiores se utilizan para guardar el número de subtipos sin desbordarse, de la siguiente manera:
12 ~ 31 bits ( offset_value)
0 ~ 11 bits (cnt_of_class)
0 ~ 11 bits (cnt_of_class)
0 ~ 11 bits (cnt_of_class)
0 ~ 11 bits (clase cnt_of_class)
Figura 7 Formato de datos compuestos
Esto combina offset_value y cnt_of_class en un entero de 32 bits, de modo que estos dos valores puedan ser acumulado y ejecutado al mismo tiempo, reduciendo así a la mitad el esfuerzo computacional.
Supongamos que el tamaño del bloque CTB es 64*64, el valor de compensación se define como la siguiente matriz:
Offset_value[64][64] = { ... . .. }; donde Cada formato de datos es un formato de datos que cumple con los requisitos
Rec_pixel_ value[64][64] = { .... ...}; p>
BO_class[64][64] = { ... ... } ; Rango de valores 0 ~ 31
EO0_class [64][64] = { ... ... } ; Rango de valores 0 ~ 4
EO1_class[64][64] = { .... } ; Rango de valores 0 ~ 4
EO2_class[64][64] = { . ... } ; Rango de valores 0 ~ 4
EO3_class[64][64] = { ...} ; Rango de valores 0 ~ 4
Definir una matriz:
Int BO_Class [32] = {0};
For(int i = 0; i lt; 64; i)
For(intj = 0; j lt ; 64; j)
{
Int Rec_pixel_value[i][j] gt;
BO_ Class[clase] = Offset_value[i; ] [j];
}
Después de completar la operación anterior, puede separar cada subclase de BO_Class:
For(int i = 0; i lt ; 32; i)
{
valor de compensación = BO_Class[i] gt;
cnt_of_ BO_Class[i] amp; /p>
}
Modo de desplazamiento de borde:
1. Fusione EO0 y EO1 en una matriz: EO0 y EO1 contienen EO0 y EO1 ambos contienen 0 ~ 4 Hay 5 subclases en total, que requieren 3 bits. Para fusionar estas dos subclases, es necesario crear una matriz bidimensional. Los dos subíndices representan los índices de subclase de los dos tipos respectivamente.
Supongamos que el subíndice de la izquierda representa el índice de subcategoría de EO1 y el subíndice de la derecha representa el índice de subcategoría de EO0:
EO_01[8][8]
2. Siga el método anterior para combinar EO2 y EO3 en una matriz:
EO_23[8][8]
3. Complete las siguientes operaciones:
{
Int clase_0 = EO0_clase[i][j];
Int clase_1 = EO1_clase[i][j]
Int desplazamiento = Valor_desplazamiento[i] [j];
EO_01[class_1][class_ 0] = desplazamiento
EO_23[class_3][class_2] = desplazamiento
4. Separe EO0; EO1, EO2 y EO3:
Int EO0[5] = {0}
Int EO1[5] = {0}; [5] = {0} ;
Int EO3[5] = {0}
Para(int i = 0; i lt; 5; i)
For(int J = 0; J lt; 5; J )
EO0[j] = EO_01[i][j]
EO1[i] = EO_01; [i][j];
EO2[j] = EO_23[i][j];
Finalmente, separe el desplazamiento y el recuento para cada clase.
4. Resumen
Después de la optimización, la cantidad de cálculo de la parte de estadísticas de compensación en SAO se reduce a aproximadamente el 25%. Dado que la parte estadística consume el 90% del tiempo de cálculo de todo el módulo SAO, el efecto de optimización del algoritmo es más obvio en la capa C. A nivel de ensamblaje, aunque hay cierto efecto, no es muy obvio porque hay una matriz de 8 * 8 en el medio de la operación, lo que no favorece la paralelización del conjunto de instrucciones multimedia.