## 一、前言

一直都想搞个安卓版本的视频监控程序,很早以前弄过一个,采用的是早期的ffmpeg2的lib文件,对于现在众多的网络流媒体格式,支持有限,而且新的Qt编写安卓程序,结构上也变动了,新的安卓系统权限要求也和以前处理不一样了,现在需要动态授权,以前是直接配置文件写好需要哪些权限就行,所以近期特意全部重写了一遍安卓版本的视频监控程序,内核还是采用的ffmpeg,换成了最新的ffmpeg4版本,在ubuntu系统上用安卓编译器编译了对应的lib文件,然后放到win上编写Qt+安卓程序。

为了统一管理一个版本的ffmpeg视频监控内核程序,直接在现有的程序上修改,增加了动态申请权限的代码,同时对应的进度条和复选框等指示器放大,方便选中,通道画面限定默认4个,可以自行增加画面数量,一开始测试保存截图和视频文件的时候,发现死活不成功,后面动态权限申请成功以后,把把成功,这里搞了很久,原来对不一样的安卓系统处理要求不一样。新时代新技术层出不穷,迭代真是非常的快,想要保持活力看来还得不断的学习及了解新技术新知识。一个有前途的程序员每天60%的时间要拿出来学习研究,40%用来应付工作,这样每两年工资可翻一倍,而且最要命的是程序员也是要有一些天赋的,并非所有人都适合,大部分程序员把时间都扔在了业务逻辑之中,最后被淘汰!这也是35岁中年危机的主要原因。事实上有实力的程序员越老越值钱,扯远了!

## 二、功能特点

1. 多线程实时播放视频流+本地视频+USB摄像头等。

2. 支持windows+linux+mac,支持ffmpeg3和ffmpeg4,支持32位和64位。

3. 多线程显示图像,不卡主界面。

4. 自动重连网络摄像头。

5. 可设置边框大小即偏移量和边框颜色。

6. 可设置是否绘制OSD标签即标签文本或图片和标签位置。

7. 可设置两种OSD位置和风格。

8. 可设置是否保存到文件以及文件名。

9. 可直接拖曳文件到ffmpegwidget控件播放。

10. 支持h265视频流+rtmp等常见视频流。

11. 可暂停播放和继续播放。

12. 支持存储单个视频文件和定时存储视频文件。

13. 自定义顶部悬浮条,发送单击信号通知,可设置是否启用。

14. 可设置画面拉伸填充或者等比例填充。

15. 可设置解码是速度优先、质量优先、均衡处理。

16. 可对视频进行截图(原始图片)和截屏。

17. 录像文件存储支持裸流和MP4文件。

18. 音视频完美同步,采用外部时钟同步策略。

19. 支持seek定位播放位置。

20. 支持qsv、dxva2、d3d11va等硬解码。

21. 支持opengl绘制视频数据,极低CPU占用。

22. 支持安卓和嵌入式linux,交叉编译即可。

## 三、效果图

## 四、相关站点

