八月的雨季 最後的冰吻

八月的雨季 最後的冰吻

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);
        }
  	}
03-09 23:12