Como funciona um codec de vídeo. Parte 2. O que, para que, como

Primeira parte: Fundamentos do trabalho com vídeo e imagens

Como funciona um codec de vídeo. Parte 2. O que, para que, como

O quê? Um codec de vídeo é uma parte do software/hardware que comprime e/ou descomprime vídeo digital.

Para que serve? Apesar de certas limitações tanto na largura de banda quanto
na quantidade de espaço para armazenamento, o mercado exige vídeos de qualidade cada vez maior. Você se lembra de como no post anterior calculamos o mínimo necessário para 30 quadros por segundo, 24 bits por pixel, com resolução de 480×240? Obtivemos 82,944 Mbit/s sem compressão. A compressão é até agora a única forma de transmitir HD/FullHD/4K para telas de televisão e na Internet. Como isso é alcançado? Vamos dar uma olhada breve nos métodos principais.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

A tradução foi feita com o apoio da empresa EDISON Software.

Nós estamos envolvidos na integração de sistemas de vigilância por vídeo, além de desenvolvendo um microtomógrafo.

Codec vs Contêiner

Um erro comum entre iniciantes é confundir codec de vídeo digital e contêiner de vídeo digital. Um contêiner é um formato. Uma embalagem que contém metadados de vídeo (e, possivelmente, áudio). O vídeo comprimido pode ser visto como a carga útil do contêiner.

Normalmente, a extensão do arquivo de vídeo indica seu tipo de contêiner. Por exemplo, um arquivo video.mp4 é provavelmente um contêiner MPEG-4 Parte 14, e um arquivo chamado video.mkv é, mais provavelmente, uma matryoshka. Para ter certeza do codec e do formato do contêiner, você pode usar FFmpeg ou MediaInfo.

Um pouco de história

Antes de avançarmos para Como?, vamos nos aprofundar um pouco na história para entender melhor alguns codecs antigos.

Codec de vídeo H.261 apareceu em 1990 (tecnicamente — em 1988) e foi criado para trabalhar com uma taxa de transmissão de 64 Kbit/s. Já utilizava ideias como subamostragem de cor, macroblocos, etc. Em 1995, o padrão do codec de vídeo H.263, que se desenvolveu até 2001.

Em 2003, a primeira versão do H.264/AVCfoi finalizada. No mesmo ano, a empresa 'TrueMotion' lançou seu codec de vídeo gratuito que comprime vídeo com perdas chamado VP3. Em 2008, o Google comprou essa empresa, lançando VP8 no mesmo ano. Em dezembro de 2012, o Google lançou VP9, e ele é suportado por cerca de ¾ do mercado de navegadores (incluindo dispositivos móveis).

AV1 — é um novo codec de vídeo gratuito de código aberto, desenvolvido pelo Aliança por Mídias Abertas (AOMedia), que inclui empresas renomadas como: Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel e Cisco. A primeira versão do codec 0.1.0 foi publicada em 7 de abril de 2016.

O nascimento do AV1

No início de 2015, o Google estava trabalhando no VP10, a Xiph (que pertence à Mozilla) estava trabalhando no Daala, e a Cisco desenvolveu seu codec de vídeo gratuito chamado Thor.

Em seguida A MPEG LA anunciou inicialmente limites anuais para HEVC (H.265) e uma taxa, 8 vezes superior à do H.264, mas logo mudaram as regras novamente:

sem limite anual,
uma taxa sobre o conteúdo (0,5% da receita) e
um custo por unidade de produto aproximadamente 10 vezes superior ao do H.264.

A Aliança para Mídias Abertas foi formada por empresas de diferentes setores: fabricantes de hardware (Intel, AMD, ARM, Nvidia, Cisco), provedores de conteúdo (Google, Netflix, Amazon), criadores de navegadores (Google, Mozilla) e outros.

As empresas tinham um objetivo comum — um codec de vídeo sem royalties. Então surgiu AV1 com uma licença de patente muito mais simples. Timothy B. Terriberry fez uma apresentação impressionante, que se tornou a fonte do conceito atual do AV1 e seu modelo de licença.

Você ficará surpreso ao saber que é possível analisar o codec AV1 através do navegador (os interessados podem acessar aomanalyzer.org).

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Codec Universal

Vamos revisar os principais mecanismos que fundamentam o codec de vídeo universal. A maioria desses conceitos é útil e é utilizada em codecs modernos, como VP9, AV1 e HEVC. Aviso que muitas coisas explicadas serão simplificadas. Às vezes, exemplos reais (como no caso do H.264) serão utilizados para demonstrar as tecnologias.