1. 国内站点:[https://gitee.com/feiyangqingyun/QWidgetDemo](https://gitee.com/feiyangqingyun/QWidgetDemo)

2. 国际站点:[https://github.com/feiyangqingyun/QWidgetDemo](https://github.com/feiyangqingyun/QWidgetDemo)

3. 个人主页:[https://blog.csdn.net/feiyangqingyun](https://blog.csdn.net/feiyangqingyun)

4. 知乎主页:[https://www.zhihu.com/people/feiyangqingyun/](https://www.zhihu.com/people/feiyangqingyun/)

5. 体验地址:[https://blog.csdn.net/feiyangqingyun/article/details/97565652](https://blog.csdn.net/feiyangqingyun/article/details/97565652)

## 五、核心代码

#include "head.h"#include "frmtab.h"//动态设置权限bool checkPermission(const QString &permission){#ifdef Q_OS_ANDROID#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))    QtAndroid::PermissionResult result = QtAndroid::checkPermission(permission);    if (result == QtAndroid::PermissionResult::Denied) {        QtAndroid::requestPermissionsSync(QStringList() << permission);        result = QtAndroid::checkPermission(permission);        if (result == QtAndroid::PermissionResult::Denied) {            return false;        }    }#endif#endif    return true;}void initStyle(){    //复选框单选框滑块等指示器大小    QStringList list;    int rbtnWidth = 20;    int ckWidth = 18;    list.append(QString("QRadioButton::indicator{width:%1px;height:%1px;}").arg(rbtnWidth));    list.append(QString("QCheckBox::indicator,QGroupBox::indicator,QTreeWidget::indicator,QListWidget::indicator{width:%1px;height:%1px;}").arg(ckWidth));    QString normalColor = "#E8EDF2";    QString grooveColor = "#1ABC9C";    QString handleColor = "#1ABC9C";    int sliderHeight = 12;    int sliderRadius = sliderHeight / 2;    int handleWidth = (sliderHeight * 3) / 2 + (sliderHeight / 5);    int handleRadius = handleWidth / 2;    int handleOffset = handleRadius / 2;    list.append(QString("QSlider::horizontal{min-height:%1px;}").arg(sliderHeight * 2));    list.append(QString("QSlider::groove:horizontal{background:%1;height:%2px;border-radius:%3px;}")                .arg(normalColor).arg(sliderHeight).arg(sliderRadius));    list.append(QString("QSlider::add-page:horizontal{background:%1;height:%2px;border-radius:%3px;}")                .arg(normalColor).arg(sliderHeight).arg(sliderRadius));    list.append(QString("QSlider::sub-page:horizontal{background:%1;height:%2px;border-radius:%3px;}")                .arg(grooveColor).arg(sliderHeight).arg(sliderRadius));    list.append(QString("QSlider::handle:horizontal{width:%2px;margin-top:-%3px;margin-bottom:-%3px;border-radius:%4px;"                        "background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #FFFFFF,stop:0.8 %1);}")                .arg(handleColor).arg(handleWidth).arg(handleOffset).arg(handleRadius));    //偏移一个像素    handleWidth = handleWidth + 1;    list.append(QString("QSlider::vertical{min-width:%1px;}").arg(sliderHeight * 2));    list.append(QString("QSlider::groove:vertical{background:%1;width:%2px;border-radius:%3px;}")                .arg(normalColor).arg(sliderHeight).arg(sliderRadius));    list.append(QString("QSlider::add-page:vertical{background:%1;width:%2px;border-radius:%3px;}")                .arg(grooveColor).arg(sliderHeight).arg(sliderRadius));    list.append(QString("QSlider::sub-page:vertical{background:%1;width:%2px;border-radius:%3px;}")                .arg(normalColor).arg(sliderHeight).arg(sliderRadius));    list.append(QString("QSlider::handle:vertical{height:%2px;margin-left:-%3px;margin-right:-%3px;border-radius:%4px;"                        "background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5,stop:0.6 #FFFFFF,stop:0.8 %1);}")                .arg(handleColor).arg(handleWidth).arg(handleOffset).arg(handleRadius));    qApp->setStyleSheet(list.join(""));}int main(int argc, char *argv[]){#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);#endif#if (QT_VERSION > QT_VERSION_CHECK(5,4,0))    //设置opengl模式 AA_UseDesktopOpenGL AA_UseSoftwareOpenGL AA_UseOpenGLES    //QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);#endif    QApplication a(argc, argv);    App::setFont();    App::setCode();    App::ConfigFile = AppPath + "/video_ffmpeg.ini";    App::readConfig();    frmTab w;#ifdef Q_OS_ANDROID    //请求权限    checkPermission("android.permission.READ_EXTERNAL_STORAGE");    checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");    QString strDir = AppPath + "/snap";    QDir dir(strDir);    if (!dir.exists()) {        dir.mkpath(strDir);    }    initStyle();    w.showMaximized();#else    w.resize(1100, 700);    w.setWindowTitle(QString("qt+ffmpeg 示例 %1 %2").arg(App::Version).arg(App::TitleFlag));    w.show();    App::setFormInCenter(&w);#endif    return a.exec();}

DS1819 对应版本的FFMPEG_Qt音视频开发33-ffmpeg安卓版相关推荐

  1. Android音视频开发从入门到精通,我这一路走来的经验分享

    前不久,在国家统计局针对北京市进行的农民工市民化状况进行的调研中,从事信息技术,软件技术等IT服务业的人员也被当做农民工. 编程的门槛不高,薪资水平也还可观.这一直是"三百六十行,行行转IT ...

  2. im和音视频开发哪个更好_找时间成为更好的开发人员

    im和音视频开发哪个更好 There's no time for anything. At least that's how it feels doesn't it? No time to learn ...

  3. Android IOS WebRTC 音视频开发总结(二三)-- hurtc使用说明

    Android IOS WebRTC 音视频开发总结(二三)-- hurtc使用说明 本文主要介绍如何测试基于浏览器和手机的视频通话程序,转载请说明出处,文章来自博客园RTC.Blacker,更多详见 ...

  4. 即时通讯音视频开发(六):如何开始音频编解码技术的学习

    前言 即时通讯应用中的实时音视频技术,几乎是IM开发中的最后一道高墙.原因在于:实时音视频技术 = 音视频处理技术 + 网络传输技术 的横向技术应用集合体,而公共互联网不是为了实时通信设计的. 系列文 ...

  5. python去除视频中的logo_Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解...

    moviepy音视频开发专栏<moviepy音视频开发专栏>为收费专栏,基于老猿阅读moviepy1.03版本的源代码以及大量测试验证的基础上,详细介绍moviepy主要音视频剪辑相关类的 ...

  6. “铜三铁四“来一套程序员内卷超车赛道-音视频开发

    往年的金三银四,今年被戏称为"铜三铁四".知名的大厂HR们都在不断的裁员,能被保住不被裁掉可能就万事大吉了,赛道越来越窄,都在预测未来计算机行业是不是下一个土木工程? 其实每一个行 ...

  7. moviepy音视频开发:使用credits1给视频加片头片尾字幕

    ☞ ░ 前往老猿Python博文目录 ░ 一.概述 在<moviepy音视频剪辑:视频基类VideoClip子类DataVideoClip.UpdatedVideoClip.ImageClip. ...

  8. 浅谈音视频开发入门基础及进阶资源分享

    导言:音视频开发涉及的知识面比较广,知识点又相对独立琐碎,入门门槛相对较高.想要对音视频开发具有深入全面的了解,需要在行业深耕多年.本文将简单介绍音视频的采集,编解码,传输,渲染四个技术点并对涉及到的 ...

  9. 音视频开发:直播推流技术指南

    一.推流架构 推流SDK客户端的模块主要有三个,推流采集端.队列控制模块.推流端.其中每个模块的主要流程如下,本文的主要目的就是拆分推流流程. 1.1 采集端 视频采集:通过Camera采集视频. 音 ...

最新文章

  1. 在 Android 上使用协程(二):Getting started
  2. finishBeanFactoryInitialization 处理预实例化Bean
  3. 多年前那些优秀的工程师,后来都去哪儿了?
  4. mysql 命令行 设置同步_MySQL同步(二) 设置同步
  5. 级数求和(洛谷-P1035)
  6. 统计学习导论(ISLR) 第四章分类算法课后习题
  7. Spring Thymeleaf无法显示图片
  8. Home Assistant -ESP Home接入homekit篇
  9. Sensible, not sensitive; simply complicated; predictably irrational; kindly demanding; constructivel
  10. C# 判断文件是否在使用的状态FSDF
  11. 2015InfoQ软件大会技术记录
  12. 小程序:浅谈小程序更新机制,发版后多久能全覆盖
  13. mysql占用内存过高_mysql数据库占用内存过高解决办法
  14. 记一次腾讯面试:进程之间究竟有哪些通信方式?如何通信? ---- 告别死记硬背
  15. 用C++实现中国象棋
  16. Android---AndroidX
  17. DeepDGA:基于生成对抗网络的DGA生成与检测
  18. 基础:cin与char*的相关问题
  19. python注册码_python 注册码
  20. 智能交通信号灯管理系统

热门文章

  1. tcl脚本学习十一:proc应用 (带默认参数)
  2. OpenCV基本步骤(初步学习)
  3. 逻辑分析推理(五小姐问题)
  4. keil编译出错关于__use_no_semihosting_swi的使用
  5. AB1601串口之bugs
  6. 吴恩达机器学习(第二章)——单变量线性回归
  7. 跨链Cosmos(10) IBC接口
  8. 近世代数--整环上的整除理论--主理想整环中最大公因子的存在表示定理
  9. 数学建模——K-means聚类模型Python代码
  10. 命令行工具cobra的使用