用ffmpeg如何将一帧h264转成jpg

来源:互联网 发布:北京 软件编程培训班 编辑:程序博客网 时间:2024/06/05 08:02
一 什么是h264帧,什么是jpg?
h264帧,是把yuv经过h264压缩算法压缩成的一帧h264数据
jpg,是一种图片格式,压缩算法为mjpeg。


二 把h264转换成jpg图片需要做什么?
分为三步:
1 解码h264
2 编码mjpeg
3 存到文件(存到文件就不介绍了)


三 ffmpeg转h264为jpg图片代码实现。
ffmpeg直接是支持h264解码和mjpeg编码的。(注意,ffmpeg默认不支持h264编码,要支持编码需要在编译ffmpeg的时候,引入
x264库,先编译安装x264库,然后编译ffmpeg库的时候指向x264库即可)
(1)首先初始化h264解码器和mjpeg编码器。
av_register_all();
    avcodec_register_all();
//上面这个就不介绍了,注册所有的编解码器
s->mjpeg_info.f_pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);//找到h264解码器
    s->mjpeg_info.f_pCodecCtx = avcodec_alloc_context3(s->mjpeg_info.f_pCodec);//申请h264解码上下文


if(avcodec_open2(s->mjpeg_info.f_pCodecCtx,s->mjpeg_info.f_pCodec,NULL) != 0)//打开h264解码器
{
return NGX_ERROR;
}
    
    s->mjpeg_info.f_pJpegCodec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);//找到mjpeg编码器
//为什么这里不和h264一样,先申请编码上下文,并且打开编码器呢?
因为mjpeg编码的时候,如果分辨率发生了变化,编码上下文就需要重新初始化,也就是把原有的编码器关闭,并把上下文释放掉,
然后重新申请一个,并重新打开编码器

注意两个结构体:
AVPacket 存放编码后的数据帧
AVFrame 存放解码后的原始数据
avcodec_decode_video2(s->mjpeg_info.f_pCodecCtx,s->mjpeg_info.f_pFrame,&GetFrame,&f_pPackage);//先h264帧解码
if(s->mjpeg_info.f_pJpegCodecCtx && (s->mjpeg_info.f_pJpegCodecCtx->width != s->mjpeg_info.lastWidth
        || s->mjpeg_info.f_pJpegCodecCtx->height != s->mjpeg_info.lastHeight))//然后判断分辨率是否发生了变化
{
    if(s->mjpeg_info.f_pJpegCodecCtx != NULL)
    {
        avcodec_close(s->mjpeg_info.f_pJpegCodecCtx);
        avcodec_free_context(&s->mjpeg_info.f_pJpegCodecCtx);
        s->mjpeg_info.f_pJpegCodecCtx = NULL;
    }
    }//变化了则释放原有的编码上下文,并关闭编码器
s->mjpeg_info.f_pJpegCodecCtx = avcodec_alloc_context3(s->mjpeg_info.f_pJpegCodec);//申请编码上下文
//设置必要的编码参数
s->mjpeg_info.f_pJpegCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;//编码器类型
    s->mjpeg_info.f_pJpegCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P;//YUV layout格式
s->mjpeg_info.f_pJpegCodecCtx->time_base.num = 1;//
    s->mjpeg_info.f_pJpegCodecCtx->time_base.den = 15;//这两个参数设置时间基

   
    s->mjpeg_info.f_pJpegCodecCtx->width = s->mjpeg_info.f_pFrame->width;
    s->mjpeg_info.f_pJpegCodecCtx->height = s->mjpeg_info.f_pFrame->height; //分辨率
avcodec_open2(s->mjpeg_info.f_pJpegCodecCtx,s->mjpeg_info.f_pJpegCodec,NULL);//打开编码器
avcodec_encode_video2(s->mjpeg_info.f_pJpegCodecCtx,&pkt_out,s->mjpeg_info.f_pFrame,&got_packet_ptr);//编码mjpeg
fwrite(pkt_out.data, sizeof(uint8_t),pkt_out.size, pFile);//存图片


四 后续再讲一些类似aac语音解码播放,或者转码为其它格式,敬请期待。

更多开源流媒体技术,请关注我们的微信:EasyDarwin