Passo 1 — Divisão da imagem

O primeiro passo é dividir o quadro em várias seções, subseções e assim por diante.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Por quê? Existem várias razões. Quando fragmentamos a imagem, é possível prever um vetor de movimento com mais precisão, utilizando seções pequenas para partes em movimento pequeno. Já para fundos estáticos, é possível utilizar seções maiores.

Normalmente, os codecs organizam essas seções em segmentos (ou fragmentos), macroblocos (ou blocos de árvore de codificação) e várias subseções. O tamanho máximo dessas seções varia, o HEVC define 64×64, enquanto o AVC usa 16×16, e as subseções podem ser divididas em tamanhos de 4×4.

Lembra das variedades de quadros do artigo anterior?! Isso também pode ser aplicado aos blocos, então, podemos ter fragmento I, bloco B, macrobloco P, etc.

Para quem deseja praticar — veja como a imagem é dividida em seções e subseções. Para isso, você pode usar o que já foi mencionado no artigo anterior. Intel Video Pro Analyzer (o que é pago, mas tem uma versão de teste gratuita com limite nos primeiros 10 quadros). Aqui estão analisadas as seções. VP9:

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Passo 2 — previsão

Assim que tivermos as seções, podemos elaborar previsões astrológicas com elas. Para INTER-previsão é necessário transmitir os vetores de movimento e o resto, enquanto para a INTRA-previsão é transmitida a direção da previsão e o resto.

Passo 3 — transformação

Depois de obtermos o bloco residual (seção prevista → seção real), podemos transformá-lo de maneira a saber quais pixels podem ser descartados, mantendo a qualidade geral. Existem algumas transformações que garantem um comportamento preciso.

Embora existam outros métodos, vamos considerar mais detalhadamente a transformação discreta do cosseno (DCT — da transformação discreta do cosseno). As principais funções da DCT:

  • Transforma blocos de pixels em blocos de coeficientes de frequência de tamanho uniforme.
  • Compacta a potência, ajudando a eliminar a redundância espacial.
  • Garante a reversibilidade.

Em 2 de fevereiro de 2017, Cintra R.J. e Bayer F.M. publicaram um artigo sobre uma transformação semelhante à DCT para compressão de imagens que requer apenas 14 adições.

Não se preocupe se não entender as vantagens de cada item. Agora, vamos ver exemplos específicos que demonstram seu real valor.

Vamos pegar um bloco de pixels de 8×8:

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Este bloco é renderizado na seguinte imagem de 8 por 8 pixels:

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Aplicamos a DCT a este bloco de pixels e obtemos um bloco de coeficientes com tamanho 8×8:

Como funciona um codec de vídeo. Parte 2. O que, para que, como

E se renderizarmos este bloco de coeficientes, obteremos a seguinte imagem:

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Como podemos ver, isso não se parece com a imagem original. É possível notar que o primeiro coeficiente difere muito dos demais. Esse primeiro coeficiente é conhecido como coeficiente DC, que representa todas as amostras na matriz de entrada, algo semelhante à média.

Este bloco de coeficientes possui uma propriedade interessante: ele separa os componentes de alta frequência dos de baixa frequência.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Na imagem, a maior parte da potência está concentrada em frequências mais baixas. Portanto, se convertermos a imagem em seus componentes de frequência e descartarmos os coeficientes de frequência mais alta, podemos reduzir a quantidade de dados necessária para descrever a imagem, sem sacrificar muito a qualidade.

Frequência se refere à rapidez com que o sinal muda.

Vamos tentar aplicar o conhecimento obtido no exemplo de teste, convertendo a imagem original em sua frequência (bloco de coeficientes), utilizando DCT, e depois descartando parte dos coeficientes menos importantes.

Primeiro, vamos converter isso para a área de frequência.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Em seguida, descartamos parte (67%) dos coeficientes, principalmente a parte inferior direita.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Finalmente, reconstruímos a imagem a partir deste bloco de coeficientes descartados (lembre-se, isso deve ser reversível) e comparamos com o original.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Podemos ver que ela se assemelha à imagem original, mas há muitas diferenças em relação ao original. Descartamos 67,1875% e ainda assim obtivemos algo que lembra a fonte original. Poderíamos ter descartado os coeficientes de maneira mais pensada para obter uma imagem de qualidade ainda melhor, mas isso já é um próximo tópico.

Cada coeficiente é formado usando todos os pixels.

