【H.264/AVC视频编解码技术详解】五. H.264的码流封装格式

简介: 《H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.

《H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看!

“纸上得来终觉浅,绝知此事要躬行”,只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会!

链接地址:H.264/AVC视频编解码技术详解

本节视频免费


H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流。对于不同的应用场景,NAL规定了一种通用的格式适应不同的传输封装类型。通常NAL Unit的传输格式分两大类:字节流格式RTP包格式

  • 字节流格式:字节流格式在H.264标准的协议文档中在Annex B中规定,是大多数编码器实现的默认输出格式。字节流格式以连续的bit字节的形式传输码流,因此必须从码流中获取NAL Unit。方法是在码流中识别NAL Unit的识别码:0x00 00 00 01或0x 00 00 01。这一系列以使用流格式的H.264码流为主
  • RTP包格式:包格式方法将NAL Unit按照RTP数据包的格式封装。使用RTP包格式不需要额外的分割识别码,在RTP包的封装信息中有相应的数据长度信息。此种封装格式在标准协议文档中没有明确规定,但在JM Decoder中做了一定处理。通常可以在NAL Unit的起始位置用一个固定长度的长度码表示整个NAL Unit的长度。

流格式的H.264码流的结构如下图所示:

NAL Unit的字节流格式:

  • leading_zero_8bits:在第一个NAL单元之前的前缀0字节;
  • zero_byte:一个字节的0字符;
  • start_code_prefix_one_3bytes:3个字符的起始前缀符,值为0x 00 00 01,与zero_byte共同构成一个0x 00 00 00 01的前缀符;
  • nal_unit:表示一个NAL Unit的比特位;
  • trailing_zero_8bits:结束0字符;

对于字节流格式的H.264码流,从原始码流中读取NAL Unit的方法为检测两个起始码0x 00 00 01或0x 00 00 00 01之间的数据即可。

下面给出一个简单的提取NAL UNIT的参考程序:

// FindNALContent.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

typedef unsigned char uint8;
using namespace std;

static int find_nal_prefix(FILE **pFileIn, vector<uint8> &nalBytes)
{
    FILE *pFile = *pFileIn;
    /*
    00 00 00 01 x x x x x x 00 00 00 01
    */
    uint8 prefix[3] = { 0 };
    uint8 fileByte;
    /*
    [0][1][2] = {0 0 0} -> [1][2][0] ={0 0 0} -> [2][0][1] = {0 0 0}
    getc() = 1 -> 0 0 0 1
    [0][1][2] = {0 0 1} -> [1][2][0] ={0 0 1} -> [2][0][1] = {0 0 1}
    */

    nalBytes.clear();

    int pos = 0, getPrefix = 0;
    for (int idx = 0; idx < 3; idx++)
    {
        prefix[idx] = getc(pFile);
        nalBytes.push_back(prefix[idx]);
    }

    while (!feof(pFile))
    {
        if ((prefix[pos % 3] == 0) && (prefix[(pos + 1) % 3] == 0) && (prefix[(pos + 2) % 3] == 1))
        {
            //0x 00 00 01 found
            getPrefix = 1;
            nalBytes.pop_back();
            nalBytes.pop_back();
            nalBytes.pop_back();
            break;
        } 
        else if ((prefix[pos % 3] == 0) && (prefix[(pos + 1) % 3] == 0) && (prefix[(pos + 2) % 3] == 0))
        {
            if (1 == getc(pFile))
            {
                //0x 00 00 00 01 found
                getPrefix = 2;
                nalBytes.pop_back();
                nalBytes.pop_back();
                nalBytes.pop_back();
                break;
            }
        }
        else
        {
            fileByte = getc(pFile);
            prefix[(pos++) % 3] = fileByte;
            nalBytes.push_back(fileByte);
        }
    }

    return getPrefix;
}

