石家庄pc端网站建设,衡水网页网站建设,网站app制作平台,做网站0基础写代码技术背景
GB/T28181-2022相对2016版#xff0c;对图像抓拍有了明确的界定#xff0c;图像抓拍在视频监控行业非常重要, Android平台GB28181设备接入端#xff0c;无需实时上传音视频实时数据的情况下#xff0c;就可以抓图上传到指定的图像存储服务器上。
图像抓拍基本要…技术背景
GB/T28181-2022相对2016版对图像抓拍有了明确的界定图像抓拍在视频监控行业非常重要, Android平台GB28181设备接入端无需实时上传音视频实时数据的情况下就可以抓图上传到指定的图像存储服务器上。
图像抓拍基本要求如下
源设备向目标设备发送图像抓拍配置命令需要携带传输路径、会话ID等信息。目标设备完成图像传输后发送图像抓拍传输完成通知命令采用IETF RFC3428中的MESSAGE方法实现。图像文件命名规则宜采用“设备编码(20位)、图像编码(2位)、时间编码(17位)、序列码(2位)”的形式图像格式宜使用JPEG图像分辨率宜采用与主码流相同的分辨率。 需要注意的是MESSAGE消息头Content-type头域为Content-type:Application/MANSCDPxml采用XML封装。设备收到图像抓拍配置命令后发送配置响应命令响应命令中包含执行结果信息。
图像抓拍流程如下 技术实现
大牛直播SDK的SmartGBD已经完成GB28181设备接入侧的图像抓拍。 总体功能设计如下 [视频格式]H.264/H.265(Android H.265硬编码) [音频格式]G.711 A律、AAC [音量调节]Android平台采集端支持实时音量调节 [H.264硬编码]支持H.264特定机型硬编码 [H.265硬编码]支持H.265特定机型硬编码 [软硬编码参数配置]支持gop间隔、帧率、bit-rate设置 [软编码参数配置]支持软编码profile、软编码速度、可变码率设置 支持横屏、竖屏推流 Android平台支持后台service推送屏幕(推送屏幕需要5.0版本)支持纯视频、音视频PS打包传输支持RTP OVER UDP和RTP OVER TCP被动模式TCP媒体流传输客户端支持信令通道网络传输协议TCP/UDP设置支持注册、注销支持注册刷新及注册有效期设置支持设备目录查询应答支持心跳机制支持心跳间隔、心跳检测次数设置支持移动设备位置(MobilePosition)订阅和通知 适用国家标准GB/T 28181—2016支持语音广播支持语音对讲支持图像抓拍支持历史视音频文件检索支持历史视音频文件下载支持历史视音频文件回放支持云台控制和预置位查询 [实时水印]支持动态文字水印、png水印 [镜像]Android平台支持前置摄像头实时镜像功能 [实时静音]支持实时静音/取消静音 [实时快照]支持实时快照 [降噪]支持环境音、手机干扰等引起的噪音降噪处理、自动增益、VAD检测 [外部编码前视频数据对接]支持YUV数据对接 [外部编码前音频数据对接]支持PCM对接 [外部编码后视频数据对接]支持外部H.264数据对接 [外部编码后音频数据对接]外部AAC数据对接 [扩展录像功能]支持和录像SDK组合使用录像相关功能。
图像抓拍相关信令处理如下
/** Author: daniusdk.com*/package com.gb.ntsignalling;public interface GBSIPAgent {void setDeviceConfigListener(GBSIPAgentDeviceConfigListener deviceConfigListener);/** 通知图像抓拍传输完成*/boolean notifyUploadSnapShotFinished(String fromUserName, String fromUserNameAtDomain, String deviceID, String sessionID, java.util.ListString snapShotList);}
Device配置Listener如下
package com.gb.ntsignalling;public interface GBSIPAgentDeviceConfigListener {/** 图像抓拍配置*/void ntsOnDeviceSnapShotConfig(String from_user_name, String from_user_name_at_domain,String sn, String device_id, SnapShotConfig config,ListString extra_info_list);
}
Snapshot配置接口如下
public interface SnapShotConfig {int snap_num();int interval();String upload_url();String session_id();
}图像抓拍JNI接口设计如下
public class SmartPublisherJniV2 {/*** 截图接口, 支持JPEG和PNG两种格式* param compress_format: 压缩格式, 0:JPEG格式, 1:PNG格式, 其他返回错误* param quality: 取值范围:[0, 100], 值越大图像质量越好, 仅对JPEG格式有效, 若是PNG格式,请填100* param file_name: 图像文件名, 例如:/dirxxx/test20231113100739.jpeg, /dirxxx/test20231113100739.png* param user_data_string: 用户自定义字符串* return {0} if successful*/public native int CaptureImage(long handle, int compress_format, int quality, String file_name, String user_data_string);}
Device Snap Shot Listener 核心代码如下
/** Author: daniusdk.com*/public class GBDeviceSnapShotListenerImpl implements GBSIPAgentDeviceControlListener {Overridepublic void ntsOnDeviceSnapShotConfig(String from_user_name, final String from_user_name_at_domain,String sn, String device_id, final SnapShotConfig config,ListString extra_info_list) {if (null config)return;handler_.postDelayed(new Runnable() {Overridepublic void run() {Log.i(TAG, ntsOnDeviceSnapShotConfig device_id: device_id_ session_id: config.session_id() , snap_num: config.snap_num() , interval: config.interval() , upload_url: config.upload_url());if (null gb28181_agent_)return;if (null snap_shot_impl_) {snap_shot_impl_ new SnapShotGBImpl(image_path_, context_, handler_, lib_publisher_jni, snap_shot_publisher_);snap_shot_impl_.start();}snap_shot_impl_.add_config(gb28181_agent_, from_user_name_, from_user_name_at_domain_, sn_,device_id_, snap_shot_config_, extra_info_list_);}private String from_user_name_;private String from_user_name_at_domain_;private String sn_;private String device_id_;private SnapShotConfig snap_shot_config_;private ListString extra_info_list_;public Runnable set(String from_user_name, String from_user_name_at_domain,String sn, String device_id, SnapShotConfig config,ListString extra_info_list) {this.from_user_name_ from_user_name;this.from_user_name_at_domain_ from_user_name_at_domain;this.sn_ sn;this.device_id_ device_id;this.snap_shot_config_ config;this.extra_info_list_ extra_info_list;return this;}}.set(from_user_name, from_user_name_at_domain, sn, device_id, config, extra_info_list), 0);}
}public class SnapShotGBImpl extends SnapShotImpl {private ListSnapConfig config_list_ new LinkedList();public SnapShotGBImpl(String dir, Context context, android.os.Handler handler,SmartPublisherJniV2 lib_sdk, LibPublisherWrapper publisher) {super(dir, context, handler, lib_sdk, publisher);}public boolean add_config(GBSIPAgent agent, String from_user_name, String from_user_name_at_domain, String sn,String device_id, SnapShotConfig config, ListString extra_info_list) {if (null agent)return false;if (is_null_or_empty(device_id))return false;if (null config)return false;if (config.snap_num() 1)return false;if (config.interval() 1)return false;if (is_null_or_empty(config.session_id()))return false;SnapConfig c new SnapConfig(agent, from_user_name, from_user_name_at_domain, sn, device_id, config, extra_info_list);config_list_.add(c);return true;}public void on_captured_image(long result, String file_name, long file_date_time_ms, String user_data) {SnapConfig config find_config(user_data);if (null config) {super.on_captured_image(result, file_name, file_date_time_ms, user_data);return;}SnapItem item config.find_capturing_item(file_name);if (null item) {super.on_captured_image(result, file_name, file_date_time_ms, user_data);return;}if (result ! 0) {item.set_status(SnapItem.ERROR_STATUS);item.set_error_info(capture failed);Log.e(TAG, capture failed, file: file_name , session_id: user_data);return;}item.set_status(SnapItem.CAPTURE_COMPLETION_STATUS);}public void on_uploaded(boolean is_ok, String file_name, String session_id, String gb_name) {SnapConfig config find_config(session_id);if (null config) {Log.w(TAG, on_uploaded cannot find config, session_id: session_id , gb_name: gb_name);return;}SnapItem item config.find_uploading_item(gb_name);if (null item) {Log.w(TAG, on_uploaded cannot find item, session_id: session_id , gb_name: gb_name);return;}if (is_ok) {item.set_status(SnapItem.UPLOAD_COMPLETION_STATUS);Log.i(TAG, on_uploaded ok, session_id: session_id , file: file_name);}else {item.set_status(SnapItem.ERROR_STATUS);item.set_error_info(upload failed);Log.e(TAG, on_uploaded failed, session_id: session_id , file: file_name);}}Overridepublic void on_stop() {this.config_list_.clear();shutdown(200, TimeUnit.MILLISECONDS);}private void process_upload() {android.os.Handler app_handler os_handler();for(SnapConfig c : config_list_)c.upload_files(app_handler, this);}private void process_finished() {ListString notified_files null;IteratorSnapConfig iterator config_list_.iterator();while(iterator.hasNext()) {SnapConfig c iterator.next();if (!c.is_can_notify_server())continue;iterator.remove();if (null notified_files)notified_files new LinkedList();c.notify_server(notified_files);}// 暂时删除这些文件, 根据业务需求随时调整就好if(notified_files ! null !notified_files.isEmpty())execute(new DeleteFilesTask(notified_files));}private static class SnapItem {private int status_ INITIALIZATION_STATUS;private final String device_id_;private final int sn_; // 序列码, 40~41private final String dir_;private String file_name_;}private static class SnapConfig {private WeakReferenceGBSIPAgent agent_;private final String from_user_name_;private final String from_user_name_at_domain_;private final String sn_;private final String device_id_;private final String session_id_;private final int snap_num_;private final String upload_url_;private final int interval_sec_;private final ListString extra_info_list_;private ArrayListSnapItem items_;public final String session_id() {return this.session_id_;}public void upload_files(android.os.Handler os_handler, SnapShotGBImpl snap) {if (null items_)return;for (SnapItem i : items_) {if (i.is_capture_completion_status()) {i.set_status(SnapItem.UPLOADING_STATUS);BaseUploadTask upload_task new MyUploadTask(upload_url_, i.file_name(), i.gb_snap_shot_file_id(),session_id(), i.gb_name(), os_handler, snap);if (!snap.submit(upload_task) ) {i.set_status(SnapItem.ERROR_STATUS);i.set_error_info(submit upload task failed);}}}}public void notify_server(ListString notified_files) {ArrayListString snap_shot_list new ArrayList(items_.size());for (SnapItem i : items_) {if (SnapItem.UPLOAD_COMPLETION_STATUS i.status())snap_shot_list.add(i.gb_snap_shot_file_id());if (notified_files ! null)notified_files.add(i.file_name());}if (null agent_)return;GBSIPAgent agent agent_.get();if (null agent)return;agent.notifyUploadSnapShotFinished(from_user_name_, from_user_name_at_domain_, device_id_, this.session_id(), snap_shot_list);}}private static class DeleteFilesTask implements Runnable {private ListString file_name_list_;public DeleteFilesTask(ListString file_name_list) {this.file_name_list_ file_name_list;}Overridepublic void run() {if (null file_name_list_)return;if (file_name_list_.isEmpty()) {file_name_list_ null;return;}for (String i : file_name_list_) {try {File f new File(i);if (!f.exists()||!f.isFile() )continue;if (f.delete())Log.i(TAG, delete file: i);elseLog.w(TAG, delete file failed, i);}catch(Exception e) {Log.e(TAG, DeleteFilesTask.run Exception:, e);}}file_name_list_.clear();file_name_list_ null;}}public static class BaseUploadTask extends CancellableTask {private final String upload_url_;private final String file_name_;private final String gb_snap_shot_file_id_;private final String session_id_;private final String gb_name_;private WeakReferenceandroid.os.Handler os_handler_;private WeakReferenceSnapShotGBImpl snap_;public BaseUploadTask(String upload_url, String file_name, String gb_snap_shot_file_id,String session_id, String gb_name, android.os.Handler os_handler, SnapShotGBImpl snap) {this.upload_url_ upload_url;this.file_name_ file_name;this.gb_snap_shot_file_id_ gb_snap_shot_file_id;this.session_id_ session_id;this.gb_name_ gb_name;if (os_handler !null)this.os_handler_ new WeakReference(os_handler);if (snap ! null)this.snap_ new WeakReference(snap);}protected final String upload_url() {return this.upload_url_;}protected final String file_name() {return this.file_name_;}protected final String gb_snap_shot_file_id() {return this.gb_snap_shot_file_id_;}protected final String session_id() {return this.session_id_;}protected final String gb_name() { return this.gb_name_; }protected final android.os.Handler os_handler() {if (os_handler_ ! null)return os_handler_.get();return null;}protected final SnapShotGBImpl snap() {if (snap_ ! null)return snap_.get();return null;}private static class ResultRunnable implements Runnable {private final boolean result_;private final String file_name_;private final String session_id_;private final String gb_name_;private WeakReferenceSnapShotGBImpl snap_;public ResultRunnable(boolean result, String file_name, String session_id,String gb_name, SnapShotGBImpl snap) {this.result_ result;this.file_name_ file_name;this.session_id_ session_id;this.gb_name_ gb_name;if (snap ! null)this.snap_ new WeakReference(snap);}Overridepublic void run(){if (null this.snap_)return;SnapShotGBImpl snap this.snap_.get();if (null snap)return;snap.on_uploaded(result_, file_name_, session_id_, gb_name_);}}protected void post_result(boolean is_ok) {android.os.Handler handler os_handler();if (null handler)return;SnapShotGBImpl gb_snap snap();if (null gb_snap)return;handler.post(new ResultRunnable(is_ok, file_name_,session_id_, gb_name_, gb_snap));}}
}
总结
以上是GB28181图像抓拍大概的流程和设计参考权当抛砖引玉Android终端除支持常规的音视频数据接入外还可以支持移动设备位置(MobilePosition)订阅和通知、图像抓拍、语音广播和语音对讲、历史视音频下载和回放。感兴趣的开发者可以单独跟我探讨。