美文网首页
FFMPEG YUV转JPEG图片

FFMPEG YUV转JPEG图片

作者: 何亮hook_8285 | 来源:发表于2022-12-18 16:05 被阅读0次

    此代码通过读取YUV数据转换JPEG图片数据,并且存储到磁盘中。
    代码如下:

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <thread>
    #include <functional>
    
    extern "C"{
    #include <libavformat/avformat.h>
    #include <libavutil/pixdesc.h>
    #include <libavutil/opt.h>
    #include <libavutil/imgutils.h>
    #include <libswscale/swscale.h>
    };
    
    
    //heliang
    int main()
    {
    
        AVPixelFormat pfmt=AV_PIX_FMT_YUV420P;
        AVFrame *frame=av_frame_alloc();
        frame->width=1920;
        frame->height=818;
        frame->format=pfmt;
    
        std::ifstream ifs("d:\\test.yuv",std::ios::binary);
        //获取一帧数据大小
        int frameSize=av_image_get_buffer_size(pfmt,frame->width,frame->height,1);
    
        //读取一帧数据
        std::unique_ptr<uint8_t*> yuvFrameData=std::make_unique<uint8_t*>(new uint8_t[frameSize]);
        ifs.read((char*)*yuvFrameData.get(),frameSize);
    
        //填充图像的平面线尺寸
        av_image_fill_linesizes(frame->linesize,pfmt,frame->width);
    
        //将1维数组转换成二维数组,例如Y=frame->data[0],U=frame->data[1],V=Y=frame->data[2]
        av_image_fill_pointers(frame->data,pfmt,frame->height,*yuvFrameData.get(),frame->linesize);
    
        //创建AV_PIX_FMT_YUVJ422P的帧
        AVFrame  *yuvj422pFrame=av_frame_alloc();
        yuvj422pFrame->width=frame->width;
        yuvj422pFrame->height=frame->height;
        yuvj422pFrame->format=AV_PIX_FMT_YUVJ422P;
        //初始化buffer数据
        av_frame_get_buffer(yuvj422pFrame,0);
    
        //yuv420p转yuvj422p
        SwsContext *swsContext= nullptr;
        //创建重采样的上下文
        swsContext=sws_getCachedContext(
                swsContext,  //重采样上下文
                frame->width, //源yuv宽度
                frame->height, //源yuv高度
                pfmt, //yuv存储格式
                yuvj422pFrame->width,
                yuvj422pFrame->height,
                AV_PIX_FMT_YUVJ422P,
                SWS_BILINEAR, //重采样算法,线性算法
                NULL, //源过滤,不使用
                NULL, //目标过滤,不使用
                0  //过滤参数,不使用
        );
    
    
        //转换
        int reH=sws_scale(swsContext, //重采样上下文
                  frame->data, //yuv数据
                  frame->linesize, //yuv设置一行大小
                  0, //设置y,不考虑,设置0
                  frame->height, //设置yuv高度
                  yuvj422pFrame->data, //设置rgba的存储空间
                  yuvj422pFrame->linesize //rgba存储空间
        );
    
        std::cout << "reH=" << reH << std::endl;
    
    
    
        AVFormatContext *pfctx=avformat_alloc_context();
        //通过简称获取输出上下文,通过ffmpeg -formats命令查看
        pfctx->oformat=av_guess_format("mjpeg", NULL, NULL);
        if (avio_open(&pfctx->pb, "d:\\test.jpg", AVIO_FLAG_READ_WRITE) < 0) //创建并初始化一个AVIOContext
        {
            std::cout << "avio_open error msg " << std::endl;
            return -1;
        }
    
        //找到编码器
        AVCodec *codec=avcodec_find_encoder(pfctx->oformat->video_codec);
        AVCodecContext *enCodecCtx=avcodec_alloc_context3(codec);
        enCodecCtx->codec_id=pfctx->oformat->video_codec;
        enCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
        enCodecCtx->width=frame->width;
        enCodecCtx->height=frame->height;
        enCodecCtx->pix_fmt=AV_PIX_FMT_YUVJ422P;
        enCodecCtx->time_base={1,25};
    
        AVStream* stream = avformat_new_stream(pfctx, 0);
        avcodec_parameters_from_context(stream->codecpar,enCodecCtx);
        av_dump_format(pfctx, 0, NULL, 1);
    
        int ret=avcodec_open2(enCodecCtx,codec,NULL);
        if(ret!=0)
        {
            char buf[1024]={0};
            av_strerror(ret,buf,sizeof(buf));
            std::cout << "avcodec_open2 failed error msg :" << buf << std::endl;
            return 0;
        }
    
        avformat_write_header(pfctx, NULL);
    
        AVPacket *pkt=av_packet_alloc();
    
    
        //发送到编码器中
         ret = avcodec_send_frame(enCodecCtx, yuvj422pFrame);
        while (ret >= 0)
        {
            //接受编码器数据
            ret = avcodec_receive_packet(enCodecCtx, pkt);
            if (ret < 0)
                break;
    
            av_write_frame(pfctx, pkt);
            //解引用
            av_packet_unref(pkt);
        }
    
        av_write_trailer(pfctx);
        ifs.close();
        av_packet_free(&pkt);
        av_frame_free(&frame);
        av_frame_free(&yuvj422pFrame);
        avcodec_free_context(&enCodecCtx);
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:FFMPEG YUV转JPEG图片

          本文链接:https://www.haomeiwen.com/subject/uoseqdtx.html