Qt/C++音视频开发55-加密保存到文件并解密播放

一、前言

为了保证视频文件的安全性,有时候需要对保存的视频文件加密,然后播放的时候解密出来再播放,只有加密解密的秘钥一致时才能正常播放,用ffmpeg做视频文件的加密保存和解密播放比较简单,基于ffmpeg强大的字典参数设计,在avformat_write_header写入头部数据的时候,可以通过万能的av_dict_set来给options设置encryption_scheme/encryption_key/encryption_kid三键值,这样保存后的文件是加密过的,第三方播放器都无法正常播放,需要用ffmpeg打开并设置一样的秘钥才能解密播放,打开这边也是通过av_dict_set来给options设置decryption_key键值,在调用avformat_open_input的时候传入options即可。这种加密解密的应用场景一般在对视频文件要求安全性很高的地方,相当于需要定制播放器才能正常播放,做的好一点的话,还可以自定义格式,文件格式关联到定制的播放器,如果默认的MP4文件格式,可能用户不自觉的还会去双击播放,打不开就会很纳闷,所以针对这种加密过的视频文件一般定义一个自定义的格式保存比较好,拓展名仅仅是个名字,和里面的内容无关,内容都是二进制数据。

查阅资料得知,加密和未加密的文件,就是在头部数据中stbl下新增加了3个box。

  • senc:sample specific encryption data,特定加密数据样本。
  • saio:sample auxiliary information offsets,样本辅助信息偏移量。
  • saiz:sample auxiliary information sizes,样本辅助信息大小。

二、效果图

在这里插入图片描述

三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_demo。

四、功能特点

1. 基础功能

  1. 支持各种音频视频文件格式,比如mp3、wav、mp4、asf、rm、rmvb、mkv等。
  2. 支持本地摄像头设备,可指定分辨率、帧率。
  3. 支持各种视频流格式,比如rtp、rtsp、rtmp、http等。
  4. 本地音视频文件和网络音视频文件,自动识别文件长度、播放进度、音量大小、静音状态等。
  5. 文件可以指定播放位置、调节音量大小、设置静音状态等。
  6. 支持倍速播放文件,可选0.5倍、1.0倍、2.5倍、5.0倍等速度,相当于慢放和快放。
  7. 支持开始播放、停止播放、暂停播放、继续播放。
  8. 支持抓拍截图,可指定文件路径,可选抓拍完成是否自动显示预览。
  9. 支持录像存储,手动开始录像、停止录像,部分内核支持暂停录像后继续录像,跳过不需要录像的部分。
  10. 支持无感知切换循环播放、自动重连等机制。
  11. 提供播放成功、播放完成、收到解码图片、收到抓拍图片、视频尺寸变化、录像状态变化等信号。
  12. 多线程处理,一个解码一个线程,不卡主界面。

