Análise de H264

Formato de codificação H264

A função do H.264 é dividida em duas camadas, a camada de codificação de vídeo VCL e a camada de abstração de rede NAL. Os dados VCL são uma saída após o processamento da codificação e representam uma sequência de dados de vídeo compactados e codificados . Quando os dados VCL são transmitidos ou armazenados, esses dados VCL codificados serão mapeados ou encapsulados em unidades NAL .

  • VCL, camada de codificação de vídeo, camada de codificação de vídeo, informações de conteúdo de dados de vídeo puro após a codificação, sem nenhuma informação de cabeçalho redundante;
  • NAL, Network Abstraction Layer, camada de abstração de rede, é responsável por empacotar e enviar de forma adequada durante a transmissão da rede ;

Simplificando, durante a transmissão de dados de vídeo, os dados VCL serão empacotados em unidades básicas NAL para transmitir dados da unidade NAL .

insira a descrição da imagem aqui

NAL

H.264Os principais objetivos de:

  • Alta taxa de compressão de vídeo;
  • Boa afinidade de rede, podendo ser aplicado em diversas redes de transmissão;

NAL, Network Abstraction Layer, é definido da seguinte forma:
:::info
A Network Abstraction Layer faz parte dos padrões de codificação de vídeo H.264/ANC e HEVC (Padrões de codificação de vídeo)
O principal objetivo do NAL é o fornecimento (fornecimento) de um representação de vídeo “compatível com a rede” abordando aplicativos “conversacionais (bidirecionais)” (telefonia com vídeo: videotelefonia) e “sem conversação” (armazenamento, transmissão ou streaming).
padrões de codificação de vídeo
O principal objetivo do NAL é fornecer uma representação de vídeo compatível com a rede, abordando aplicativos bidirecionais (telefonia com vídeo) e unidirecionais (telefonia sem vídeo - armazenamento, transmissão ou reprodução de vídeo).
Comparado com os padrões de codificação de vídeo anteriores, o NAL obteve uma melhoria significativa na flexibilidade de aplicação.
:::
Portanto, NALtrata-se de empacotar VCLos dados para uma melhor transmissão na rede.

unidades NAL

Os dados de vídeo codificados são compactados em NAL units, cada um dos quais NAL unitsé um pacote contendo um número inteiro de bytes. NAL unitO primeiro byte de cada um é header, que contém as informações do tipo de dados. NAL unitA definição da estrutura é orientada packete bitstreamprojetada, com bom desempenho de transmissão de rede.

No quadro de dados H264 real, muitas vezes há (NAL unit)um separador 00 00 00 01 ou 00 00 01delimitador entre os quadros StartCode, que é chamado de início de um quadro. Portanto, uma estrutura NALUoriginal contém três partes:NALU

  • StartCode

  • Cabeçalho NALU

  • NALU Payload (carga de sequência de bytes, RBSP, carga bruta de sequência de bytes)
    insira a descrição da imagem aqui

    NALU Header
    NALU Header é um byte imediatamente após StartCode , e o significado de cada bit é o seguinte:

    insira a descrição da imagem aqui

  • F: bit proibido, proibido, ocupando o primeiro bit do cabeçalho NAL, quando o valor do bit proibido for 1, significa um erro de sintaxe;

  • NRI: Nível de referência, ocupando o segundo e terceiro bits do cabeçalho NAL, quanto maior o valor, mais importante é a unidade NAL;

  • Tipo: tipo de unidade NAL, que ocupa do quarto ao oitavo dígitos do cabeçalho NAL. Os tipos de unidade NAL comuns são os seguintes:
    insira a descrição da imagem aqui

    NAL unitpodem ser classificados em VCLe non-VCL NAL units. Que VCL NAL unitcontém o quadro de dados da imagem de vídeo, non-VCL NAL unitque contém informações adicionais, como informações de conjunto de parâmetros SPSe informações complementares de aprimoramento .PPS(important header data that can apply to a large number of VCL NAL units)SEI(timing information and other supplemental data that may enhance usability of the decoded video signal but are not necessary for decoding the values of the samples in the video pictures)

  • quadros IDR. Um quadro IDR é um quadro I, mas um quadro I não é necessariamente um quadro IDR. Em uma unidade de fluxo de vídeo completa, o primeiro quadro de imagem é um quadro IDR e o quadro IDR é um quadro de atualização forçada. Durante o processo de decodificação, quando um quadro IDR aparece, sps e pps devem ser atualizados para evitar erros no IDR anterior frame Causa sps, pps referem-se a I-frames levando a incorrigível.

  • SEI, Supplemental Enhancement Information, fornece um método para adicionar informações adicionais ao fluxo de vídeo;

  • SPS, Sequence Parameter Set, um conjunto de parâmetros globais de uma sequência de vídeo codificada (Coded Video Sequence) é armazenado no SPS. Portanto, esse tipo salva os parâmetros relacionados à sequência de codificação.

  • PPS, Picture Paramater Set, este tipo salva os parâmetros relacionados à imagem geral.

  • Delimitador AU, o nome completo de AU é Unidade de Acesso, que é uma coleção de uma ou mais NALUs, representando um quadro completo.