Importante: cada coeficiente não se traduz diretamente em um único pixel, mas representa uma soma ponderada de todos os pixels. Este impressionante gráfico mostra como calcular o primeiro e o segundo coeficiente usando pesos únicos para cada índice.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Você também pode tentar visualizar a DCT, observando a formação simples de uma imagem a partir dela. Por exemplo, aqui está o símbolo A, formado usando cada peso de coeficiente:

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Passo 4 – quantização

Depois que descartamos alguns coeficientes no passo anterior, na última etapa (transformação), realizamos uma forma especial de quantização. Nesta fase, é aceitável perder informação. Ou, de forma mais simples, vamos quantizar os coeficientes para alcançar compressão.

Como podemos quantizar um bloco de coeficientes? Um dos métodos mais simples é a quantização uniforme, onde pegamos o bloco, dividimos por um valor (por 10) e arredondamos o resultado.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Podemos reverter esse bloco de coeficientes? Sim, podemos, multiplicando pelo mesmo valor pelo qual dividimos.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Esse abordagem não é a melhor, pois não leva em consideração a importância de cada coeficiente. Poderíamos usar uma matriz de quantização em vez de um único valor, e essa matriz poderia aproveitar a propriedade DCT, quantizando a maioria dos quadrantes inferiores direitos e uma minoria dos superiores esquerdos.

Etapa 5 — codificação de entropia

Depois de quantizarmos os dados (blocos de imagem, fragmentos, quadros), ainda podemos compactá-los sem perdas. Existem muitos métodos algorítmicos para compressão de dados. Vamos apresentar brevemente alguns deles; para um entendimento mais profundo, você pode ler o livro "Understanding Compression: Data Compression for Modern Developers".Understanding Compression: Data Compression for Modern Developers»).

Codificação de vídeo com VLC

Suponha que temos um fluxo de símbolos: a, e, r e t. A probabilidade (dentro de 0 a 1) de quão frequentemente cada símbolo aparece no fluxo é apresentada nesta tabela.

aert
Probabilidade0,30,30,20,2

Podemos atribuir códigos binários únicos (preferencialmente pequenos) aos símbolos mais prováveis, e códigos maiores aos menos prováveis.

aert
Probabilidade0,30,30,20,2
Código binário0101101110

Compactamos o fluxo, supondo que ao final gastaremos 8 bits por símbolo. Sem compressão, seriam necessários 24 bits por símbolo. Se substituirmos cada símbolo pelo seu código, há uma economia!

O primeiro passo é a codificação do símbolo e, que é igual a 10, e o segundo símbolo é a, que é adicionado (não de forma matemática): [10] [0], e finalmente o terceiro símbolo t, que torna nosso fluxo de bits compactado final igual a [10] [0] [1110] ou 1001110, o que requer apenas 7 bits (3,4 vezes menos espaço do que o original).

Observe que cada código deve ser um código único com prefixo. O algoritmo de Huffman ajudará a encontrar esses números. Embora esse método não esteja isento de falhas, existem codecs de vídeo que ainda oferecem esse método algorítmico para compressão.

Tanto o codificador quanto o decodificador devem ter acesso à tabela de símbolos com seus códigos binários. Portanto, também é necessário enviar no input essa tabela.

Codificação aritmética

Suponha que temos um fluxo de símbolos: a, e, r, s e t, e suas probabilidades são apresentadas nesta tabela.

aerst
Probabilidade0,30,30,150,050,2

Com esta tabela, construiremos intervalos que contêm todos os possíveis símbolos, ordenados pela maior quantidade.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Agora vamos codificar uma sequência de três símbolos: eat.

Primeiro, escolhemos o primeiro símbolo e, que está no subintervalo de 0,3 a 0,6 (não inclusivo). Pegamos esse subintervalo e o dividimos novamente nas mesmas proporções que antes, mas agora para este novo intervalo.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Vamos continuar codificando nossa sequência eat. Agora pegamos o segundo símbolo a, que está no novo subintervalo de 0,3 a 0,39, e depois pegamos nosso último símbolo t e, repetindo o mesmo processo, obtemos o último subintervalo de 0,354 a 0,372.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Só precisamos escolher um número no último subintervalo de 0,354 a 0,372. Vamos escolher 0,36 (mas poderíamos escolher qualquer outro número nesse subintervalo). Só com esse número conseguiremos recuperar nossa sequência original. É como se estivéssemos desenhando uma linha dentro dos intervalos para codificar nossa sequência.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

