栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

基于FFMPEG将YUV420转为jpg

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于FFMPEG将YUV420转为jpg

代码1来自雷神博客,从文件中读取一帧的YUV数据,然后将其进行编码,然后调用av_write_frame函数将AVPacket里面的数据写到输出文件中去,在手敲代码的过程中,对解码后的AVPakcet里面的数据进行测试,发现AVPacket里面的data其实就是一副picture 完整的数据,于是便直接将其写入文件中去,不再采用av_write_frame的方式,如代码2,大体上采用雷博的代码,在一些细节地方做了修改。

代码1:

int YUV_2_JPG1(char* pFile)
{
    if (NULL == pFile) return -1;

    AVFormatContext* pFormatCtx;
    AVOutputFormat*  pOutFmt;
    AVStream* pStream;
    AVCodecContext* pCodecCtx;
    AVCodec* pCodec;
    AVFrame* pFrame;
    AVPacket pkt;

    uint8_t* picture_buf;
    int y_size = 0;
    int size = 0;
    int width = 640;
    int height = 480;
    const char* out_file = "test1.jpg";

    int got_picture = 0;
    int ret = 0;

    FILE* in_file = fopen(pFile, "rb");
    if (NULL == in_file)
    {
        printf("open input file error!n");
        return -1;
    }

    av_register_all();

    pFormatCtx = avformat_alloc_context();   //分配AVFormatCtx
    pOutFmt = av_guess_format("mjpeg", NULL, NULL); //设置输出文件格式
    pFormatCtx->oformat = pOutFmt;

    if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) //创建并初始化一个AVIOContext
    {
        printf("Could not open output file!n");
        return -1;
    }

    pStream = avformat_new_stream(pFormatCtx, 0);
    if (NULL == pStream)
        return -1;
    
    pCodecCtx = pStream->codec;
    pCodecCtx->codec_id = pOutFmt->video_codec;
    pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
    pCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P;
    pCodecCtx->width = width;
    pCodecCtx->height = height;
    pCodecCtx->time_base.num = 1;
    pCodecCtx->time_base.den = 25;

    //av_dump_format(pFormatCtx, 0, out_file, 1);

    pCodec = avcodec_find_encoder(pCodecCtx->codec_id); //查找编码器
    if (NULL == pCodec)
    {
        printf("can not find codec!n");
        return -1;
    }
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    {
        printf("con not open codec!n");
        return -1;
    }

    pFrame = av_frame_alloc();
    size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);//获取图片的大小
    picture_buf = (uint8_t*)av_malloc(size);
    if (NULL == picture_buf)
    {
        printf("malloc picture buf error!n");
        return -1;
    }
   avpicture_fill((AVPicture*)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

    avformat_write_header(pFormatCtx, NULL); 

    y_size = pCodecCtx->width * pCodecCtx->height;
    av_new_packet(&pkt, y_size*2);  //给AVPacket申请空间

    if (fread(picture_buf, 1, y_size*3/2,in_file) != (y_size*3/2))
    {
        printf("read input file error!n");
        return -1;
    }    

    pFrame->width = pCodecCtx->width;  
    pFrame->height =  pCodecCtx->height;
    pFrame->format = pCodecCtx->pix_fmt;
    pFrame->data[0] = picture_buf;
    pFrame->data[1] = picture_buf + y_size;
    pFrame->data[2] = picture_buf + y_size*5/4;

    ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_picture);//编码
    if (ret < 0)
    {
        printf("encodec yuv data error!n");
        return -1;
    }
    if (1 == got_picture)
    {
        pkt.stream_index = pStream->index;
        av_write_frame(pFormatCtx, &pkt); //写数据
    }

    av_write_trailer(pFormatCtx);

    av_free_packet(&pkt);
    av_free(picture_buf);
    av_free(pFrame);
    avcodec_close(pStream->codec);
    avio_close(pFormatCtx->pb);
    avformat_free_context(pFormatCtx);

    fclose(in_file);

    return 0;
}

代码2:

int YUV_2_JPG2(char* pFile)
{
    if (NULL == pFile) return -1;

    AVFormatContext* pFormatCtx;
    AVStream* pStream;
    AVCodecContext* pCodecCtx;
    AVCodec* pCodec;
    AVFrame* pFrame;
    AVPacket pkt;

    uint8_t* picture_buf;
    int y_size = 0;
    int size = 0;
    int width = 640;
    int height = 480;

    int got_picture = 0;
    int ret = 0;

    FILE* in_file = fopen(pFile, "rb");
    if (NULL == in_file)
    {
        printf("open input file error!n");
        return -1;
    }
    FILE* out_file =  fopen("test2.jpg", "wb");
    if (NULL == out_file)
    {
        printf("open output file error!n");
        return -1;
    }

    av_register_all();

    pFormatCtx = avformat_alloc_context();   //分配AVFormatCtx


    pStream = avformat_new_stream(pFormatCtx, 0);
    if (NULL == pStream)
        return -1;
    
    pCodecCtx = pStream->codec;
    pCodecCtx->codec_id = AV_CODEC_ID_MJPEG;
    pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
    pCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P;
    pCodecCtx->width = width;
    pCodecCtx->height = height;
    pCodecCtx->time_base.num = 1;
    pCodecCtx->time_base.den = 25;

    //av_dump_format(pFormatCtx, 0, out_file, 1);

    pCodec = avcodec_find_encoder(pCodecCtx->codec_id); //查找编码器
    if (NULL == pCodec)
    {
        printf("can not find codec!n");
        return -1;
    }
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    {
        printf("con not open codec!n");
        return -1;
    }

    pFrame = av_frame_alloc();
    size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);//获取图片的大小
    picture_buf = (uint8_t*)av_malloc(size);
    if (NULL == picture_buf)
    {
        printf("malloc picture buf error!n");
        return -1;
    }
   avpicture_fill((AVPicture*)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);


    y_size = pCodecCtx->width * pCodecCtx->height;
    av_new_packet(&pkt, y_size*2);  //给AVPacket申请空间

    if (fread(picture_buf, 1, y_size*3/2,in_file) != (y_size*3/2))
    {
        printf("read input file error!n");
        return -1;
    }    

    pFrame->width = pCodecCtx->width;  
    pFrame->height =  pCodecCtx->height;
    pFrame->format = pCodecCtx->pix_fmt;
    pFrame->data[0] = picture_buf;
    pFrame->data[1] = picture_buf + y_size;
    pFrame->data[2] = picture_buf + y_size*5/4;

    ret = avcodec_encode_video2(pCodecCtx, &pkt, pFrame, &got_picture);//编码
    if (ret < 0)
    {
        printf("encodec yuv data error!n");
        return -1;
    }
    if (1 == got_picture)
    {
            fwrite(pkt.buf->data, 1, pkt.size, out_file);
    }

    av_free_packet(&pkt);
    av_free(picture_buf);
    av_free(pFrame);
    avcodec_close(pStream->codec);
    avformat_free_context(pFormatCtx);

    fclose(in_file);
    fclose(out_file);
    return 0;
}

文章最底部,领取最新最全C++音视频学习提升资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/960383.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号