2. 特色功能

  1. 同时支持多种解码内核,包括qmedia内核(Qt4/Qt5/Qt6)、ffmpeg内核(ffmpeg2/ffmpeg3/ffmpeg4/ffmpeg5)、vlc内核(vlc2/vlc3)、mpv内核(mpv1/mp2)、海康sdk、easyplayer内核等。
  2. 非常完善的多重基类设计,新增一种解码内核只需要实现极少的代码量,就可以应用整套机制。
  3. 同时支持多种画面显示策略,自动调整(原始分辨率小于显示控件尺寸则按照原始分辨率大小显示,否则等比缩放)、等比缩放(永远等比缩放)、拉伸填充(永远拉伸填充)。所有内核和所有视频显示模式下都支持三种画面显示策略。
  4. 同时支持多种视频显示模式,句柄模式(传入控件句柄交给对方绘制控制)、绘制模式(回调拿到数据后转成QImage用QPainter绘制)、GPU模式(回调拿到数据后转成yuv用QOpenglWidget绘制)。
  5. 支持多种硬件加速类型,ffmpeg可选dxva2、d3d11va等,mpv可选auto、dxva2、d3d11va,vlc可选any、dxva2、d3d11va。不同的系统环境有不同的类型选择,比如linux系统有vaapi、vdpau,macos系统有videotoolbox。
  6. 解码线程和显示窗体分离,可指定任意解码内核挂载到任意显示窗体,动态切换。
  7. 支持共享解码线程,默认开启并且自动处理,当识别到相同的视频地址,共享一个解码线程,在网络视频环境中可以大大节约网络流量以及对方设备的推流压力。国内顶尖视频厂商均采用此策略。这样只要拉一路视频流就可以共享到几十个几百个通道展示。
  8. 自动识别视频旋转角度并绘制,比如手机上拍摄的视频一般是旋转了90度的,播放的时候要自动旋转处理,不然默认是倒着的。
  9. 自动识别视频流播放过程中分辨率的变化,在视频控件上自动调整尺寸。比如摄像机可以在使用过程中动态配置分辨率,当分辨率改动后对应视频控件也要做出同步反应。
  10. 音视频文件无感知自动切换循环播放,不会出现切换期间黑屏等肉眼可见的切换痕迹。
  11. 视频控件同时支持任意解码内核、任意画面显示策略、任意视频显示模式。
  12. 视频控件悬浮条同时支持句柄、绘制、GPU三种模式,非绝对坐标移来移去。
  13. 本地摄像头设备支持指定设备名称、分辨率、帧率进行播放。
  14. 录像文件同时支持打开的视频文件、本地摄像头、网络视频流等。
  15. 瞬间响应打开和关闭,无论是打开不存在的视频或者网络流,探测设备是否存在,读取中的超时等待,收到关闭指令立即中断之前的操作并响应。
  16. 支持打开各种图片文件,支持本地音视频文件拖曳播放。
  17. 视频控件悬浮条自带开始和停止录像切换、声音静音切换、抓拍截图、关闭视频等功能。
  18. 音频组件支持声音波形值数据解析,可以根据该值绘制波形曲线和柱状声音条,默认提供了声音振幅信号。
  19. 标签和图形信息支持三种绘制方式,绘制到遮罩层、绘制到图片、源头绘制(对应信息可以存储到文件)。
  20. 各组件中极其详细的打印信息提示,尤其是报错信息提示,封装的统一打印格式。针对现场复杂的设备环境测试极其方便有用,相当于精确定位到具体哪个通道哪个步骤出错。
  21. 代码框架和结构优化到最优,性能强悍,持续迭代更新升级。
  22. 源码支持Qt4、Qt5、Qt6,兼容所有版本。

3. 视频控件

  1. 可动态添加任意多个osd标签信息,标签信息包括名字、是否可见、字号大小、文本文字、文本颜色、标签图片、标签坐标、标签格式(文本、日期、时间、日期时间、图片)、标签位置(左上角、左下角、右上角、右下角、居中、自定义坐标)。
  2. 可动态添加任意多个图形信息,这个非常有用,比如人工智能算法解析后的图形区域信息直接发给视频控件即可。图形信息支持任意形状,直接绘制在原始图片上,采用绝对坐标。
  3. 图形信息包括名字、边框大小、边框颜色、背景颜色、矩形区域、路径集合、点坐标集合等。
  4. 每个图形信息都可指定三种区域中的一种或者多种,指定了的都会绘制。
  5. 内置悬浮条控件,悬浮条位置支持顶部、底部、左侧、右侧。
  6. 悬浮条控件参数包括边距、间距、背景透明度、背景颜色、文本颜色、按下颜色、位置、按钮图标代码集合、按钮名称标识集合、按钮提示信息集合。
  7. 悬浮条控件一排工具按钮可自定义,通过结构体参数设置,图标可选图形字体还是自定义图片。
  8. 悬浮条按钮内部实现了录像切换、抓拍截图、静音切换、关闭视频等功能,也可以自行在源码中增加自己对应的功能。
  9. 悬浮条按钮对应实现了功能的按钮,有对应图标切换处理,比如录像按钮按下后会切换到正在录像中的图标,声音按钮切换后变成静音图标,再次切换还原。
  10. 悬浮条按钮单击后都用名称唯一标识作为信号发出,可以自行关联响应处理。
  11. 悬浮条空白区域可以显示提示信息,默认显示当前视频分辨率大小,可以增加帧率、码流大小等信息。
  12. 视频控件参数包括边框大小、边框颜色、焦点颜色、背景颜色(默认透明)、文字颜色(默认全局文字颜色)、填充颜色(视频外的空白处填充黑色)、背景文字、背景图片(如果设置了图片优先取图片)、是否拷贝图片、缩放显示模式(自动调整、等比缩放、拉伸填充)、视频显示模式(句柄、绘制、GPU)、启用悬浮条、悬浮条尺寸(横向为高度、纵向为宽度)、悬浮条位置(顶部、底部、左侧、右侧)。

