自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(30)
  • 收藏
  • 关注

原创 Electron 主进程和渲染进程通信

每个 Electron 应用都有一个单一的主进程,BrowserWindow 类的每个实例创建一个应用程序窗口,且在单独的渲染器进程中加载一个网页。本章我们来介绍下,如何在主进程和渲染器进程之间传递消息。

2025-12-20 15:06:37 535

原创 Electron 预加载脚本

Electron 的主进程是一个拥有操作系统完整访问权限的 Node.js 环境。除了 Electron 内置模块外,你还可以调用 Node.js 核心模块,以及所有通过 npm 安装的第三方包。另一方面,出于安全考量,渲染进程默认运行在网页环境中,而非 Node.js 环境。为了衔接 Electron 中不同类型的进程,我们需要使用一种名为「预加载」(preload)的特殊脚本。

2025-12-20 15:06:14 497

原创 第一个 Electron 程序

为了解决渲染进程无法访问 process 的问题,我们可以修改 index.js,允许渲染进程访问 node.js 环境和关闭上下文隔离都是不安全的行为,我们可以通过预加载脚本,把主进程的部分函数和属性暴露给渲染进程。这里解释下什么是渲染进程,什么是主进程,简单来说,”main" 中声明的 index.js 文件以及加载的 js 都是属于主进程,BrowserWindow 加载执行的 html js css 都是属于渲染进程。执行完成后,将会生成一个 package.json 文件,如下所示。

2025-12-14 17:22:25 595

原创 electron 安装

Electron 是一个用 HTML CSS 和 javaScript 开发应用程序的框架,使用 Chromium 作为前端,Node.js 作为后端。什么是 Chromium,Chromium 是网页渲染引擎,负责解析和显示网页,什么是 Node.js,我们可以简单的理解为 javascript 是只能运行在浏览器环境下的,而 node.js 使得 javascrit 能够运行在本地环境。与之相反的是 Emscripten,它使得 C++ 能够在浏览器运行。

2025-12-14 11:33:44 977

原创 基于 libwebsockets 实现 websocket 服务

这个处理回调函数的地方我用了线程处理,因为我在接收消息回调里调用了发送消息接口,我在消息处理函数和发送消息函数里都加锁了,接收到消息时,发送消息,此时由于接收消息这里加锁了,发送消息函数得不到执行,接收消息回调就无法结束,锁也就无法释放。4. 回调函数实现,由于回调函数不能是普通成员函数,所以我们需要在静态成员函数中获取 this 指针,然后调用实际的回调。2. 设置参数,并创建 libwebsockets 上下文。3. 创建一个循环,调用 lws_service 处理事件。1.定义一个协议数组。

2025-12-02 19:51:20 276

原创 ffmpeg 使用滤镜实现播放倍速

avfilter_link 用于链接滤镜,上面的代码表示数据从 m_videoSrcFilterCtx 流向 videoSpeedCtx,再从 videoSpeedCtx 流向 m_videoSinkFilterCtx,很好理解,数据从输入滤镜开始,流向中间的滤镜,有中间的滤镜进行处理,再流向下一个滤镜,最终流入到输出滤镜。0 表示滤镜输入,输出端口的索引,有的滤镜有多个输入或输出,比如我们如果想把两段音频合并到一起,第一段音频就传入到融合滤镜的第一个端口,第二段音频传入到第二个端口。

2025-11-03 19:54:37 895

原创 ffmpeg 交叉编译

3. 安装交叉编译的pkg-config。下载 x264 源码,打开源码目录。1. 安装交叉编译工具链。4. 编译 ffmpeg。2. 编译 x264。

2025-10-20 20:17:49 201

原创 ffmpeg 硬解码

【代码】ffmpeg 硬解码。

2025-09-29 19:14:37 340

原创 GitLab CI/CD 入门

CI/CD 用于自动化构建,打包,测试,部署了 CI/CD 后,当我们提交代码后,将会自动执行 CI/CD 任务,本文将介绍如何使用 Docker 搭建一个 CI/CD 的自动化构建环境。如果希望 docker 使用的是本地镜像,则需要修改。docker 的镜像的构建可以参考上一篇文章。编写 .gitlab-ci.yml 文件。1. 下载 gitlab-runner。2. 注册 runner 到项目中。

2025-09-25 17:25:47 423

原创 Qt 编译环境 docker 搭建

使用 Qt 在线安装器或者离线安装包搭建 Qt 环境经常会因为网络因素导致失败,因此本文将使用本地的 Qt 环境来搭建 docker。首先创建一个文件夹,存放 Dockerfile 和 Qt 目录。把本地环境下的 Qt 拷贝到 local-qt。编写 Dockerfile。

2025-09-25 11:03:42 259

原创 ffmpeg 结合 QOpenGLWidget 实现视频播放

