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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ROS2创建自定义接口

ROS2提供了四种通信方式&#xff1a; 话题-Topics 服务-Services 动作-Action 参数-Parameters 查看系统自定义接口命令 使用ros2 interface package sensor_msgs命令可以查看某一个接口包下所有的接口 除了参数之外&#xff0c;话题、服务和动作(Action)都支持自定义接口&am…

基于卷积神经网络的目标检测

卷积神经网络基础知识 1.什么是filter 通常一个6x6的灰度图像&#xff0c;构造一个3*3的矩阵&#xff0c;在卷积神经网络中称之为filter,对&#xff16;x6的图像进行卷积运算。 2.什么是padding 假设输出图像大小为nn与过滤器大小为ff&#xff0c;输出图像大小则为(n−f1)∗(…

720漫游快速入门

720云全景漫游制作工具自2014年8月上线后&#xff0c;为数十万创作者提供全景图片&全景视频&高清矩阵上传、编辑、分享一站式软件服务&#xff0c;获得众多创作者的青睐与认可&#xff0c;同时也承载了创作者越来越多的期望&#xff0c;为了给大家提供更灵活多样的功能…

PTA—C语言期末复习(选择题)

1. 按照标识符的要求&#xff0c;&#xff08;A&#xff09;不能组成标识符。 A.连接符 B.下划线 C.大小写字母 D.数字字符 在大多数编程语言中&#xff0c;标识符通常由字母&#xff08;包括大写和小写&#xff09;、数字和下划线组成&#xff0c;但不能以数字开头&#xff0c…

MySQL事物

事务的概念 ●事务是一种机制、一个操作序列&#xff0c;包含了一组数据库操作命令&#xff0c;并且把所有的命令作为一个整体 一起向系统提交或撤销操作请求&#xff0c;即这一组数据库命令要么都执行&#xff0c;要么都不执行。 ●事务是一个不可分割的工作逻辑单元&#…

第1章_搭建开发环境

文章目录 第1章 搭建开发环境1.1开发套件硬件接口资源介绍1.2资料下载1.3安装Keil MDK1.3.1**软件下载**1.3.2**软件安装**1.3.3 PACK 安装 1.4 安装 STM32CubeMX1.5 安装 STM32CubeProgrammer1.6 安装 ST-Link 驱动1.7 安装 CH340 驱动 第1章 搭建开发环境 1.1开发套件硬件接…

可用的微信小程序抓包方式(Charles + bp)

扫码领资料 获网安教程 前言 接到对公司小程序进行渗透的任务&#xff0c;尝试了网上几种对小程序抓包的方式&#xff08;BurpProxifier、Burp安卓模拟器等&#xff09;都无法完成抓包&#xff0c;可能已经失效&#xff0c;结合不同的文章尝试了bpCharles&#xff0c;成功抓包…

vue2使用wangEditor5搭建模拟文档的编辑器快速集成

如图 1、下载依赖 2、elm引入&#xff08;可省略&#xff09; main.js 或者 按需引入 3、cv <template><div style"background: #f1f3f4"><div style"width: 100%; height: 42px"><!-- 工具栏 --><Toolbarid"tool-conta…

经典排序算法详解

目录 创作不易&#xff0c;如对您有帮助&#xff0c;还望一键三连&#xff0c;谢谢&#xff01; 前言 学习目标&#xff1a; 直接插入排序 基本思想&#xff1a; 代码 希尔排序&#xff1a; gap取值 代码 特性总结 选择排序 基本思想 代码 堆排序 思想 代码 冒…

选择适合你的8款原型设计工具

随着互联网的飞速发展&#xff0c;设计行业逐渐成为近年来的热门职业。设计师们需要的掌握的技能也越来越多&#xff0c;例如海报设计、名片设计、产品设计、网页设计等。产品原型设计就是产品设计中非常重要的一个阶段&#xff0c;主要目的是帮助用户更容易了解产品设计的思路…

驱动LSM6DS3TR-C实现高效运动检测与数据采集(6)----FIFO数据读取与配置

驱动LSM6DS3TR-C实现高效运动检测与数据采集.6--FIFO数据读取与配置 概述视频教学样品申请源码下载主要内容生成STM32CUBEMX串口配置IIC配置CS和SA0设置ICASHE修改堆栈串口重定向参考驱动程序FIFO参考程序初始化管脚获取ID复位操作设置量程BDU设置设置速率FIFO读取程序设置FIFO…

基于java语言+springboot技术架构开发的 互联网智能3D导诊系统源码支持微信小程序、APP 医院AI智能导诊系统源码

基于java语言springboot技术架构开发的 互联网智能3D导诊系统源码支持微信小程序、APP 医院AI智能导诊系统源码 一、智慧导诊系统开发原理 导诊系统从原理上大致可分为基于规则模板和基于数据模型两类。 1、基于规则推理的方法通过人工建立症状、疾病和科室之间的对应规则实现…

[XYCTF新生赛]-PWN:EZ1.0?(mips,mips的shellcode利用)

查看保护 查看ida 这里用的是retdec&#xff0c;没安装的可以看这个[CTF]-PWN:mips反汇编工具&#xff0c;ida插件retdec的安装-CSDN博客 这里直接看反汇编貌似看不出什么&#xff0c;所以直接从汇编找 完整exp&#xff1a; from pwn import* context(log_leveldebug,archmip…

高性价比:wb 1:10万的HRP直标标签抗体

货号名称规格官网价BDAA0197Recombinant Flag-Tag Monoclonal Antibody(3O2)HRP Conjugated100μl900BDAA0199Recombinant His-TagMonoclonal Antibody(14W7)HRP Conjugated100μl900BDAA0198Recombinant HA-TagMonoclonal Antibody(12H2)HRP Conjugated100μl900BDAA0199Recom…

分销裂变实战:PLG模式如何助力企业突破增长瓶颈

在竞争激烈的商业环境中&#xff0c;企业如何快速、有效地实现增长&#xff0c;一直是业界关注的焦点。近年来&#xff0c;分销裂变作为一种新兴的商业模式&#xff0c;凭借其独特的优势&#xff0c;逐渐受到企业的青睐。而产品驱动增长&#xff08;PLG&#xff09;模式更是为分…

特斯拉马斯克盛赞MEME币

刚刚&#xff0c;埃隆马斯克再次登上西方头条新闻&#xff0c;但这一次&#xff0c;不是关于火箭或电动汽车。这位炒币科技大亨在Twitter上宣布了“MEME币的明显胜利”&#xff0c;这一事件在加密社区引起了深刻的共鸣。币界网小编立马捕捉到了这一声明&#xff0c;象征着互联网…

GuLi商城-前端启动命令npm run dev

由于这里配置了dev&#xff0c;所以启动命令是npm run dev

vue2中vuedraggable设置部分元素不可拖拽,不可移动

文章目录 前言1、版本2、vuedraggable页面的具体使用3.核心(1) move官网说明(2) 注意点&#xff1a;(3) onDraggableMove方法 总结 前言 需求&#xff1a;左边是复选框&#xff0c;右边是选中的数据&#xff0c;编辑传入的数据不可拖拽&#xff0c;不可移动&#xff08;其实还…

RK3568技术笔记十八 Linux GPIO驱动程序中设备树分析

这段代码是RK3568芯片的设备树&#xff08;Device Tree&#xff09;片段&#xff0c;用于描述GPIO控制器的配置。 pinctrl: pinctrl { compatible "rockchip,rk3568-pinctrl"; // 兼容性字符串&#xff0c;指定此设备树节点适用于RK3568的引脚控制器 rockchip,grf…

鸿蒙 如何 url decode

在 TypeScript 和 JavaScript 中进行 URL 编码的最简单方式是使用内置的 global 函数 encodeURIComponent()。以下是一个示例&#xff1a; let url "https://example.com/?name测试&job开发者"; let encodedURL encodeURIComponent(url); console.log(encode…