int _tmain(int argc, _TCHAR* argv[])
{
    FILE *pFile_in = NULL;
    _tfopen_s(&pFile_in, argv[1], _T("rb"));
    if (!pFile_in)
    {
        printf("Error: Opening input file failed.\n");
    }

    vector<uint8> nalBytes;
    find_nal_prefix(&pFile_in, nalBytes);
    find_nal_prefix(&pFile_in, nalBytes);

    for (int idx = 0; idx < nalBytes.size(); idx++)
    {
        printf("%x ", nalBytes.at(idx));
    }
    printf("\n");

    find_nal_prefix(&pFile_in, nalBytes);

    for (int idx = 0; idx < nalBytes.size(); idx++)
    {
        printf("%x ", nalBytes.at(idx));
    }
    printf("\n");
    find_nal_prefix(&pFile_in, nalBytes);

    for (int idx = 0; idx < nalBytes.size(); idx++)
    {
        printf("%x ", nalBytes.at(idx));
    }
    printf("\n");

    fclose(pFile_in);
    return 0;
}
目录
相关文章
|
4月前
|
编解码 监控 网络协议
如何使用FFmpeg实现RTSP推送H.264和H.265(HEVC)编码视频
本文详细介绍了如何使用FFmpeg实现RTSP推送H.264和H.265(HEVC)编码视频。内容涵盖环境搭建、编码配置、服务器端与客户端实现等方面,适合视频监控系统和直播平台等应用场景。通过具体命令和示例代码,帮助读者快速上手并实现目标。
1001 6
|
7月前
|
编解码 应用服务中间件 开发工具
如何在RTMP推送端和RTMP播放端支持Enhanced RTMP H.265(HEVC)
时隔多年,在Enhancing RTMP, FLV With Additional Video Codecs And HDR Support(2023年7月31号正式发布)官方规范出来之前,如果RTMP要支持H.265,大家约定俗成的做法是扩展flv协议,CDN厂商携手给出的解决方案是给flv的videotag CodecID增加一个新类型(12)来表示h265(hevc),和h264不同的地方是要解析HEVCDecoderConfigurationRecord,从HEVCDecoderConfigurationRecord中解析出vps, sps, pps. 有了vps, sps, pps,
148 6
|
10月前
|
存储 编解码 自然语言处理
常见的音频与视频格式
常见的音频格式有 WAV、MP3、FLAC、APE、AAC、OGG 等,常见的视频格式有 MP4、AVI、MOV、WMV、MKV、FLV、3GP、MPEG 等,它们在兼容性、文件大小、画质等方面各有特点。
|
编解码 开发工具 开发者
如何支持RTSP播放H.265(HEVC)流
随着H.265的普及,越来越多的开发者希望大牛直播SDK能支持低延迟的RTSP H.265播放,并分享相关经验: 实现思路: 对rtsp来说,要播放h265只要正确解析sdp和rtp包即可. 下面对这些相关内容做一些介绍.
510 1
|
编解码 算法
白话H.265/HEVC和H.264/AVC编码结构
写在前面 在信息化时代,视频技术和应用的发展,特别是高清(HD)、超高清(UHD)、多视点(MultiView)视频、VR/AR技术的兴起,海量的视频信息已如潮涌般深入到我们工作和生活的方方面面。随着5G通信技术逐渐铺开落地,移动端设备的传输数据量会进一步增加。
2899 0
|
算法 开发者
MPEG 音频 | 学习笔记
快速学习 MPEG 音频,介绍了 MPEG 音频系统机制, 以及在实际应用过程中如何使用。
MPEG 音频 | 学习笔记
|
编解码
H.264 码率设置
一、什么是视频码率 视频码率是视频数据(包含视频色彩量、亮度量、像素量)每秒输出的位数。一般用的单位是kbps。 二、设置视频码率的必要性 在网络视频应用中,视频质量和网络带宽占用是相矛盾的。
1787 0
|
存储 编解码 网络协议
封装格式介绍
音视频封装格式介绍,FLV,MP4,音视频同步
170 0
|
存储 编解码 API
FFmpeg编解码处理4-音频编码
基于 FFmpeg 4.1 版本。
417 0
FFmpeg编解码处理4-音频编码
|
存储 编解码 API
FFmpeg编解码处理3-视频编码
基于 FFmpeg 4.1 版本。
364 0
FFmpeg编解码处理3-视频编码