五、相关代码

bool FFmpegSave::initStream()
{AVDictionary *options = NULL;QByteArray fileData = fileName.toUtf8();const char *url = fileData.data();//既可以是保存到文件也可以是推流(对应格式要区分)const char *format = "mp4";if (videoIndexIn < 0 && audioCodecName == "mp3") {format = "mp3";}if (fileName.startsWith("rtmp://")) {format = "flv";} else if (fileName.startsWith("rtsp://")) {format = "rtsp";av_dict_set(&options, "stimeout", "3000000", 0);av_dict_set(&options, "rtsp_transport", "tcp", 0);} else if (fileName.startsWith("udp://")) {format = "mpegts";}//如果存在秘钥则启用加密QByteArray cryptoKey = this->property("cryptoKey").toByteArray();if (!cryptoKey.isEmpty()) {av_dict_set(&options, "encryption_scheme", "cenc-aes-ctr", 0);av_dict_set(&options, "encryption_key", cryptoKey.constData(), 0);av_dict_set(&options, "encryption_kid", cryptoKey.constData(), 0);}//开辟一个格式上下文用来处理视频流输出(末尾url不填则rtsp推流失败)int result = avformat_alloc_output_context2(&formatCtx, NULL, format, url);if (result < 0) {debug(result, "创建格式", "");return false;}//创建输出视频流if (!this->initVideoStream()) {goto end;}//创建输出音频流if (!this->initAudioStream()) {goto end;}//打开输出文件if (!(formatCtx->oformat->flags & AVFMT_NOFILE)) {result = avio_open(&formatCtx->pb, url, AVIO_FLAG_WRITE);if (result < 0) {debug(result, "打开输出", "");goto end;}}//写入文件开始符result = avformat_write_header(formatCtx, &options);if (result < 0) {debug(result, "写文件头", "");goto end;}return true;end://关闭释放并清理文件this->close();this->deleteFile(fileName);return false;
}void FFmpegThread::initOption()
{//设置缓存大小(1080p可将值调大/现在很多摄像机是2k可能需要调大/一般2k是1080p的四倍)av_dict_set(&options, "buffer_size", "8192000", 0);//设置超时断开连接时间(单位微秒/3000000表示3秒)av_dict_set(&options, "stimeout", "3000000", 0);//设置最大时延(单位微秒/1000000表示1秒)av_dict_set(&options, "max_delay", "1000000", 0);//自动开启线程数av_dict_set(&options, "threads", "auto", 0);//通信协议采用tcp还是udp(udp优点是无连接/在网线拔掉以后十几秒钟重新插上还能继续接收/缺点是网络不好的情况下会丢包花屏)if (transport != "auto") {av_dict_set(&options, "rtsp_transport", transport.toUtf8().constData(), 0);}//开启无缓存(rtmp等视频流不建议开启)//av_dict_set(&options, "fflags", "nobuffer", 0);//av_dict_set(&options, "fflags", "discardcorrupt", 0);//有些视频网站根据这个头部消息过滤不让ffmpeg访问需要模拟成其他的//av_dict_set(&options, "user_agent", "libmpv", 0);av_dict_set(&options, "user_agent", "Mozilla", 0);//增加rtp/sdp支持(后面发现不要加)if (videoUrl.endsWith(".sdp")) {//av_dict_set(&options, "protocol_whitelist", "file,rtp,udp", 0);}//设置分辨率帧率等参数if (videoType == VideoType_Camera || videoType == VideoType_Desktop) {//设置分辨率if (bufferSize != "0x0") {av_dict_set(&options, "video_size", bufferSize.toUtf8().constData(), 0);}//设置帧率if (frameRate > 0) {av_dict_set(&options, "framerate", QString::number(frameRate).toUtf8().constData(), 0);}//设置坐标XY以及是否采集鼠标指针if (videoType == VideoType_Desktop) {//av_dict_set(&options, "draw_mouse", "0", 0);//av_dict_set(&options, "show_region", "1", 0);int offsetX = this->property("offsetX").toInt();int offsetY = this->property("offsetY").toInt();
#ifdef Q_OS_WIN//windows上通过设置offset_x/offset_y来设置偏移值av_dict_set(&options, "offset_x", QString::number(offsetX).toUtf8().constData(), 0);av_dict_set(&options, "offset_y", QString::number(offsetY).toUtf8().constData(), 0);
#else//linux系统通过设备名称带上偏移值传入videoUrl += QString("+%1,%2").arg(offsetX).arg(offsetY);
#endif}//设置输入格式(具体要看设置是否支持)//后面改成了统一转成标准yuv420所以不用设置也没有任何影响//av_dict_set(&options, "input_format", "mjpeg", 0);}//如果设置了秘钥则需要启用解密if (!secretKey.isEmpty()) {QByteArray cryptoKey = this->property("cryptoKey").toByteArray();av_dict_set(&options, "decryption_key", cryptoKey.constData(), 0);}
}

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

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