A operação reversa (ou seja, decodificação) é igualmente simples: com nosso número 0,36 e nosso intervalo original, podemos iniciar o mesmo processo. Mas agora, usando esse número, identificamos a sequência codificada com esse número.

Com o primeiro intervalo, notamos que nosso número corresponde à fatia, portanto, esse é nosso primeiro símbolo. Agora, novamente, dividimos esse subintervalo, realizando o mesmo processo que antes. Aqui podemos notar que 0,36 corresponde ao símbolo a, e após repetir o processo, chegamos ao último símbolo t (formando nossa sequência codificada original. eat).

Para tanto o codificador quanto o decodificador, deve haver disponível uma tabela de probabilidades dos símbolos, por isso é necessário enviar também ela nos dados de entrada.

Bastante elegante, não é? Quem quer que tenha concebido essa solução era incrivelmente inteligente. Alguns codecs de vídeo usam essa técnica (ou, de qualquer forma, a oferecem como uma opção).

A ideia é comprimir um fluxo de bits quantizados sem perdas. Certamente, este artigo não abrange toneladas de detalhes, razões, compromissos, etc. Mas você, se for um desenvolvedor, deve saber mais. Novos codecs tentam usar diferentes algoritmos de codificação de entropia, como ANS.

Passo 6 - formato de fluxo de bits

Depois de fazer tudo isso, o que resta é descompactar os quadros comprimidos no contexto dos passos executados. É necessário informar explicitamente o decodificador sobre as decisões tomadas pelo codificador. Todas as informações necessárias devem ser fornecidas ao decodificador: profundidade de bits, espaço de cor, resolução, informações de previsões (vetores de movimento, previsão INTER direcionada), perfil, nível, taxa de quadros, tipo de quadro, número do quadro e muito mais.

Faremos uma breve introdução ao fluxo de bits H.264. Nosso primeiro passo é criar um fluxo de bits H.264 mínimo (o FFmpeg, por padrão, adiciona todos os parâmetros de codificação, como SEI NAL — discutiremos isso mais adiante). Podemos fazer isso usando nosso próprio repositório e FFmpeg.

.\/s\/ffmpeg -i \/files\/i\/minimal.png -pix_fmt yuv420p \/files\/v\/minimal_yuv420.h264

Este comando gerará um fluxo de bits bruto H.264 com um quadro, resolução 64×64, no espaço de cor YUV420. Usaremos a seguinte imagem como quadro.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Fluxo de bits H.264

Padrão AVC (H.264) define que as informações serão enviadas em macroquadros (no sentido de rede), chamados de NAL (este é um nível de abstração de rede). O principal objetivo do NAL é fornecer uma representação "amigável à rede" do vídeo. Este padrão deve funcionar em televisores (com base em fluxos), na internet (com base em pacotes).

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Há um marcador de sincronização para determinar os limites dos elementos NAL. Cada marcador de sincronização contém um valor 0x00 0x00 0x01, exceto o primeiro, que é igual a 0x00 0x00 0x00 0x01. Se executarmos hexdump para o fluxo de bits H.264 gerado, identificaremos pelo menos três padrões NAL no início do arquivo.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Como mencionado, o decodificador deve saber não apenas os dados da imagem, mas também os detalhes do vídeo, quadro, cores, parâmetros utilizados e muito mais. O primeiro byte de cada NAL determina sua categoria e tipo.

Identificador do tipo NALDescrição
0Tipo desconhecido
1Fragmento de imagem codificado sem IDR
2Seção de dados codificada do slice A
3Seção de dados codificada do slice B
4Seção de dados codificada do slice C
5 Fragmento IDR codificado da imagem IDR
6Informações adicionais sobre a extensão SEI
7Conjunto de parâmetros de sequência SPS
8Conjunto de parâmetros de imagem PPS
9Delimitador de acesso
10Fim da sequência
11Fim do fluxo
……

Normalmente, o primeiro NAL do fluxo de bits é SPS. Este tipo de NAL é responsável por informar sobre variáveis gerais de codificação, como perfil, nível, resolução, entre outros.

Se pularmos o primeiro marcador de sincronização, podemos decodificar o primeiro byte para saber qual tipo de NAL é o primeiro.

Por exemplo, o primeiro byte após o marcador de sincronização é 01100111, onde o primeiro bit (0) está no campo forbidden_zero_bit. Os próximos 2 bits (11) nos informam o campo nal_ref_idc, que indica se este NAL é um campo de referência ou não. E os outros 5 bits (00111) nos informam o campo nal_unit_type, neste caso, é um bloco SPS (7) NAL.