Analisar dados H264

De acordo com a H264análise do formato de codificação acima, é possível startcodedistinguir cada um NAL unite, em seguida, analisar NAL unito primeiro byte de cada um para obter NAL unitas NAL Typeinformações de importância e comprimento. O código específico é o seguinte:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum {
    
    
    NALU_TYPE_SLICE = 1,    // 不分区,非IDR图像
    NALU_TYPE_DPA,          // 片分区A
    NALU_TYPE_DPB,          // 片分区B
    NALU_TYPE_DPC,          // 片分区C
    NALU_TYPE_IDR,          // IDR图像中的片
    NALU_TYPE_SEI,         // 补充增强信息单元
    NALU_TYPE_SPS,          // 序列参数集
    NALU_TYPE_PPS,          // 图像参数集
    NALU_TYPE_AUD,          // 分界符
    NALU_TYPE_EOSEQ,        // 序列结束符
    NALU_TYPE_EOSTREAM,     // 码流结束符
    NALU_TYPE_FILL          // 填充
} NaluType;

typedef enum {
    
    
    NALU_PRIORITY_DISPOSABLE = 0,
    NALU_PRIORITY_LOW,
    NALU_PRIORITY_HIGH,
    NALU_PRIORITY_HIGHEST
} NaluPriority;


typedef struct {
    
    
    int pos;        // NALU对应起始码,在文件中的位置
    int codelen;    // 起始码大小
    int header;     // (0) + (priority)2bits + (types)5bits
} Nalu_t;

void fill_typestr(char *type_str, int type) {
    
    
    switch(type) {
    
    
        case NALU_TYPE_SLICE:sprintf(type_str,"SLICE");break;
        case NALU_TYPE_DPA:sprintf(type_str,"DPA");break;
        case NALU_TYPE_DPB:sprintf(type_str,"DPB");break;
        case NALU_TYPE_DPC:sprintf(type_str,"DPC");break;
        case NALU_TYPE_IDR:sprintf(type_str,"IDR");break;
        case NALU_TYPE_SEI:sprintf(type_str,"SEI");break;
        case NALU_TYPE_SPS:sprintf(type_str,"SPS");break;
        case NALU_TYPE_PPS:sprintf(type_str,"PPS");break;
        case NALU_TYPE_AUD:sprintf(type_str,"AUD");break;
        case NALU_TYPE_EOSEQ:sprintf(type_str,"EOSEQ");break;
        case NALU_TYPE_EOSTREAM:sprintf(type_str,"EOSTREAM");break;
        case NALU_TYPE_FILL:sprintf(type_str,"FILL");break;
    }
}

void fill_priostr(char *priostr, int prio) {
    
    
    switch(prio) {
    
    
        case NALU_PRIORITY_DISPOSABLE:sprintf(priostr,"DISPOS");break;
        case NALU_PRIORITY_LOW:sprintf(priostr,"LOW");break;
        case NALU_PRIORITY_HIGH:sprintf(priostr,"HIGH");break;
        case NALU_PRIORITY_HIGHEST:sprintf(priostr,"HIGHEST");break;
    }
}


int startcode_len(unsigned char *buf) {
    
    
    if (buf[0] == 0 && buf[1] == 0) {
    
    
        if (buf[2] == 1) return 3;
        else if(buf[3] == 1) return 4;
    }    
    return -1;
}

void h264_analyse(const char *file) {
    
    
    FILE *fp = fopen(file, "r");
    unsigned char *buf = malloc(30000000); // 根据视频大小设
    Nalu_t *nalu = malloc(sizeof(*nalu));
    memset(nalu, 0, sizeof(Nalu_t));
    
    // 获取文件大小
    fseek(fp, 0, SEEK_END);
    int filesize = ftell(fp);
    rewind(fp);

    // 先读部分数据,解析第一个NALU
    fread(buf, 1, 100, fp);
    nalu->pos = 0;
    nalu->codelen = startcode_len(&buf[nalu->pos]);

    printf("| NUM | CODE |   PRIO |   TYPE  | LEN |\n");

    int cnt = 0;                // nalu个数
    int left = 0, right = 100;  // left表示当前搜索位置,right表示当前文件偏移
    int found, len;             
    while (1) {
    
    
        int headidx = nalu->pos + nalu->codelen;  // NALU header
        nalu->header = buf[headidx];
        // int nForbiddenBit = (nFrameType >> 7) & 0x1;//第1位禁止位,值为1表示语法出错
        // int nReference_idc = (nFrameType >> 5) & 0x03;//第2~3位为参考级别
        // int nType = nFrameType & 0x1f;//第4~8为是nal单元类型
        int type = nalu->header & 0x1F;             // NALU Type
        char type_str[10] = {
    
    0};
        fill_typestr(type_str, type);

        // int prio = (nalu->header & 0x60)>>5;
        int prio = (nalu->header >> 5) & 0x03;
        char prio_str[10] = {
    
    0};
        fill_priostr(prio_str, prio);
        
        // 找到下一个起始码
        found = 0; len = 0;
        left += nalu->codelen + 1;  // 跳过startcode和header
        while (!found) {
    
    
            if (left < right) {
    
    
                if (left + 4 >= filesize) // 防止在函数内数组越界
                    goto clean;
                len = startcode_len(&buf[left++]);
                if (len > 0) found = 1;
            } else {
    
    
                if (right + 100 < filesize) {
    
    
                    fread(&buf[right], 1, 100, fp);
                    right += 100;
                } else {
    
        // 剩余的数据不到100B字节
                    fread(&buf[right], 1, filesize - right, fp);
                    right = filesize;
                }
            }
        }
        int nalulen = left - nalu->pos - nalu->codelen;  // NALU大小,不包括起始码

        printf("|%5d|%6d|%8s|%9s|%5d|\n", cnt, nalu->codelen, prio_str, type_str, nalulen);
        cnt++;
        nalu->codelen = len;
        nalu->pos = left - 1;
    }

clean:
    free(nalu);
    free(buf);
    fclose(fp);
}

