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

=====================================================

FFmpeg简单使用:解封装 ---- 基本流程

FFmpeg简单使用:解封装 ---- 提取aac

FFmpeg简单使用:音频解码 ---- 提取pcm

FFmpeg简单使用:视频解码 ---- 提取yuv

FFmpeg简单使用:音频编码 ---- pcm转aac

FFmpeg简单使用:视频编码 ---- YUV转H264

FFmpeg简单使用:过滤器 ---- 视频过滤

FFmpeg简单使用:过滤器 ---- 视频过滤2

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

FFmpeg简单使用:解封装h264 ---- 提取SPS PPS

=====================================================

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.

 

 

 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.

 

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

图4.

 

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

NALU header格式:

0x67:

F:0 默认为0

R :11 表示这个帧很重要

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

 

posted @ 2020-10-15 08:49  Vzf  阅读(4412)  评论(0编辑  收藏  举报