相关文章

FPGA:卷积编码及维特比译码仿真

FPGA&#xff1a;卷积编码及维特比译码仿真 本篇记录一下在FPGA中完成卷积编码和维特比译码的过程&#xff0c;通过代码解释编码的过程和译码的过程&#xff0c;便于理解&#xff0c;同时也方便移植到其他工程中。 1. 准备工作 卷积编译码IP核—convolutionIP核和viterbiIP核…

STM32F407 串口使用DMA方式通信

DMA的原理&#xff0c;就是利用寄存器方式进行读写&#xff0c;这样的好处就是相对于中断触发&#xff08;往往一个字节字节的就中断一次&#xff09;&#xff0c;CPU中断次数大大降少&#xff0c;提高了效率&#xff0c;但也影响了实时性。总体来说&#xff0c;对于一般的应用…

Oracle 12c自动化管理特性的新进展:自动备份、自动恢复和自动维护功能的优势|oracle 12c相对oralce 11g的新特性(3)

一、前言: 前面几期讲解了oracle 12c多租户的使用、In-Memory列存储来提高查询性能以及数据库的克隆、全局数据字典和共享数据库资源的使用 今天我们讲讲oracle 12c的另外的一个自动化管理功能新特性:自动备份、自动恢复、自动维护的功能 二、自动备份、自动恢复、自动维护…

Android开发笔记 :理解Fragment

Android开发笔记&#xff1a;理解Fragment 导言 本篇文章产生的原因很简单&#xff0c;就是我在了解Android Jetpack中的Lifecycle框架时发现Lifecycle具体时间和状态的更新都是由一个名为ReportFragment的Fragment来跟踪的&#xff0c;为了更好的了解Fragment是如何追踪Activ…

机器学习的主要内容

分类任务 回归任务 有一些算法只能解决回归问题有一些算法只能解决分类问题有一些算法的思路既能解决回归问题&#xff0c;又能解决分类问题 一些情况下&#xff0c; 回归任务可以转化为分类任务&#xff0c; 比如我们预测学生的成绩&#xff0c;然后根据学生的成绩划分为A类、…

LeetCode刷题

一 【移除元素】 原题链接&#xff1a;27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用…

基因组注释(Annotation)

基因组组装完成后&#xff0c;或者是完成了草图&#xff0c;就不可避免遇到一个问题&#xff0c;需要对基因组序列进行注释。注释之前首先得构建基因模型&#xff0c;有三种策略&#xff1a; 从头注释(de novo prediction)&#xff1a;通过已有的概率模型来预测基因结构&#…

C++17中std::filesystem::path的使用

C17引入了std::filesystem库(文件系统库, filesystem library)。这里整理下std::filesystem::path的使用。 std::filesystem::path&#xff0c;文件系统路径&#xff0c;提供了对文件系统及其组件(例如路径、常规文件和目录)执行操作的工具。此path类主要用法包括&#x…

【Kafaka实现高吞吐量、低延迟的底层原理】

文章目录 Kafaka实现高吞吐量、低延迟的底层原理顺序写入Page Cache零拷贝分区分段索引批量读写批量压缩 Kafaka实现高吞吐量、低延迟的底层原理 Kafka虽然是基于磁盘做的数据存储&#xff0c;但却具有高并发、高吞吐量、低延时的特点&#xff0c;其吞吐量动辄几万、几十上百万…