增加音频播放功能,增加图片格式转化(上篇文章是写在 openglwidget 里,由于 yuv 标准不同,可能某些视频显示会不太对),修复了时钟计时不准导致音视频不同步问题,如时钟线程 sleep 时,时钟还未更新,会导致计算播放时间有问题。初始值为线程数,每一个线程退出,数量减 1,stop 时,视频解码和音频解码线程可能还在某次循环内,这时如果 close,会导致解码器被释放掉,解码时又用到了,导致崩溃。VideoDecoder.cpp 代码如下。VideoDecoder.h 代码如下。

2025-09-21 17:09:35 363

原创 ffmpeg 结合 Qt 实现视频播放(暂时没有播放音频)

视频中可能是这样存储的 [V0, V1, V2][A0, A1, A2][V3, V4, V5][A3, A4, A5][V6, V7, V8][A6, A7, A8][V9][A9] V 表示视频,A 表示音频,所以如果读取一个包,解码,播放。所以我们将视频和音频读到队列中,再开启线程,同步对音频和视频进行解码。如果小于当前计时器,说明已经过了当前时间,丢弃该帧(一般情况下,解码的速度应该是比播放快的,而且都解码完成了再丢弃,时间已经花费了,丢弃好像意义也不大?同时,创建了一个线程用于计时。

2025-09-11 19:55:38 176

原创 ffmpeg 入门(八、音频转码)

在上篇文章中,我们对一个视频进行了解码并重新编码,但是在处理音频时,我们使用了原视频的音频参数,因为对于不同的编码器,需要的音频帧大小不同,而 swr_convert 不会对音频帧的大小进行处理,本文增加了对于音频帧大小变化的情况的处理。代码中分成了两种情况进行处理,如果是支持可变帧大小的编码器,直接把帧发送给编码器,如果是固定帧大小的,则写入 fifo 缓冲区,再从 fifo 读取 帧。

2025-09-02 19:50:47 377

原创 ffmpeg 入门(七、音视频编码)

在编码模块中,音频的格式是直接拷贝源文件的格式的,音频处理需要做格式转换外,不同编码器要求的帧大小有所不同,因此还需额外处理。

2025-08-28 19:55:19 212

原创 ffmpeg 入门(六、视频解码小结)

open 函数执行了打开视频文件,初始化解码器,初始化格式转换实例等操作。close 释放内存。decode 进行解码和格式转换。将之前的代码封装成一个类。

2025-08-11 20:07:51 136

原创 ffmpeg 入门(五、音频帧解码及重采样)

与视频格式转换类似的是,首先需要先创建一个格式转换的实例,不同的是,音频格式转换需要先设置参数并分配一个格式转换实例,再调用 swr_init 进行初始化。和视频帧类似,音频解码也需要进行格式转换,一方面不同视频的音频格式不同,转换成统一格式方便后续处理,另外一方面,有的格式适合存储,有的格式适合编解码。音频的解码和视频的类似,查找音频流,查找解码器,打开解码器实例,解码流程也是一样的,把对应的视频解码器实例替换成音频解码器实例即可。

2025-08-05 20:24:42 163

原创 ffmpeg 入门(四、视频帧格式转换)

解码时 AVFrame 对象只需要调用 av_frame_alloc() 即可,当调用 avcodec_receive_frame(video_decode_ctx, frame) 时,​​解码器内部会自动为 frame 分配缓冲区​​。完整代码展示,这段代码功能和上篇文字功能一致,区别在于,上一篇的格式转换放在了 save_frame_to_image,而现在放在了 main 里,这样主要可以把未学习到的内容放在 save_frame_to_image,以便阅读。

2025-07-22 20:13:06 406

原创 ffmpeg 入门(三、解码视频帧)

上面的说明是 ffmpeg 对 av_read_frame 的注释,从这里看来,视频帧应该是不需要循环解码的,但是查找资料,都是需要循环解码的,考虑到 I 帧,P 帧,B帧之类的,即当前帧需依赖后续的帧来进行解码,所以可能后续输出多个帧。笔者尝试了几个视频,两个方法解码出的帧数并无差别,但查阅 ffmpeg ffmpeg/doc/examples/decode_video.c 后,里面也是循环接收帧的,因此还是建议用第二段代码。对于音频,若每帧大小固定(如PCM或ADPCM),则包含整数个帧;

2025-07-19 16:24:28 318

原创 ffmpeg 入门(二、打开视频文件)

输出参数,指向 AVFormatContext 的指针。函数成功后,该指针将被初始化为有效的上下文。使用完毕后需通过 avformat_close_input() 释放。指定输入格式(如 av_find_input_format(“mp4”))。通常设为 NULL,让 FFmpeg 自动探测格式。如果 decoder_ret 不为 NULL,自动查找并返回与该流匹配的解码器。传递额外选项(如网络超时、缓冲区大小)

2025-07-10 20:20:20 453

原创 ffmpeg 入门 (一 、ffmpeg 重要库和数据结构介绍 )

提供音视频编解码器的实现。

2025-07-08 19:33:36 716

原创 h264 转 mp4

在使用 ffmpeg 处理 h264 转 mp4 时,生成的 mp4 无法播放,经排查发现是原始数据包没有时间戳信息。

2025-04-09 17:09:12 238

原创 Qt WebAssembly lineedit 中文输入

Qt WebAssembly 中的 lineedit 无法输入中文,在此实现了个 MLineEdit 类,将 QLineEdit 提升为 MLineEdit 即可实现中文输入。

2025-03-11 10:16:17 225

原创 Qt WebAssembly 网络请求

其基本思想是: 通过 emscripten::val::global("fetch") 获取 fetch 函数来进行网络请求,使用emscripten::function 把函数暴露给 javascript,再通过 emscripten::val::call 来调用函数。代码本身还有许多不完善的地方,比如请求头和参数可以提供接口供外部调用,通过条件编译来实现 webassembly 和 其它构建套件的兼容。

2025-02-25 20:48:55 433

原创 ffmpeg 编译

2. 自行编译(我自己编译的时候没有需要安装这些,有些可能是其它工具需要所以已经安装过了,有些可能是系统自带的,也可能不是必须的,是编译选择了某些选项才需要的,所以可以先跳过,出错了再回来看需要什么)其中 home、usr、opt 这个都和 linux 的类似,也就是说如果你把 ffmpeg 安装路径设为 usr/local/ffmpeg,之后编译完成后可以在这里的 usr 找到它。--enable-sdl2 这个是启用关于音频的部分,--disable-asm 是关闭汇编代码优化的。

2025-02-24 22:28:40 1492

原创 Qt WebAssembly 本地文件读取

通过 set 的方式把对象指针和函数属性字符串传给 input,onchange 有点类似于 qml 里的槽函数,input.set(std::string("onchange").c_str(), emscripten::val::module_property("onFileChange"));把 this 指针是为了后面发送信号用,web 的文件读取是异步的,因此需要通过回调函数等方式获取到文件内容。这里也是同上面一样,set 属性,绑定 函数指针和属性,然后发送信号。

2025-02-24 19:52:33 735

原创 Qt stylesheet 调试工具

对原来的 Qt stylesheet 调试工具做了 Qt 6 适配

2025-02-15 16:43:09 462

原创 linuxdeployqt 工具的编译和使用

第二种,如果有多个可执行文件依赖这个库,需要拷贝多份,问题在于,比如说,这个库用来操作数据库多个库就会对应多个数据库,但是实际需要的是同一个数据库。然后我遇到的问题是,我的程序生成了一个可执行文件,和多个库,可执行文件依赖这些库。linuxdeployqt,这个工具的主要原理就是 利用 ldd 找到程序运行所需要的库, 拷贝到 lib,然后把可执行文件的依赖 通过 pat。在这里,是比较 glcv 的版本,不知道版本过高会怎么样,注释,重新编译(注释掉,编译,打包后面也成功了).AppImage 文件。

2025-02-14 18:25:53 781 1

原创 Qt6 QtCipherSqlitePlugin 编译

最近需要用到 sqlite 数据库,但是 sqlite 数据库不支持加密,需要使用 SQLCipher,网上教程多是说直接用 QCreator 打开编译即可,实际我在编译中遇到了一些问题在此记录一下。至此,sqlitecipher 编译完成,但是 test,testapp 仍报错,在其 exe 同级目录新建目录 sqldrivers 把刚刚编译好的库放入即可。这个信号有三个参数,但是只传了一个,这里比较奇怪,同一个信号发送了两次,没看懂,注释掉报错的地方,如果有大佬了解,烦请指正。

2025-02-07 23:03:13 746

原创 结合 shared_ptr 的代码来分析下循环引用是怎么产生的

在代码中,创建了 A 和 B 分别一个实例,其中 pa 指向 A 实例的内存 ,pb 指向 B 实例的内存例,他们的引用计数 +1,之后,B 的成员变量 p 也指向了 A实例的 内存,引用计数 +1, 另一个同理。上文中提到,智能指针,本质上是一个局部变量,在其生命周期结束时,释放内存。所以,程序结束时,pa,pb 各自调用了一次析构函数,引用计数变为 1,所以没有释放托管指针的内存。pa 释放内存的时机是什么呢,pa 的 生命周期结束,以及 B 实例的内存释放(这时候,B里的智能指针生命周期结束)。

2024-12-07 19:45:26 158

原创 自己实现shared_ptr 和 unique_ptr

shared_ptr 和 unique_ptr 原理与实现

2024-12-05 18:31:15 451

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除