Android平台GB28181设备接入端实现实时快照
2023-06-13 09:13:42 时间
Android平台GB28181设计开发的时候,有个功能必不可少的:实时快照,特别是用于执法记录仪等场景下,用于图像留底或分析等考量。
实时快照的实现并不难,目前实现有两种方式,一种是拿到数据(比如摄像头数据)后,直接上层编码,存取快照;另一种模式是,数据投递到JNI层,底层针对投递过来的编码前数据,做png编码,并保存到设定的目录下,今天我们主要探讨第二种实现模式。
我们在publisher实例初始化的时候,设置是否启用快照:
private void InitAndSetConfig() {
int audio_opt = 1;
int fps = 18;
int gop = fps * 2;
Log.i(TAG, "InitAndSetConfig video_width: " + video_width_ + " cur_video_height" + video_height_ + " imageRotationDegree:" + cameraImageRotationDegree_);
publisherHandle = libPublisher.SmartPublisherOpen(context_, audio_opt, 3, video_width_, video_height_);
if (publisherHandle == 0) {
Log.e(TAG, "sdk open failed!");
return;
}
Log.i(TAG, "publisherHandle=" + publisherHandle);
if(videoEncodeType == 1) {
int h264HWKbps = setHardwareEncoderKbps(true, video_width_, video_height_);
h264HWKbps = h264HWKbps*fps/25;
Log.i(TAG, "h264HWKbps: " + h264HWKbps);
int isSupportH264HWEncoder = libPublisher
.SetSmartPublisherVideoHWEncoder(publisherHandle, h264HWKbps);
if (isSupportH264HWEncoder == 0) {
libPublisher.SetNativeMediaNDK(publisherHandle, 1);
Log.i(TAG, "Great, it supports h.264 hardware encoder!");
}
}
else if (videoEncodeType == 2) {
int hevcHWKbps = setHardwareEncoderKbps(false, video_width_, video_height_);
hevcHWKbps = hevcHWKbps*fps/25;
Log.i(TAG, "hevcHWKbps: " + hevcHWKbps);
int isSupportHevcHWEncoder = libPublisher
.SetSmartPublisherVideoHevcHWEncoder(publisherHandle, hevcHWKbps);
if (isSupportHevcHWEncoder == 0) {
libPublisher.SetNativeMediaNDK(publisherHandle, 1);
Log.i(TAG, "Great, it supports hevc hardware encoder!");
}
}
boolean is_sw_vbr_mode = true;
if(is_sw_vbr_mode) //H.264 software encoder
{
int is_enable_vbr = 1;
int video_quality = CalVideoQuality(video_width_, video_height_, true);
int vbr_max_bitrate = CalVbrMaxKBitRate(video_width_, video_height_);
libPublisher.SmartPublisherSetSwVBRMode(publisherHandle, is_enable_vbr, video_quality, vbr_max_bitrate);
}
if (is_pcma_) {
libPublisher.SmartPublisherSetAudioCodecType(publisherHandle, 3);
} else {
libPublisher.SmartPublisherSetAudioCodecType(publisherHandle, 1);
}
libPublisher.SetSmartPublisherEventCallbackV2(publisherHandle, new EventHandePublisherV2());
libPublisher.SmartPublisherSetSWVideoEncoderProfile(publisherHandle, 3);
libPublisher.SmartPublisherSetSWVideoEncoderSpeed(publisherHandle, 2);
libPublisher.SmartPublisherSetGopInterval(publisherHandle, gop);
libPublisher.SmartPublisherSetFPS(publisherHandle, fps);
// libPublisher.SmartPublisherSetSWVideoBitRate(publisherHandle, 600, 1200);
boolean is_noise_suppression = true;
libPublisher.SmartPublisherSetNoiseSuppression(publisherHandle, is_noise_suppression ? 1 : 0);
boolean is_agc = false;
libPublisher.SmartPublisherSetAGC(publisherHandle, is_agc ? 1 : 0);
int echo_cancel_delay = 0;
libPublisher.SmartPublisherSetEchoCancellation(publisherHandle, 1, echo_cancel_delay);
libPublisher.SmartPublisherSaveImageFlag(publisherHandle, 1);
}
记得留意最后一句:libPublisher.SmartPublisherSaveImageFlag(publisherHandle, 1);
相关接口说明如下:
/**
* Set if needs to save image during publishing stream(设置是否启用快照)
*
* @param is_save_image: if with 1, it will save current image via the interface of SmartPlayerSaveImage(), if with 0: does not it
*
* @return {0} if successful
*/
public native int SmartPublisherSaveImageFlag(long handle, int is_save_image);
设置后,页面有需要实时快照的数据时,点击“实时快照”按钮即可,需要注意的是,实时快照需要存储路径和保存下来的快照文件名称。具体实现如下:
class ButtonCaptureImageListener implements View.OnClickListener {
@SuppressLint("SimpleDateFormat")
public void onClick(View v) {
if(isPushingRtmp || isRecording || isRTSPPublisherRunning || isGB28181StreamRunning)
{
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "dn_" + timeStamp; //创建以时间命名的文件名称
String imagePath = imageSavePath + "/" + imageFileName + ".png";
Log.i(TAG, "imagePath:" + imagePath);
libPublisher.SmartPublisherSaveCurImage(publisherHandle, imagePath);
}
else
{
Log.e(TAG, "快照失败,请确保在推送、录像、GB28181推送或内置RTSP服务发布状态..");
}
}
}
快照截取成功后,publisher实例会回调以下事件:
case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CAPTURE_IMAGE:
publisher_event = "快照: " + param1 + " 路径:" + param3;
if (param1 == 0) {
publisher_event = publisher_event + "截取快照成功..";
} else {
publisher_event = publisher_event + "截取快照失败..";
}
break;
由于实时快照,功能复杂度不高,而且也可以在上层实现,很容易被忽略,如果做的精细的话,还是需要开发者花费一定的心思。
相关文章
- Android 相机方向传感,如何在Android设备中获取相机传感器尺寸?[通俗易懂]
- android 模拟器 haxm,Android模拟器不使用HAXM
- android 安装p12证书,如何在Android中使用p12证书(客户端证书)
- Ubuntu14.04安装Android SDK
- android 获取收到短信验证码,Android自动获取短信验证码
- Android设备调试工具一览表
- Android preference_android studio preview
- android的toast提示_android studio unknown host
- android应用程序_chrome Android
- android activitymanager 系统api_Android view
- Android Services Library_android freeware
- Android studio更新后出现警告:Warning:The `android.dexOptions.incremental` property is deprecated and it has
- 2022最新手机设备标识码(IMEI、MEID、UDID、UUID、ANDROID_ID、GAID、IDFA等)教程
- 【Android 应用开发】BluetoothClass详解
- 【Android Gradle 插件】Module 目录下 build.gradle 配置文件 ( android 闭包块配置 | AppExtension 扩展类型参考文档 )
- 【错误记录】Android Studio 编译时 lint 检查报错 ( WARNING: DSL element ‘android.dataBinding.enabled‘ is obsolet )
- 【Android Gradle 插件】自定义 Gradle 任务 ⑪ ( Gradle 任务分组 | 为自定义 Gradle 任务指定分组 | 为自定义 Gradle任务指定任务描述 | 代码示例 )
- 【愚公系列】2023年04月 攻防世界-MOBILE(基础android)
- android获取设备唯一标示详解手机开发
- 获取Android设备屏幕宽、高、dpi密度及横竖屏等参数详解编程语言
- 微软展示Win10与Android移动设备的更深度兼容体验
- Connecting Android to Oracle: The Ultimate Guide for Seamless Integration.(android连接oracle)
- Android的Touch事件处理机制介绍
- android横竖屏限制的配置方法
- Android进入设备后台data文件夹的办法
- android中写一个内部类来选择文件夹中指定的图片类型实例说明