当前位置: 首页 > news >正文

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.lryc.cn/news/392707.html

相关文章:

  • Fastapi 项目第二天首次访问时数据库连接报错问题Can‘t connect to MySQL server
  • 尚硅谷k8s 2
  • 机器学习---线性回归
  • 字符串去重、集合遍历 题目
  • SQL窗口函数详解
  • 如何用Java写一个整理Java方法调用关系网络的程序
  • 基于STM32设计的管道有害气体检测装置(ESP8266局域网)176
  • iCloud照片库全指南:云端存储与智能管理
  • IDEA中使用Maven打包及碰到的问题
  • TreeMap、HashMap 和 LinkedHashMap 的区别
  • 【跟我学K8S】45天入门到熟练详细学习计划
  • ubuntu下载Nginx
  • 【区分vue2和vue3下的element UI Dialog 对话框组件,分别详细介绍属性,事件,方法如何使用,并举例】
  • docker push 推送镜像到阿里云仓库
  • 伯克利、斯坦福和CMU面向具身智能端到端操作联合发布开源通用机器人Policy,可支持多种机器人执行多种任务
  • 昇思25天学习打卡营第17天(+1)|Diffusion扩散模型
  • 【Leetcode笔记】406.根据身高重建队列
  • Linux 安装pdfjam (PDF文件尺寸调整)
  • python+playwright 学习-90 and_ 和 or_ 定位
  • 亲子时光里的打脸高手,贾乃亮与甜馨的父爱如山
  • MySQL篇-SQL优化实战
  • 【MySQL备份】Percona XtraBackup总结篇
  • 【Git 】规范 Git 提交信息的工具 Commitizen
  • ABB PPC902AE1013BHE010751R0101控制器 处理器 模块
  • 大模型AIGC转行记录(一)
  • element-ui Tree之懒加载叶子节点强制设置父级半选效果
  • Java项目:基于SSM框架实现的高校共享单车管理系统分前后台【ssm+B/S架构+源码+数据库+开题报告+任务书+毕业论文】
  • 【Android】自定义换肤框架02之自定义AssetManager和Resource
  • 熵权法、熵值法、熵权TOPSIS三种方法的实用场景及优劣比较
  • 无人机人员搜救