FFmpeg简单使用:过滤器 ---- h264_mp4toannexb

H264有两种封装方式:字节流AnnexB格式 AVCC格式。

1. AnnexB格式 ---- 用于实时播放

开始前缀(00000001或000001)+NALU数据  绝大部分编码器的默认输出格式
  一共有两种起始码start_code
   ①3字节0x000001  单帧多slice(即单帧多个NALU)之间间隔
   ②4字节0x00000001 帧之间,或者SPS等之前
4字节类型的开始码在在连续的数据传输中非常有用,因为用字节来对齐、分割流数据,比如:用连续的31个bit0后接一个bit1来分割流数据,是很容易的。

AnnexB格式每个NALU都包含起始码,且通常会周期性的在关键帧之前重复SPS和PPS
  所以解码器可以从视频流随机点开始进行解码,实时的流格式

 2. AVCC格式 ---- 用于存储

AVCC格式不使用起始码作为NALU的分界,这种格式在每个NALU前都加上一个大端格式的前缀(1、2、4字节,代表NALU长度)

所以在解析AVCC格式的时候需要将指定的前缀字节数的值保存在一个头部对象中,这个都通常称为extradata或者sequence header。同时,SPS和PPS数据也需要保存在extradata或者叫’sequence header’中。

3.AVPacket数据格式

AVPacket中的data格式是:size(4个字节)+ nalu + size(4个字节)+ nalu,一个packet可能会存在多个nalu,前面size表示nalu的大小(不包含自身)

图1.

如图1所示,前4个字节表示:第一个nalu大小是0x52d = 1325, 总的pkt的大小是66736。表示存在多个nalu。下一个nalu位置:0x7dc0 + 0x025d + 4 = 0x8021,如图2所示

图2.

FFmpeg简单使用:过滤器 ---- h264_mp4toannexb_第1张图片

 4.AVPacket转换为 AnnexB,使用h264_mp4toannexb

编码:

// 1 获取相应的比特流过滤器
    // FLV/MP4/MKV等结构中,h264需要h264_mp4toannexb处理。添加SPS/PPS等信息。
    // FLV封装时,可以把多个NALU放在一个VIDEO TAG中,结构为4B NALU长度+NALU1+4B NALU长度+NALU2+...,
    // 需要做的处理把4B长度换成00000001或者000001
    // annexb模式: startcode 00000001 AVCC模式: 无startcode (mp4 flv mkv)
    const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb");
    AVBSFContext *bsf_ctx = NULL;
    // 2 初始化过滤器上下文
    av_bsf_alloc(bsfilter, &bsf_ctx); //AVBSFContext;
    // 3 添加解码器属性
    avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->codecpar);
    av_bsf_init(bsf_ctx);
   // 4 发送和接受if (av_bsf_send_packet(bsf_ctx, pkt) != 0) // bitstreamfilter内部去维护内存空间
    {
          av_packet_unref(pkt);   // 你不用了就把资源释放掉
          continue;       // 继续送
    }
    av_packet_unref(pkt);   // 释放资源
    while(av_bsf_receive_packet(bsf_ctx, pkt) == 0)
    {
          out_pkt_count++;
          // printf("fwrite size:%d\n", pkt->size);
          av_packet_unref(pkt);
     }

 

我们看看filter之后的数据:

图3.

FFmpeg简单使用:过滤器 ---- h264_mp4toannexb_第2张图片

 我们可以看到,和图1相比size变为00 00 00 01.下面我们看下一帧

图4.

 

FFmpeg简单使用:过滤器 ---- h264_mp4toannexb_第3张图片

FFmpeg简单使用:过滤器 ---- h264_mp4toannexb_第4张图片

 

 我们可以看到,下一个并不是简单变为00 00 00 01,而是插入了一个nalu,再下一个nalu(f885位置),才是之前的nalu。我们分析一下中间插入的nalu,看第一下第一个字节表示nalu header.

NALU header格式:

0x67:

F:0 默认为0

R :11 表示这个帧很重要

T:7 表示SPS,到这里可以看出,插入了一个filter

你可能感兴趣的:(ffmpeg,ffmpeg)