技术标签: android
信息发布系统中需要支持海康视频监控预览功能,下面将列出功能实现相关流程
文末附带demo
准备工作(省略步骤,module文件和so文件见demo)
1.引用module
//组件依赖
implementation project(path: ':hatom-video-player')
2.创建jnilib,复制粘贴so库文件
3.build.gradle文件
defaultConfig {
...
ndk{
abiFilters 'arm64-v8a','armeabi-v7a'
}
...
}
正式开始:
1.manifest文件,申请权限,开启硬件加速(SurfaceView需要)
<uses-permission android:name="android.permission.INTERNET" />
<!-- 存储 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".MyApp"
android:allowBackup="true"
android:hardwareAccelerated="true"
...
</application>
2.自定义Application,初始化sdk
public class BaseApp extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
HatomPlayerSDK.init(this, "", isAppDebug());
}
public static Context getContext() {
return context;
}
public static boolean isAppDebug() {
if ("".equals(context.getPackageName())) return false;
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo(context.getPackageName(), 0);
return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
}
3.MainActivity中调用
//监控视频短链接地址
public static final String playUrl = "rtsp://61.53.68.15:554/openUrl/NCfAEgM";
//创建HatomPlayer实例
HatomPlayer hatomPlayer = new DefaultHatomPlayer();
//onCreate中增加回调
binding.texture.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
//设置播放画面显示surface,支持TextureView和SurfaceView
hatomPlayer.setSurfaceTexture(binding.texture.getSurfaceTexture());
//播放前设置播放配置(可选)
PlayConfig playConfig = new PlayConfig();
//使用硬解码
playConfig.hardDecode = false;
//开启智能信息
playConfig.privateData = false;
hatomPlayer.setPlayConfig(playConfig);
//设置播放参数
//realPlayUrl为预览短链接,需要通过调用openApi获取
hatomPlayer.setDataSource(playUrl, null);
//设置播放回调
hatomPlayer.setPlayStatusCallback((status, s) -> {
switch (status) {
case SUCCESS:
Log.i("swyLog", "播放成功");
break;
case FAILED:
case EXCEPTION:
case FINISH:
hatomPlayer.stop();
Log.i("swyLog", "error is : " + MessageFormat.format("播放失败,错误码为:{0}", convertToHexString(s)));
break;
default:
break;
}
});
hatomPlayer.start();
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
}
});
//格式化错误码方法
public static String convertToHexString(String errorCode) {
if (errorCode.startsWith("0x")) {
return errorCode;
}
if (TextUtils.isEmpty(errorCode)) {
return "";
}
int parseInt = Integer.parseInt(errorCode);
StringBuilder hexCode = new StringBuilder(Integer.toHexString(parseInt));
if (hexCode.length() < 8) {
int count = 8 - hexCode.length();
for (int i = 0; i < count; i++) {
hexCode.insert(0, "0");
}
}
return MessageFormat.format("{0}{1}", "0x", hexCode.toString());
}
重要说明:
binding.texture.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
//设置播放画面显示surface,支持TextureView和SurfaceView
hatomPlayer.setSurfaceTexture(binding.texture.getSurfaceTexture());
这里使用的TextureView.getSurfaceTexture,如果不增加SurfaceTextureListener监听,则会无法正常显示监控预览,另外,根据自己在设备上实际测试发现,从设置该回调,到进入onSurfaceTextureAvailable回调,中间会有一段比较长的时间(秒级)
实际业务场景遇到的问题分享:
信息发布系统的业务场景里,因为要单独定义一个组件PreviewWidget,然后父布局动态的addView加载该组件,因为MainActivity中需要执行业务,然后组件中只给外部返回一个hatomPlayer对象,但是把后续代码拿出来之后,就发现总是白屏,显示不出来,打断点发现,texture.getSurfaceTexture总是拿到空,想了很多办法都无法解决。最终发现的问题所在,就是上面说的进入回调会有一个秒级的延时,所以,最终的解决方法就是PreviewWidget中的onSurfaceTextureAvailable响应之后,给MainActivity发event事件通知,然后MainActivity再去执行后续逻辑,至此问题就解决了,代码如下,可以参考一下便于理解本段表述的意思
PreviewWidget
texture_view.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
hatomPlayer.setSurfaceTexture(texture_view.getSurfaceTexture());
LiveDataBus.getInstance()
.with(EventBus.PREVIEW_AVAILABLE, PreviewAvailableEvent.class)
.postValue(new PreviewAvailableEvent());
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
MainActivity
LiveDataBus.getInstance()
.with(EventBus.PREVIEW_AVAILABLE, PreviewAvailableEvent.class)
.observe(this, event -> {
showTextures();
});
public void showTextures() {
if (TextUtils.isEmpty(previewUrl)) {
Log.i("swyLog", "监控预览地址为空");
return;
}
//播放前设置播放配置(可选)
PlayConfig playConfig = new PlayConfig();
//使用硬解码
playConfig.hardDecode = true;
//开启智能信息
playConfig.privateData = true;
hatomPlayer.setPlayConfig(playConfig);
//设置播放参数
//预览短链接,需要通过调用openApi获取
// String url = "rtsp://61.53.68.15:554/openUrl/e9KXHVu";
hatomPlayer.setDataSource(previewUrl, null);
//设置播放回调
hatomPlayer.setPlayStatusCallback((status, s) -> {
switch (status) {
case SUCCESS:
runOnUiThread(() -> {
previewWidget.setError("");
Log.i("swyLog", "播放成功");
});
break;
case FAILED:
case EXCEPTION:
case FINISH:
runOnUiThread(() -> {
hatomPlayer.stop();
previewWidget.setError(MessageFormat.format("播放失败,错误码为:{0}", convertToHexString(s)));
Log.i("swyLog", "error is : " + MessageFormat.format("播放失败,错误码为:{0}", convertToHexString(s)));
});
break;
default:
break;
}
});
hatomPlayer.start();
}
至此完结
文章浏览阅读1w次,点赞13次,收藏121次。c++_c++入门
文章浏览阅读1.5k次。先上代码:${ pageContext.request.contextPath }号码段管理 号码段管理 号码段管理 区域号
文章浏览阅读118次。从 SQL 到SPL基本查询语法迁移之多表操作上一篇我们针对单表的情形了解了如何把数据计算从 SQL 查询迁移到集算器,或者更准确地说,迁移到集算器所使用的SPL集算语言。这个迁移过程,既有相同的概念,也有不同的思路。接下来,我们一起针对多表的情况看一下集算器和SPL语言是如何发挥更大的..._sql常用比if更好用
文章浏览阅读1.5k次。文章目录多臂赌博机Multi-armed bandit(无状态)马尔科夫决策过程MDP(markov decision process1.动态规划蒙特卡罗方法——不知道环境完整模型情况下2.1 on-policy蒙特卡罗2.2 off-policy蒙特卡罗时序差分方法强化学习:Reinforcement learning目标:学习从环境状态到行为的映射,智能体选择能够获得环境最大奖赏的行为..._国科大 强化学习
文章浏览阅读1k次。如何用 Visual studio 2003/2005 调试 ASP 应用程序、Javascript 代码 在vs2005中调试ASP网站的错误信息:无法提供此类型的页。说明: 由于已明确禁止所请求的页类型,无法对该类型的页提供服务。扩展名“.asp”可能不正确。 请检查以下的 URL 并确保其拼写正确。 怎么解决这个问题呢?请看下文。 ASP.NET 已经很_visual studio 2003 asp 远程调试
文章浏览阅读1.3w次,点赞2次,收藏29次。一、前言 无论是端游、页游、手游如果是采用了MMO即时战斗游戏模式,基本都会遇到同屏多角色实时移动、释放技能、战斗等场景,于是自然也需要实现如何管理同屏内各种角色的信息同步:例如角色的位置、以及角色身上的装备、时装、buffer等状态的实时切换。同步在网络游戏中是非常重要的,它保证了每个玩家在屏幕上看到的东西大体是一样的,解决同步问题的最简单的方法就是把每个玩家的_mmo城镇同步
文章浏览阅读1.2k次。Maccms 8.x版本中存在安全漏洞。远程攻击者可借助index.php?m=vod-search请求中的‘wd’参数利用该漏洞执行命令。2.借助index.php?m=vod-search请求中的‘wd’参数利用该漏洞执行命令。利用浏览器浏览器发送POST数据包或直接使用Python编写的脚本进行发送POST数据包。3.进行攻击,该payload是直接生成一个c.php一句话木马文件,连接密码为c。Maccms是一套跨平台的基于PHP和MySQL快速建站系统。_vulfocus/dedecms-cve-2017-17731
文章浏览阅读86次。计算机软件专业面向对象oop课程笔记_包含警戒存在于
文章浏览阅读845次。oracle行锁 select for update_oracle select 加锁检测 update
文章浏览阅读817次。结合报错信息及代码,报错处的代码为ActiveIncrUserTimer使用了注解@Autowired进行依赖注入,但是没有找到可以被用来注入的实例。即Spring Boot获取ActiveIncrUserService 的实例失败。原来是我不小心把这个代码ActiveIncrUserServiceImp给误删了。_@autowired(required = true)
文章浏览阅读2k次。USB3.0单路uvc iso传输速率只有92MB/s, 1080p yuv 23.4fps,我们需要提高UVC传输速率(YUV帧率)_全志uvc提升iso传输速度
文章浏览阅读59次。-----------------------------------------------------------------------------------------欲穷千里目,更上一层楼。 2014年曾是一个开始,在此期间,无限的恐惧与励志。此部落格也在这一年的一月份开通,这里也是一个互联网世界。 记录2014流水:1月-4月,日子如压缩般被度过,Web方面完..._proxmox solidworks cad