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

使用FFmpeg+SDL2读取本地摄像头并渲染

核心流程分为设备初始化、数据捕获、解码、格式转换和渲染五个阶段。

一、整体流程

初始化摄像头
FFmpeg 捕获视频流
解码为 YUV 帧
YUV 转 RGB
SDL2 渲染到窗口

二、代码实现

1. 枚举并打开摄像头设备
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>// 枚举设备(Windows)
avdevice_register_all();
AVDictionary *options = NULL;
av_dict_set(&options, "list_devices", "true", 0);
AVFormatContext *fmt_ctx = NULL;
avformat_open_input(&fmt_ctx, "video=dummy", av_find_input_format("dshow"), &options);// 打开摄像头(Linux V4L2)
avformat_open_input(&fmt_ctx, "/dev/video0", av_find_input_format("v4l2"), NULL);

​:Windows 设备名可能乱码,需通过 ffmpeg -list_devices true -f dshow -i dummy 获取准确名称7。


2. 配置视频流与解码器
// 查找视频流索引
int video_stream_index = -1;
for (int i = 0; i < fmt_ctx->nb_streams; i++) {if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream_index = i;break;}
}// 初始化解码器(H.264/MJPEG)
AVCodecParameters *codec_par = fmt_ctx->streams[video_stream_index]->codecpar;
AVCodec *codec = avcodec_find_decoder(codec_par->codec_id);
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codec_ctx, codec_par);
avcodec_open2(codec_ctx, codec, NULL);

3. 初始化 SDL2 渲染窗口

使用SDL窗口

SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Camera", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, codec_ctx->width, codec_ctx->height, SDL_WINDOW_SHOWN);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING,codec_ctx->width, codec_ctx->height);

获取 Qt 窗口句柄

// 在 Qt 窗口中创建一个容器(如 QLabel)
QLabel *sdlContainer = new QLabel(this);
sdlContainer->resize(640, 480);// 将 Qt 窗口句柄传递给 SDL2
SDL_Window *sdlWindow = SDL_CreateWindowFrom((void*)sdlContainer->winId());

4. 帧处理循环(解码 → 转换 → 渲染)​
AVPacket *pkt = av_packet_alloc();
AVFrame *frame = av_frame_alloc();
SwsContext *sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,codec_ctx->width, codec_ctx->height, AV_PIX_FMT_YUV420P,SWS_BILINEAR, NULL, NULL, NULL);while (1) {av_read_frame(fmt_ctx, pkt);  // 读取数据包if (pkt->stream_index == video_stream_index) {avcodec_send_packet(codec_ctx, pkt);if (avcodec_receive_frame(codec_ctx, frame) == 0) {// YUV 格式转换(例如 MJPEG → YUV420)AVFrame *yuv_frame = av_frame_alloc();sws_scale(sws_ctx, frame->data, frame->linesize, 0, frame->height,yuv_frame->data, yuv_frame->linesize);// SDL 渲染SDL_UpdateYUVTexture(texture, NULL,yuv_frame->data[0], yuv_frame->linesize[0],  // Yyuv_frame->data[1], yuv_frame->linesize[1],  // Uyuv_frame->data[2], yuv_frame->linesize[2]); // VSDL_RenderClear(renderer);SDL_RenderCopy(renderer, texture, NULL, NULL);SDL_RenderPresent(renderer);}}av_packet_unref(pkt);
}
http://www.lqws.cn/news/592075.html

相关文章:

  • 07 Springboot+netty+mqtt服务端实现【重构】
  • php-mqtt/client 发布、订阅
  • 学习threejs,使用自定义GLSL 着色器,生成艺术作品
  • Redis-渐进式遍历
  • Android实现仿iOS风格滚动时间选择器
  • 【机器学习深度学习】理解欠拟合、拟合、过拟合
  • React安装使用教程
  • Linux->进程控制(精讲)
  • 文心一言开源版测评:能力、易用性与价值的全面解析
  • 通过http调用来访问neo4j时报错,curl -X POST 执行指令报错
  • 博途多重背景、参数实例
  • swing音频输入
  • 跨境证券交易系统合规升级白皮书:全链路微秒风控+开源替代,护航7月程序化交易新规落地
  • 7.可视化的docker界面——portainer
  • CloudBase AI ToolKit实战:从0到1开发一个智能医疗网站
  • LLM中的思维链,仅仅在提示词中加上思维链,让模型输出,和加上思维链限制模型输出答案,这两方式模型是不是进行了思考的
  • 鸿蒙Next开发中三方库使用指南之-nutpi-privacy_dialog集成示例
  • 用“做饭”理解数据分析流程(Excel三件套实战)​
  • 网站崩溃的幕后黑手:GPTBot爬虫的流量冲击
  • 论文阅读:Align and Prompt (ALPRO 2021.12)
  • 零开始git使用教程-传html文件
  • 浅谈Docker Kicks in的应用
  • 51单片机制作万年历
  • 观察者模式
  • 新版本 Spring Data Jpa + QueryDSL 使用教程
  • TensorFlow源码深度阅读指南
  • 【科研绘图系列】基于R语言的复杂热图绘制教程:环境因素与染色体效应的可视化
  • C#程序设计简介
  • 9-2 MySQL 分析查询语句:EXPLAIN(详细说明)
  • Milvus docker-compose 部署