int main(int argc, char const* argv[])
{
    
    
    h264_analyse("/opt/nvidia/deepstream/deepstream-6.1/samples/streams/sample_720p.h264"); 
    return 0;
}

O arquivo analisa as informações de cada unidade NAL da seguinte forma:

| NUM | CODE |   PRIO |   TYPE  | LEN |
|    0|     4|  DISPOS|      AUD|    3|
|    1|     4| HIGHEST|      SPS|   26|
|    2|     4| HIGHEST|      PPS|    6|
|    3|     4|  DISPOS|      SEI|  704|
|    4|     4| HIGHEST|      IDR|47583|
|    5|     4|  DISPOS|      AUD|    3|
|    6|     4|    HIGH|    SLICE|25063|
|    7|     4|  DISPOS|      AUD|    3|
|    8|     4|  DISPOS|    SLICE| 8783|
|    9|     4|  DISPOS|      AUD|    3|
|   10|     4|    HIGH|    SLICE| 3004|
|   11|     4|     LOW|         |23386|
|   12|     4|  DISPOS|      AUD|    3|
|   13|     4|  DISPOS|    SLICE| 7633|
...

Ferramenta de análise H264 Elecard StreamEye Tools

O Elecard StreamEye Tools é um conjunto de ferramentas poderosas projetadas para profissionais e prosumidores no campo de compressão de vídeo. O Elecard StreamEye Tools permite ao usuário realizar uma análise profunda e eficaz de sequências de vídeo. O Elecard StreamEye Tools é um conjunto de ferramentas poderosas
, Projetado para profissionais e prosumidores na área de compressão de vídeo. As ferramentas Elecard StreamEye permitem que os usuários realizem análises profundas e eficazes de sequências de vídeo.

Link: https://pan.baidu.com/s/1MUy6rs3MuDW6PUGkhDHy6g?pwd=of07 Código de extração: of07

O kit de ferramentas Elecard StreamEye Tools contém os cinco aplicativos a seguir:
Elecard StreamEye
Elecard YUV Viewer
Elecard Video Quest (avaliador de qualidade)
Elecard Stream Analyzer
Elecard Buffer Analyzer

insira a descrição da imagem aqui

Elecard Stream Analyzer

O Elecard Stream Analyzer é uma ferramenta poderosa projetada para análise de sintaxe (análise gramatical) de fluxos de mídia codificados (dados de mídia codificados) e apresentação do log de análise em um formato legível por humanos. O Stream Analyzer opera com MPEG-1 Video/Audio, MPEG-2 Arquivos de vídeo/áudio, AAC, AC-3 e AVC/H.264 (tipos de dados suportados).

  1. H264Análise NAL unit_
    insira a descrição da imagem aqui


Ao comparar com os resultados da análise de código acima, pode-se ver que o código de análise acima está correto.

  1. H264HEXvisualizador de arquivos
    insira a descrição da imagem aqui

Elecard StreamEyeName

O StreamEye fornece ao usuário uma representação visual dos recursos de vídeo codificados e uma análise da estrutura de fluxo de MPEG-1/2/4 ou AVC/Н.264 Video Elementary Streams (VES), MPEG-1 System Streams (SS), MPEG -2 Fluxos de Programa (PS) e Fluxos de Transporte MPEG-2 (TS)

insira a descrição da imagem aqui

Visão geral de algumas funções:

insira a descrição da imagem aqui

  1. bitrateanalisar

Estado selecionado bitrate, exibe a bitratecurva correspondente

  1. espaço colorido
    insira a descrição da imagem aqui

  2. informações do arquivo
    insira a descrição da imagem aqui

  3. A ferramenta de vetor de movimento
    insira a descrição da imagem aqui

    StreamEye é muito poderosa e pode ser analisada de acordo com suas necessidades.

Acho que você gosta

Origin blog.csdn.net/hello_dear_you/article/details/128599328
Recomendado
Clasificación