点分治维护dp+连通块上新型dp思路+乘积方面进行根号dp:0922T4

首先连通块&#xff0c;所以点分治肯定是 Trick1 钦定选根的连通块dp 对于钦定选根的连通块dp&#xff0c;有一种常见思路 先对原树求其dfn序&#xff0c;按dfn序倒序求解 具体的&#xff0c;对于当前点 i i i&#xff08;注意这里都是指dfn序&#xff09;&#xff0c;我们…

设计模式之解析器(Interpreter)的C++实现

1、解析模式的提出 在软件开发的过程中&#xff0c;需要实现一种需求&#xff0c;该需求的结构稳定&#xff0c;但是需求的业务内容会频繁变化&#xff0c;如果使用普通语法实现需求&#xff0c;需要经常更新代码&#xff0c;不具有灵活性。可以使用解析器模式解决实现该类需求…

Spring面试题16:Spring框架中的单例bean是线程安全的吗?Spring框架中bean的生命周期?哪些是重要的bean生命周期方法?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring框架中的单例bean是线程安全的吗?为什么? 是的,Spring框架中的单例Bean是线程安全的。 Spring中的单例Bean默认是在容器启动时创建的,并…

Hive参数与性能调优-V2.0

Hive作为大数据平台举足轻重的框架&#xff0c;以其稳定性和简单易用性也成为当前构建企业级数据仓库时使用最多的框架之一。 但是如果我们只局限于会使用Hive&#xff0c;而不考虑性能问题&#xff0c;就难搭建出一个完美的数仓&#xff0c;所以Hive性能调优是我们大数据从业…

【计算机网络笔记一】网络体系结构

IP和路由器概念 两台主机如何通信呢&#xff1f; 首先&#xff0c;主机的每个网卡都有一个全球唯一地址&#xff0c;MAC 地址&#xff0c;如 00:10:5A:70:33:61 查看 MAC 地址&#xff1a; windows: ipconfig / alllinux&#xff1a;ifconfig 或者 ip addr 同一个网络的多…

Qt5开发及实例V2.0-第十六章-Qt汽车销售管理系统实例

Qt5开发及实例V2.0-第十六章-Qt汽车销售管理系统实例 Qt汽车销售管理系统实例一、 系统概述二、 系统模块三、 界面设计四、 代码实现五、 总结 本章相关例程源码下载 Qt汽车销售管理系统实例 一、 系统概述 汽车销售管理系统是一款基于QT5框架开发的管理系统&#xff0c;主要…

iPhone辐射超标,发布三年突然禁售了

昨晚 iPhone 15 预售大家抢到了吗&#xff1f; 虽然13日发布会后大家的反应十分冷静&#xff0c;但身体还是很诚实&#xff0c;官网都排到6-7周以后了... 在大伙都争着第一波尝鲜的时候&#xff0c;有一个地方正准备禁售 iPhone 。 不用想肯定是欧盟某个国家啦&#xff0c;这…

肖sir__mysql之存储练习题__013

实验 一、 实验要求&#xff1a; 理解存储过程的概念掌握存储过程的语法格式、使用方法掌握存 储过程的创建、执行 二、实验前提&#xff1a; – drop table if exists student; – Create table student – (Id varchar(255), #学号 – Name varchar(255), #姓名 – Roomid…

滴滴一面:线程池任务,如何设置优先级?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如滴滴、极兔、有赞、希音、百度、网易的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 如何设计线程池&#xff1f;请手写一个简单线程池&#xff1f; 就在昨天&…

认识面向对象-PHP8知识详解

面向对象编程&#xff0c;也叫面向对象程序设计&#xff0c;是在面向过程程序设计的基础上发展而来的&#xff0c;它比面向过程编程具有更强的灵活性和扩展性。 它用类、对象、关系、属性等一系列东西来提高编程的效率&#xff0c;其主要的特性是可封装性、可继承性和多态性。…

NIO简单介绍

一、什么是NIO 1、Java NIO全称java non-blocking IO&#xff0c; 是指JDK提供的新API。从JDK1.4开始&#xff0c;Java提供了一系列改进的输入/输出的新特性&#xff0c;被统称为NIO(即New IO)&#xff0c;是同步非阻塞的 2、NIO有三大核心部分: Channel(通道)&#xff0c; Buf…