H264
视频编解码协议,为MPEG-4 AVC或AVC
I P B 帧
I帧:可独立解码
P帧:前向预测编码帧,参考I帧 或者 P帧
B帧: 双向预测帧,参考I 帧,P帧
压缩率:B>P>I
NALU结构
H.264原始码流由一个接一个的NALU组成
⼀个原始的H.264 NALU单元通常由
[StartCode] [NALUHeader] [NALU Payload]三部分组成,其中 Start Code ⽤于标示这是⼀个NALU 单元的开
始,必须是"00 00 00 01" 或"00 00 01"
H264 封装模式
1 annexb模式
传统模式,有startcode,SPS和PPS
2 MP4模式
需要加startcode,SPS和PPS以及其它信息
对mp4视频文件解码为h264文件需在h264_mp4toannexb_filter中转换
(flv格式也需要加startcode ,ts流不需要加startcode)
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);
写H264文件
对于MP4文件,h264_mp4toannexb_filter转化后,调用
av_bsf_send_packet筛选pkt,之后调用av_bsf_receive_packet获取pkt,再写文件
// 过滤pkt
int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt);
int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt);
每次调用send,reveive 后都要释放pkt内存
while(av_read_frame(ifmt_ctx, pkt)) {
if (av_bsf_send_packet(bsf_ctx, pkt)) {
av_packet_unref(pkt);
continue;
}
av_packet_unref(pkt); // 释放资源
while(av_bsf_receive_packet(bsf_ctx, pkt)) {
fwrite(pkt->data, 1, pkt->size, outfp);
av_packet_unref(pkt);
}
}