ffmpeg使用mjpeg把yuvj420p编码为jpg图像

news2024/10/7 14:28:22

version

#define LIBAVUTIL_VERSION_MAJOR  58

#define LIBAVUTIL_VERSION_MINOR  12

#define LIBAVUTIL_VERSION_MICRO 100

note

1.

通过*.jpg推测时,out_fmt为image2,打开*.jpg文件时,in_fmt为image2

但是out_fmt为image2时,av_write_frame调用失败

2.

指定short_name为mjpeg,out_fmt为mjpeg

av_write_frame调用成功

code

void CFfmpegOps::EncodeYUVJ420pToMJPEG(const char *infile, const char *width_str, const char *height_str)
{
    if (!infile)
    {
        return;
    }

    int32_t width = 0;
    int32_t height = 0;

    try
    {
        width = std::stoi(width_str);
        height = std::stoi(height_str);
    }
    catch (std::exception& e)
    {
        return;
    }
    
#if 0
    size_t data_bytes = width * height * 3 / 2;
    std::shared_ptr<uint8_t> data(new uint8_t[data_bytes]);
#endif
    FILE *in_fp = nullptr;
    size_t n = 0;
    AVCodecContext *encoder_ctx = nullptr;
    const AVCodec *encoder = nullptr;
    const char *outfile = nullptr;
    int ret = -1;
    AVFormatContext *out_fmt_ctx = nullptr;
    AVStream *mjpeg_stream = nullptr;
    const AVOutputFormat *out_fmt = nullptr;
    AVFrame *avframe = nullptr;
    AVPacket *avpacket = nullptr;
    int frame_bytes = 0;

    in_fp = fopen(infile, "rb");
    if (!in_fp)
    {
        printf("fopen error\n");
        goto end;
    }

    avframe = av_frame_alloc();
    if (!avframe)
    {
        printf("av_frame_alloc error\n");
        goto end;
    }
    avframe->width = width;
    avframe->height = height;
    avframe->format = AV_PIX_FMT_YUVJ420P;
    avframe->pts = 0;

    // 获取单帧yuvj420p的字节数
    frame_bytes = av_image_get_buffer_size((AVPixelFormat)(avframe->format), avframe->width, avframe->height, 1);
#if 0
    if ((int)data_bytes != frame_bytes)
    {
        printf("data_bytes != frame_bytes\n");
        goto end;
    }
#endif

    ret = av_frame_get_buffer(avframe, 0);
    if (ret < 0)
    {
        printf("av_frame_get_buffer error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

    // 读取y分量
    n = fread(avframe->data[0], sizeof(uint8_t), avframe->width * avframe->height, in_fp);
    if ((int)n != (avframe->width * avframe->height))
    {
        printf("n != (avframe->width * avframe->height)\n");
        goto end;
    }

    // 读取u分量
    n = fread(avframe->data[1], sizeof(uint8_t), avframe->width * avframe->height / 4, in_fp);
    if ((int)n != (avframe->width * avframe->height / 4))
    {
        printf("n != (avframe->width * avframe->height / 4)\n");
        goto end;
    }

    // 读取v分量
    n = fread(avframe->data[2], sizeof(uint8_t), avframe->width * avframe->height / 4, in_fp);
    if ((int)n != (avframe->width * avframe->height / 4))
    {
        printf("n != (avframe->width * avframe->height / 4)\n");
        goto end;
    }

#if 0
    n = fread(data.get(), sizeof(uint8_t), data_bytes, in_fp);
    if (n != data_bytes)
    {
        printf("n != data_bytes\n");
        goto end;
    }

    ret = av_image_fill_arrays(avframe->data, avframe->linesize,
                               data.get(),
                               encoder_ctx->pix_fmt, encoder_ctx->width, encoder_ctx->height, 1);
    if (ret < 0)
    {
        printf("av_image_fill_arrays error:%s\n", GetFfmpegERR(ret));
        goto end;
    }
    else
    {
        printf("ret:%d, frame_bytes:%d\n", ret, frame_bytes);
    }
#endif

    avpacket = av_packet_alloc();
    if (!avpacket)
    {
        printf("av_packet_alloc error\n");
        goto end;
    }

    encoder = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
    if (!encoder)
    {
        printf("avcodec_find_encoder error\n");
        goto end;
    }

    encoder_ctx = avcodec_alloc_context3(encoder);
    if (!encoder_ctx)
    {
        printf("avcodec_alloc_context3 error\n");
        goto end;
    }
    // encoder_ctx->colorspace = ;
    // encoder_ctx->color_range = ;
    encoder_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
    encoder_ctx->width = width;
    encoder_ctx->height = height;
    encoder_ctx->framerate.num = 25;
    encoder_ctx->framerate.den = 1;
    encoder_ctx->time_base.num = 1;
    encoder_ctx->time_base.den = 25;
    encoder_ctx->bit_rate = frame_bytes * encoder_ctx->framerate.num * 8;

    ret = avcodec_open2(encoder_ctx, encoder, nullptr);
    if (ret < 0)
    {
        printf("avcodec_open2 error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

    out_fmt_ctx = avformat_alloc_context();
    if (!out_fmt_ctx)
    {
        printf("avformat_alloc_context error\n");
        goto end;
    }

    outfile = "image_%03d.jpg";
#if 0
    /*
    通过*.jpg推测时,out_fmt为image2,打开*.jpg文件时,in_fmt为image2
    但是out_fmt为image2时,av_write_frame调用失败
    */
    out_fmt = av_guess_format(nullptr, outfile, nullptr);
    if (!out_fmt)
    {
        printf("av_guess_format error\n");
        goto end;
    }
#else
    /*
    指定short_name为mjpeg,out_fmt为mjpeg
    av_write_frame调用成功
    */
    out_fmt = av_guess_format("mjpeg", nullptr, nullptr);
    if (!out_fmt)
    {
        printf("av_guess_format error\n");
        goto end;
    }
#endif

    out_fmt_ctx->oformat = out_fmt;

    mjpeg_stream = avformat_new_stream(out_fmt_ctx, encoder);
    if (!mjpeg_stream)
    {
        printf("avformat_new_stream error\n");
        goto end;
    }

    ret = avcodec_parameters_from_context(mjpeg_stream->codecpar, encoder_ctx);
    if (ret < 0)
    {
        printf("avcodec_parameters_from_context error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

#if 0
    ret = avio_open(&(out_fmt_ctx->pb), outfile, AVIO_FLAG_WRITE);
    if (ret < 0)
    {
        printf("avio_open error:%s\n", GetFfmpegERR(ret));
        goto end;
    }
#else
    ret = avio_open2(&(out_fmt_ctx->pb), outfile, AVIO_FLAG_READ_WRITE, nullptr, nullptr);
    if (ret < 0)
    {
        printf("avio_open2 error:%s\n", GetFfmpegERR(ret));
        goto end;
    }
#endif

    ret = avformat_write_header(out_fmt_ctx, nullptr);
    if (ret < 0)
    {
        printf("avformat_write_header error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

    ret = avcodec_send_frame(encoder_ctx, avframe);
    if (ret < 0)
    {
        printf("avcodec_send_frame error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

    while (1)
    {
        ret = avcodec_receive_packet(encoder_ctx, avpacket);
        if (ret < 0)
        {
            printf("avcodec_receive_packet error:%s\n", GetFfmpegERR(ret));
            break;
        }
        avpacket->time_base.num = encoder_ctx->time_base.num;
        avpacket->time_base.den = encoder_ctx->time_base.den;

#if 0
        ret = av_interleaved_write_frame(out_fmt_ctx, avpacket);
        if (ret < 0)
        {
            printf("av_interleaved_write_frame error:%s\n", GetFfmpegERR(ret));
            break;
        }
#else
        ret = av_write_frame(out_fmt_ctx, avpacket);
        if (ret < 0)
        {
            printf("av_write_frame error:%s\n", GetFfmpegERR(ret));
            break;
        }
#endif
    }

    // 写元数据
    ret = av_write_trailer(out_fmt_ctx);
    if (ret < 0)
    {
        printf("av_write_trailer error:%s\n", GetFfmpegERR(ret));
        goto end;
    }

end:
    if (avpacket)
    {
        av_packet_free(&avpacket);
        avpacket = nullptr;
    }

    if (avframe)
    {
        av_frame_free(&avframe);
        avframe = nullptr;
    }

    if (out_fmt_ctx->pb)
    {
        avio_close(out_fmt_ctx->pb);
        out_fmt_ctx->pb = nullptr;
    }

    if (out_fmt_ctx)
    {
        avformat_free_context(out_fmt_ctx);
        out_fmt_ctx = nullptr;
    }

    if (encoder_ctx)
    {
        avcodec_free_context(&encoder_ctx);
        encoder_ctx = nullptr;
    }

    if (in_fp)
    {
        fclose(in_fp);
        in_fp = nullptr;
    }
}

perfomance

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1873660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

冶金工业5G智能工厂工业物联数字孪生平台,推进制造业数字化转型

冶金工业5G智能工厂工业物联数字孪生平台&#xff0c;推进制造业数字化转型。传统生产方式难以满足现代冶金工业的发展需求&#xff0c;数字化转型成为必然趋势。通过引入5G、工业物联网和数字孪生等先进技术&#xff0c;冶金工业可以实现生产过程智能化、高效化和绿色化&#…

【Echarts】散点图 制作 气泡 类型图表

目录 需求主要代码效果展示注 需求 需参照设计图画出对应图表 主要代码 /**** 数据 ****/ this.dataList [...Array(8).keys()].map((item) > {return {ywlxmc: 业务类型 (item 1),sl: item > 4 ? 50 : 70} })/**** 气泡样式 ****/ const styleList [{offset: [56…

谷粒商城实战(045集群学习-elasticsearch(ES)集群)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第368p-第p369的内容 文章目录 简介集群健康分片新增节点水平扩容问题和解决集群结构测试集群信息 简介 不管用户发给哪个节点&#xff0c;都可以…

如何断点调试opencv源码

分几个步骤&#xff1a; 1、下载opencv-4.10.0-windows.exe https://opencv.org/releases/ 2、想要调试opencv的源码&#xff0c;只需要将这两个文件拷贝到我们自己项目的可执行文件的同级目录内即可。 完成拷贝后&#xff0c;直接在vs工程中打断点F11进行单步调试&#xff…

智能交通(1)——杭州交通数据集

赛题简介 在本地赛题中&#xff0c;参赛团队需要在平台提供的仿真交通场景下&#xff0c;通过算法模型驱动交通信号灯&#xff0c;以在各种交通状况&#xff08;高峰期、雨天等&#xff09;下都能最大程度地服务车辆&#xff0c;使其在模拟环境中获得综合最大得分。 数据集 …

基于 SpringBoot + Vue 的图书购物商城项目

本项目是一个基于 SpringBoot 和 Vue 的图书购物商城系统。系统主要实现了用户注册、登录&#xff0c;图书浏览、查询、加购&#xff0c;购物车管理&#xff0c;订单结算&#xff0c;会员折扣&#xff0c;下单&#xff0c;个人订单管理&#xff0c;书籍及分类管理&#xff0c;用…

subline设置打开文件重启一个新的窗口

问题 打开文件后&#xff0c;用的是同一个窗口的子tab页面 想要打开一个新的窗口 解决 点解preferences->setting 在右边的配置文件新增一行 “open_files_in_new_window”: “always” 保存 搞定&#xff01;

聊聊啥项目适合做自动化测试

作为测试从业者&#xff0c;你是否遇到过这样的场景&#xff0c;某天公司大Boss找你谈话。 老板&#xff1a;小李&#xff0c;最近工作辛苦了 小李&#xff1a;常感谢您的认可&#xff0c;这不仅是对我个人的鼓励&#xff0c;更是对我们整个团队努力的认可。我们的成果离不开每…

建筑可视化中使用云渲染的几大理由

在建筑行业中&#xff0c;可视化技术已成为不可或缺的一部分。无论是设计方案的展示、施工进度的模拟&#xff0c;还是最终效果的呈现&#xff0c;建筑可视化都发挥着至关重要的作用。 建筑可视化是指通过计算机技术和图形学算法&#xff0c;将建筑设计、规划和施工过程中的数据…

three.js实现雪花场景效果

点击获取雪花图片素材 提取码:lywa // 雪花效果 import * as THREE from "three" export function getsnowEffect(th) {console.log(th, th) // this 场景var that th// 创建一个BufferGeometry对象&#xff0c;用于存储顶点数据 const geometry new THREE.Buffe…

同城小商城货到付款系统源码小程序

&#xff1a;便捷购物新选择 &#x1f680; 一、快速便捷&#xff0c;同城直达 在这个快节奏的时代&#xff0c;时间就是金钱。你是否曾因为等待快递而焦虑不安&#xff1f;现在&#xff0c;有了“同城商城货到付款小程序”&#xff0c;这一切都变得不再是问题。它专注于同城…

2024年科技型中小企业申报指南

01 什么是科技型中小企业 科技型中小企业是指依托一定数量的科技人员从事科学技术研究开发活动&#xff0c;取得自主知识产权并将其转化为高新技术产品或服务&#xff0c;从而实现可持续发展的中小企。 02 申请“科技型中小企业”的好处 一、政策扶持与优惠 1.税收减免&…

根据肥胖类型选择减调方向收获窈窕身材

我们生活中胖子很多&#xff0c;从胖到瘦的人也不少&#xff0c;但瘦了后对自己身材满意的人却是不多的&#xff0c;很多人瘦了也只是减掉了身上的赘肉而已&#xff0c;大体的身形却是没有变化的&#xff0c;因此&#xff0c;并不感到满意。因为他们本身的形体是固定的&#xf…

恭喜!Apache SeaTunnel2024开源之夏学生中选名单出炉!

经过严格的筛选&#xff0c;开源之夏组委会及导师已经选出并录取项目对应的学生&#xff0c;社区联合中科院开展的开源之夏活动也进入到了激动人心的中选公示阶段。 在这里&#xff0c;我们恭喜下面的同学&#xff0c;已成功匹配到Apache SeaTunnel社区的项目&#xff0c;即将开…

关于vue创建项目失败报错(镜像过期)的解决方案

在新建vue项目时出现以下错误&#xff1a; 原因&#xff1a; npm.taobao.org和registry.npm.taobao.org旧域名于2021年官方公告域名更换事件&#xff0c;已于2022年05月31日零时起停止服务&#xff0c;域名HTTPS证书于2024年1月22日正式到期&#xff0c;不可再用。 解决方案:…

选型应用:Ampleon的BLF884PS功率晶体管

Ampleon的BLF884PS&#xff0c;一个高性能的射频功率晶体管&#xff0c;在射频微波领域&#xff0c;功率晶体管是关键组件之一&#xff0c;特别是在广播和通信系统中。就是这一技术的杰出代表。本文将深入介绍这一型号的特点及其制造商Ampleon的背景。 Ampleon的起源与专长 Am…

U盘数据被删,四个补救措施要收藏好!

在日常工作及学习过程中&#xff0c;大家都会频繁使用U盘进行数据储存与转移。然而因操作失误&#xff0c;如&#xff1a;手动误删、直接清空或格式化等&#xff0c;将会造成一些重要的数据遗失&#xff0c;并且在面临此状况时&#xff0c;就需要找到一个有效的方法去恢复了。那…

Excel表格转换Word文档的3个简单方法分享!

在日常办公中&#xff0c;我们经常需要将Excel表格中的数据转换为Word文档以便于编辑、排版或分享。然而&#xff0c;很多人可能并不清楚如何实现这一转换过程&#xff0c;或者只能采取复制粘贴的笨拙方式&#xff0c;导致格式错乱、效率低下。本文将详细介绍两种高效、便捷的E…

k8s集群node节点加入失败

出现这种情况&#xff1a; [preflight] FYI: You can look at this config file with kubectl -n kube-system get cm kubeadm-config -o yaml [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Writing kub…

49-5 内网渗透 - 服务注册表权限脆弱提权

一、服务注册表权限脆弱提权介绍 Windows操作系统中的注册表存储了每个系统服务的相关条目。注册表使用访问控制列表(ACL)来管理用户对其条目的访问权限。如果注册表的ACL配置不正确,可能导致低权限用户获得对服务注册表的写入权限。攻击者可以利用这一漏洞修改注册表内容,…