O segundo byte (binário=01100100, hex=0x64, dec=100) no NAL SPS é o campo profile_idc, que mostra o perfil que o codificador usou. Neste caso, foi utilizado o perfil alto restrito (ou seja, perfil alto sem suporte para o segmento B bidirecional).

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Se examinarmos as especificações do fluxo de bits H.264 para NAL SPS, encontraremos muitos valores para o nome do parâmetro, categoria e descrição. Por exemplo, vamos olhar os campos pic_width_in_mbs_minus_1 e pic_height_in_map_units_minus_1.

Nome do parâmetroCategoriaDescrição
pic_width_in_mbs_minus_10ue(v)
pic_height_in_map_units_minus_10ue(v)

Se realizarmos algumas operações matemáticas com os valores desses campos, obteremos a resolução. Podemos representar 1920 x 1080 usando pic_width_in_mbs_minus_1 com o valor 119 ((119 + 1) * macroblock_size = 120 * 16 = 1920). Novamente, economizando espaço, em vez de codificar 1920, fizemos isso com 119.

Se continuarmos verificando nosso vídeo criado em formato binário (por exemplo: xxd -b -c 11 v/minimal_yuv420.h264), podemos ir para o último NAL, que é o próprio quadro.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Aqui vemos seus primeiros 6 valores byte: 01100101 10001000 10000100 00000000 00100001 11111111. Sabendo que o primeiro byte indica o tipo de NAL, neste caso (00101) é um fragmento IDR (5), e então podemos investigar mais:

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Usando as informações da especificação, podemos decodificar o tipo de fragmento (slice_type) e o número do quadro (frame_num) entre outros campos importantes.

Para obter os valores de alguns campos (ue(v), me(v), se(v) ou te(v), precisamos decodificar o fragmento, usando um decodificador especial baseado em código exponencial de Golomb. Este método é muito eficaz para codificar valores de variáveis, especialmente quando há muitos valores padrão.

Valores slice_type e frame_num os valores deste vídeo são 7 (fragmento I) e 0 (primeiro quadro).

O fluxo de bits pode ser considerado um protocolo. Se você deseja saber mais sobre o fluxo de bits, deve consultar a especificação ITU H.264. Aqui está um diagrama que mostra onde os dados da imagem estão (YUV em formato comprimido).

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Você pode explorar outros fluxos de bits, como VP9, H.265 (HEVC) ou até mesmo nosso novo melhor fluxo de bits AV1. Todos eles são semelhantes? Não, mas entendendo pelo menos um — é muito mais fácil compreender os demais.

Quer praticar? Explore o fluxo de bits H.264

Você pode gerar um vídeo de quadro único e usar o MediaInfo para analisar o fluxo de bits H.264. De fato, nada impede até mesmo olhar o código-fonte que analisa o fluxo de bits H.264 (AVC).

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Para prática, você pode usar o Intel Video Pro Analyzer (eu já mencionei que este software é pago, mas há uma versão gratuita de teste com limite de 10 quadros?).

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Visão geral

É importante notar que muitos codecs modernos utilizam o mesmo modelo que acabamos de estudar. Aqui, vamos dar uma olhada no fluxograma do codec de vídeo Thor. Ele contém todos os passos que passamos. O objetivo desta nota é fazer com que você, pelo menos, entenda melhor as inovações e a documentação dessa área.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Anteriormente, calculamos que seriam necessários 139 GB de espaço em disco para armazenar um arquivo de vídeo de uma hora a 720p e 30 fps. Se usar os métodos que discutimos neste artigo (previsões inter-quadro e intra-quadro, transformação, quantização, codificação de entropia, etc.), é possível alcançar uma qualidade de vídeo bastante satisfatória, ocupando apenas 367,82 MB, em vez dos 139 GB de memória.

Como o H.265 alcança um melhor grau de compressão do que o H.264?

Agora que sabemos mais sobre como os codecs funcionam, é mais fácil entender como novos codecs podem fornecer resoluções mais altas com menos bits.

Ao comparar AVC e HEVC, não se deve esquecer que quase sempre é uma escolha entre maior carga na CPU e grau de compressão.

HEVC tem mais opções de seções (e subseções) do que AVC, mais direções internas de previsão, codificação de entropia aprimorada e muito mais. Todas essas melhorias tornaram H.265 capaz de compactar 50% mais do que H.264.

Como funciona um codec de vídeo. Parte 2. O que, para que, como

Primeira parte: Fundamentos do trabalho com vídeo e imagens

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster