ffmpeg + opencv 把摄像头画面保存为mp4文件(Ubuntu24.04)

参考链接

 ffmpeg + opencv 把摄像头画面保存为mp4文件_ffmpeg转化摄像头mp4-CSDN博客

调试环境

Ubuntu24.04

ffmpeg 6.1.1

opencv 4.6

g++ 13.2.0
 

C++源码

#include <iostream>
#include <sys/time.h>
#include <string>#ifdef __cplusplus
extern "C"
{
#endif#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
#include <libavcodec/avcodec.h>#ifdef __cplusplus
} // endof extern "C"
#endif#include <opencv2/opencv.hpp>
using namespace cv;AVFrame *videoFrame = nullptr;
AVCodecContext *cctx = nullptr;
SwsContext *swsCtx = nullptr;
int frameCounter = 0;
AVFormatContext *ofctx = nullptr;
int fps = 30;
int width = 640;
int height = 480;
int bitrate = 2000;
long start_time = 0;
const std::string output_filename = "out.mp4";
// const std::string output_filename = "out.ts";long getCurrentTime()
{struct timeval tv;gettimeofday(&tv, NULL);return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}static void pushFrame(uint8_t *data, long currentTime)
{int err;AVPacket pkt = {0};int inLinesize[1] = {3 * cctx->width};// From RGB to YUVsws_scale(swsCtx, (const uint8_t *const *)&data, inLinesize, 0, cctx->height, videoFrame->data, videoFrame->linesize);videoFrame->pts = ((currentTime - start_time) / 1000.0) * 90000;std::cout << videoFrame->pts << " " << cctx->time_base.num << " " << cctx->time_base.den << " " << frameCounter << std::endl;if ((err = avcodec_send_frame(cctx, videoFrame)) < 0){std::cout << "Failed to send frame" << err << std::endl;return;}pkt.buf = NULL;pkt.side_data = NULL;pkt.data = NULL;pkt.size = 0;pkt.flags |= AV_PKT_FLAG_KEY;if (avcodec_receive_packet(cctx, &pkt) == 0){static int counter = 0;if (counter == 0){FILE *fp = fopen("dump_first_frame1.dat", "wb");fwrite(pkt.data, pkt.size, 1, fp);fclose(fp);}std::cout << "pkt key: " << (pkt.flags & AV_PKT_FLAG_KEY) << " " << pkt.size << " " << (counter++) << std::endl;uint8_t *size = ((uint8_t *)pkt.data);std::cout << "first: " << (int)size[0] << " " << (int)size[1] << " " << (int)size[2] << " " << (int)size[3] << " " << (int)size[4] << " " << (int)size[5] << " " << (int)size[6] << " " << (int)size[7] << std::endl;av_interleaved_write_frame(ofctx, &pkt);av_packet_unref(&pkt);}
}static void finish()
{// DELAYED FRAMESAVPacket pkt = {0};pkt.data = NULL;pkt.size = 0;while (true){avcodec_send_frame(cctx, NULL);if (avcodec_receive_packet(cctx, &pkt) == 0){av_interleaved_write_frame(ofctx, &pkt);av_packet_unref(&pkt);}else{break;}}av_write_trailer(ofctx);avformat_close_input(&ofctx);
}static void free()
{if (videoFrame){av_frame_free(&videoFrame);}if (cctx){avcodec_free_context(&cctx);}if (ofctx){avformat_free_context(ofctx);}if (swsCtx){sws_freeContext(swsCtx);}
}int main()
{// VideoCapture capture("road_test.mp4");VideoCapture capture(0);Mat frame;capture >> frame;width = frame.cols;height = frame.rows;avdevice_register_all();int err = avformat_alloc_output_context2(&ofctx, nullptr, nullptr, output_filename.c_str());if (err){std::cout << "can't create output context" << std::endl;return -1;}const AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);if (!codec){std::cout << "can't create codec" << std::endl;return -1;}AVStream *stream = avformat_new_stream(ofctx, codec);if (!stream){std::cout << "can't find format" << std::endl;return -1;}cctx = avcodec_alloc_context3(codec);if (!cctx){std::cout << "can't create codec context" << std::endl;return -1;}stream->codecpar->codec_id = AV_CODEC_ID_H264;stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;stream->codecpar->width = width;stream->codecpar->height = height;stream->codecpar->format = AV_PIX_FMT_YUV420P;stream->codecpar->bit_rate = bitrate * 1000;avcodec_parameters_to_context(cctx, stream->codecpar);cctx->time_base = (AVRational){1, 1};cctx->max_b_frames = 2;cctx->gop_size = 12;cctx->framerate = (AVRational){fps, 1};if (stream->codecpar->codec_id == AV_CODEC_ID_H265){av_opt_set(cctx, "preset", "ultrafast", 0);}avcodec_parameters_from_context(stream->codecpar, cctx);if ((err = avcodec_open2(cctx, codec, NULL)) < 0){std::cout << "Failed to open codec" << err << std::endl;return -1;}if ((err = avio_open(&ofctx->pb, output_filename.c_str(), AVIO_FLAG_WRITE)) < 0){std::cout << "Failed to open file" << err << std::endl;return -1;}if ((err = avformat_write_header(ofctx, NULL)) < 0){std::cout << "Failed to write header" << err << std::endl;return -1;}av_dump_format(ofctx, 0, output_filename.c_str(), 1);videoFrame = av_frame_alloc();videoFrame->format = AV_PIX_FMT_YUV420P;videoFrame->width = cctx->width;videoFrame->height = cctx->height;if ((err = av_frame_get_buffer(videoFrame, 32)) < 0){std::cout << "Failed to allocate picture" << err << std::endl;return -1;}swsCtx = sws_getContext(cctx->width, cctx->height, AV_PIX_FMT_BGR24, cctx->width, cctx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, 0, 0, 0);start_time = getCurrentTime();for (int i = 0; i < 100; ++i){capture >> frame;pushFrame(frame.data, getCurrentTime());}finish();free();return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)project(recordStudy)find_package(OpenCV REQUIRED)include_directories(. ${OpenCV_INCLUDE_DIRS})link_libraries(avformat)
link_libraries(avcodec)
link_libraries(avutil)
link_libraries(swscale)
link_libraries(avdevice)add_executable(recordStudy main.cpp)
target_link_libraries(recordStudy ${OpenCV_LIBS})

牢骚

我是在VirtualBox里装的Ubuntu24.04,干啥都卡,启动都卡

VMBox 7.0.18, Ubuntu 24.04 LTS - virtualbox.org

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB-社区版-本地安装

系统&#xff1a;win10 1. 下载server:Download MongoDB Community Server | MongoDB 我选的zip包 2. 下载shell&#xff1a;MongoDB Shell Download | MongoDB 我选的zip包 3. 启动server 4. 启动shell, 完成

MYSQL函数进阶详解:案例解析(第19天)

系列文章目录 一、MySQL的函数&#xff08;重点&#xff09; 二、MySQL的窗口函数&#xff08;重点&#xff09; 三、MySQL的视图&#xff08;熟悉&#xff09; 四、MySQL的事务&#xff08;熟悉&#xff09; 文章目录 系列文章目录前言一、MySQL的函数1. 聚合函数2. group_c…

Redis 多数据源自定义配置 Spring Boot 升级版

文章目录 1.前言2.git 示例地址3.需求4.代码实现4.1 application.properties 配置文件4.2 获取 application.properties 中的 redis 配置4.2.1 Environment 对象来获取自定义 redis 配置 4.3 初始化 RedisTemplate 对象&#xff0c;并注册到 Spring IOC 容器4.3.1 初始化方法4.…

spring boot (shiro)+ websocket测试连接不上的简单检测处理

1、用前端连接测试的demo一切正常&#xff0c;但是到了项目中连接不上了 一开始以为是地址错&#xff0c;但是换了apifox测试也是不可以。 2、考虑是shiro进行了拦截了&#xff0c;所以就访问不到了地址&#xff0c;那么就放行。 3、再次用apifox测试&#xff0c;成功了。 当然…

马拉松报名小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;赛事信息管理&#xff0c;赛事报名管理&#xff0c;活动商城管理&#xff0c;留言板管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;赛事信息&…

C++:智能指针

目录 前言 1.内存泄漏及其危害 2.内存泄漏分类&#xff1a; 3.如何检测内存泄漏 4.如何避免内存泄漏 一、为什么需要智能指针&#xff1f; 二、智能指针的使用及其原理 1.RAII 2.智能指针 3.std::auto_ptr 4.std::unique_ptr 5.std::shared_ptr 6.std::weak_ptr…

SA 注册流程

目录 1. UE开机后按照3GPP TS 38.104定义的Synchronization Raster搜索特定频点 2.UE尝试检测PSS/SSS&#xff0c;取得下行时钟同步&#xff0c;并获取小区的PCI&#xff1b;如果失败则转步骤1搜索下一个频点&#xff1b;否则继续后续步骤&#xff1b; 3.解析Mib&#xff0c;…

从0到1构建渠道运营体系:实战案例与策略指南

引言 在当今竞争激烈的市场环境中&#xff0c;有效的渠道运营是企业实现产品或服务快速触达目标用户、提升市场份额的关键。从零开始构建一个高效的渠道运营体系&#xff0c;不仅需要深思熟虑的策略规划&#xff0c;还需要灵活应变的实战操作。本文将结合实战案例&#xff0c;…

JDK新特性之协程

在 JVM 中&#xff0c;java 线程直接映射内核线程&#xff0c;因此 java 线程的创建、销毁和调度都要依赖内核态的操作&#xff08;系统调用&#xff09;。而协程是真正的用户线程&#xff0c;如上图所示很多的协程可以映射很少的几个内核线程&#xff0c;并且协程的创建、销毁…

gitee代码初次上传步骤

ps. 前提是已经下载安装gitee 一、在本地项目目录下空白处右击&#xff0c;选择“Git Bash Here” 二、初始化 git init 三、添加、提交代码&#xff08;注意add与点之间的空格&#xff09; git add . git commit -m 添加注释 四、连接、推送到gitee仓库 git remote add …

Renderless 思想正在影响前端开发

本文由前端小伙伴方长_beezen 原创。欢迎大家踊跃投稿。 原文链接&#xff1a;https://juejin.cn/post/7385752495535472655 前言 截止到 2024 年&#xff0c;跨端应用开发所需要考虑的兼容性&#xff0c;已经涵盖了框架、平台和设备类型等多个方面&#xff0c;例如&#xff1…

「ETL趋势」分区支持PostgreSQL、Greenplum、Gauss200, 定时任务支持Kettle

FineDataLink作为一款市场上的顶尖ETL工具&#xff0c;集实时数据同步、ELT/ETL数据处理、数据服务和系统管理于一体的数据集成工具&#xff0c;进行了新的维护迭代。本文把FDL4.1.9最新功能作了介绍&#xff0c;方便大家对比&#xff1a;&#xff08;产品更新详情&#xff1a;…

MYSQL篇二:数据库的操作

文章目录 1. 创建数据库1.1 查看数据库列表1.2 创建与删除数据库 2. 数据的编码问题3. 字符集和校验规则3.1 查看系统默认字符集以及校验规则3.2 查看数据库支持的字符集3.3 查看数据库支持的字符集校验规则3.4 校验规则对数据库的影响 4. 操纵数据库4.1 查看当前是哪一个数据库…

安装docker compose与elasticsearch,kibana

1.docker compose安装 1.1是否已安装docker docker -v 1.2安装docker compose curl -SL https://github.com/docker/compose/releases/download/v2.18.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-composeps:如果网络太慢可直接在博客中下载附属文件 下载后修…

【二】Ubuntu24虚拟机在Mac OS的VMware Fusion下无法联网问题

文章目录 1.环境背景2. 需求背景3. 解决方法3.1 在mac的终端查看虚拟机NAT网络3.2 查看unbuntu节点2的网络配置3.3 问题定位与解决3.3.1 检查是否有冲突3.3.2 冲突解决方法 4. 总结4.1 NAT 网关的原理4.2 VMware Fusion 的 NAT 模式4.3 为什么网关冲突会引起问题4.4 理解配置冲…

python作业一

1. #A.方法一 num int(input("请输入要打印的层数:")) for n in range(1, num1):s ""for i in range(1, n1):s f"{i}" " "print(s) #方法二&#xff1a; iint(input("i:")) for i in range(1,i1):s""for j i…

JavaSE (Java基础):面向对象(下)

8.7 多态 什么是多态&#xff1f; 即同一方法可以根据发送对象的不同而采用多种不同的方式。 一个对象的实际类型是确定的&#xff0c;但可以指向对象的引用的类型有很多。在句话我是这样理解的&#xff1a; 在实例中使用方法都是根据他最开始将类实例化最左边的类型来定的&…

uni-app 自定义支付密码键盘

1.新建组件 payKeyboard .vue <template><view class"page-total" v-show"isShow"><view class"key-list"><view class"list" v-for"(item,index) in keyList" :class"{special:item.keyCode190…

文件操作及部分文件函数的介绍学习(上)

目录 前言 1.为什么要要使用文件&#xff1f; 2.什么是文件&#xff1f; 2.1程序文件 2.2数据文件 2.3文件名 4.文件的打开和关闭 4.1 流和标准流 4.1.1流 4.1.2标准流 4.2文件指针 4.3文件的打开和关闭 结语 前言 Hello&#xff0c;亲爱的小伙伴们&#xff0c;作…

游戏AI的创造思路-技术基础-计算机视觉

让游戏的AI具备“眼睛”和“视觉”&#xff0c;就是通过计算机视觉的方法进行的。现在&#xff0c;越来越多的游戏&#xff0c;特别是动捕类游戏都在使用这个方法。当然&#xff0c;计算机视觉不仅仅用于游戏&#xff0c;越来越多的应用使用到这个技术 目录 1. 定义 2. 发展历…