代码编织梦想

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;

由于实时快照,功能复杂度不高,而且也可以在上层实现,很容易被忽略,如果做的精细的话,还是需要开发者花费一定的心思。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/renhui1112/article/details/127158486

公网可用的RTMP、RTSP测试地址(更新于2021年3月)-爱代码爱编程

好多博客提到的公网可测试的RTSP和RTMP URL大多都不用了,以下是大牛直播SDK(Github)于2021年3月亲测可用的几个URL,有其他可用的URL,也欢迎大家在评论区回复。 RTMP流地址 湖南卫视:rtmp://58.200.131.2:1935/livetv/hunantv (720*576) RTSP流地址 大熊兔(VOD):

Unity环境下RTMP推流+RTMP播放低延迟解决方案-爱代码爱编程

在本文之前,我们发布了Unity环境下的RTMP推流(Windows平台+Android平台)和RTMP|RTSP拉流(Windows平台+Android平台+iOS平台)低延迟的解决方案,今天做个整体汇总,权当抛砖引玉。 1. Unity环境下RTMP推流 Unity环境下,不管是camera还是窗体数据也好,主要是高效率的拿到原始数据,采集端可用的

麒麟操作系统|Linux下低延时RTMP|RTSP直播播放实现-爱代码爱编程

背景         国产操作系统多为以Linux为基础二次开发的操作系统。2014年4月8日起,美国微软公司停止了对Windows XP SP3操作系统提供服务支持,这引起了社会和广大用户的广泛关注和对信息安全的担忧。而2020年对Windows7服务支持的终止再一次推动了国产系统的发展。         工信部对此表示,将继续加大力度,支持Linux

基于RTMP实现Linux|麒麟操作系统下屏幕|系统声音采集推送-爱代码爱编程

背景 Windows操作系统自问世以来,以其简单易用的图形化界面操作受到大众追捧,为计算机的普及、科技的发展做出了不可磨灭的功绩,也慢慢的成为人们最依赖的操作系统。在中国,90%以上的办公环境都是Windows,学校和各种培训班的培训内容也都是Windows,Windows操作系统已经渗入到各行各业,人们已经习惯了Windows的界面和操作习惯,IT计算

如何快速实现Android平台前端设备接入能力-爱代码爱编程

技术背景 SIP(会话初始化协议)是在 IP网络上进行多媒体通信的应用层控制协议,以几种RFC的形式提供,其中最重要的是包含核心协议规范的RFC3261。该协议用于创建,修改和终止与一个或多个参与者的会话。通过会话,我们了解了一组进行通信的发送方和接收方,以及在通信过程中这些发送方和接收方保持的状态。会话的示例可以包括Internet电话呼叫,多媒体分发

Android国标接入终端实现GB28181实时位置(MobilePosition)上报-爱代码爱编程

技术背景 在实现本文提到的Android平台国标GB28181接入终端的实时位置上报之前,之前已经完成了Android终端GB28181常规功能接入,采集到实时音视频数据,编码PS打包后,按需传到GB28281服务平台,媒体流支持最新GB28181-2016的UDP和TCP被动模式,参数配置,支持注册有效期、心跳间隔、心跳间隔次数、TCP/UDP信令设置

如何让android平台像ipc一样实现gb28181前端设备接入_音视频牛哥的博客-爱代码爱编程

技术背景 好多开发者在做国标对接的时候,首先想到的是IPC摄像头,通过参数化配置,接入到国标平台,实现媒体数据的按需查看等操作。 像执法记录仪等智能终端,跑在Android平台,对接GB28181平台的需求也非常大,网上相关demo也不少,但真正设计符合相关协议规范、功能完善、长时间稳定运行的并不多。基于此,我们研发了Android平台GB28181接

gb28181设备控制和teleboot远程启动命令探究_音视频牛哥的博客-爱代码爱编程

设备控制 设备控制基本要求 源设备向目标设备发送设备控制命令,控制命令的类型包括球机/云台控制、远程启动、录像控制、 报警布防/撤防、报警复位、强制关键帧、拉框放大、拉框缩小、看守位控制、设备配置等。 设备控制采用 IETFRFC3428中的 Message方法实现。 源设备包括SIP客户端、网关或者联网系统,目标设备包括SIP设备、网关或者联网系

gb28181设备接入端如何实现校时?_音视频牛哥的博客-爱代码爱编程

在探讨这个问题之前,我们先看看GB/T28181-2016官方文档怎么说的,9.10.1章节校时基本要求提到: 联网内设备支持基于SIP方式或 NTP方式的网络校时功能,标准时间为北京时间。 SIP方式校时见本节具体描述;NTP(见IETFRFC2030)协议的网络统一校时服务,网络校时设备分为时钟源和客户端,支持客户/服务器的工作模式,时钟源应支持

gb/t28181-2016基于rtp的视音频数据封装和技术实现_音视频牛哥的博客-爱代码爱编程

首先我们先回顾下相关技术规范,看看基于RTP的音视频数据PS封装。 C.1 基于RTP的视音频数据PS封装 基于RTP的 PS封装首先按照ISO/IEC13818-1:2000将视音频流封装成PS包,再将PS包以负载的方式封装成 RTP包。 进行PS封装时,应将每个视频帧封装为一个PS包,且每个关键帧的PS包中应包含系统头(System Header

gb/t28181-2016 sdp定义和音视频传输模式解读_音视频牛哥的博客-爱代码爱编程

SDP定义 联网系统中SIP消息体中携带的SDP内容应符合IETF RFC 2327的相关要求。应有如下字段:Session description: v=( protocol version) o=(owner/creator and session identifier)s=(session name) u—*(URl of description)

如何实现android平台gb28181设备对接camera2数据_音视频牛哥的博客-爱代码爱编程

技术背景 在写如何实现Android平台GB28181设备对接Camera2数据说明之前,我在前两年的blog就有针对camera2的RTMP直播推送模块做过技术分享: 在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2), 之前使用的API1

android平台实现mp4文件实时推送rtmp|轻量级rtsp服务|gb28181平台_音视频牛哥的博客-爱代码爱编程

好多开发者有这样的诉求,想把本地录制的MP4文件,以实时流数据的形式,推送到RTMP服务器,注入轻量级RTSP服务,或者对接到GB28181平台,这块前几年我们就有对接。 本次以MediaExtractor为例,先利用MediaExtractor,把mp4文件的音视频数据分离,然后调用我们publisher模块,实现编码后的数据对接到RTMP服务器、轻量

gb28181中ssrc的使用和语音广播流程浅析_音视频牛哥的博客-爱代码爱编程

今天主要聊聊GB28181中,SSRC的作用,从我们之前跟第三方厂商的对接来看,好多厂商对SSRC的处理,并不符合规范。 举个典型的操作:语音广播时带的SSRC和发送RTP包时的SSRC并不一致,然后厂商一开始给出来的结论是,不一致也不影响使用,实则按照规范来看,SSRC还是至关重要的,想想看,如果SSRC不重要的话,SDP携带的SSRC的意义在哪里?如

android平台gb28181设备接入端本地sip端口被占用或屏蔽怎么办?_音视频牛哥的博客-爱代码爱编程

好多开发者或厂商,对Android平台GB28181接入模块的定位,大多是IPC国标流程打通模拟,基于这个目的,很难按照标准SPEC规范实现Android平台GB28181设备接入,我们在跟第三方国标平台厂商对接时发现,部分公司,尽管参与了标准的制定或审校,自身实现,细节仍不尽人意。 除了作为IPC国标模拟工具,Android平台GB28181设备接入没

android平台gb28181设备接入端如何实现本地录像?_音视频牛哥的博客-爱代码爱编程

实现Android平台GB28181设备接入的时候,有个功能点不可避免,那就是本地录像,实际上,在实现GB28181设备接入模块之前,我们前些年做RTMP推送和轻量级RTSP服务的时候,早已经实现了本地录像功能。  本地录像功能,我们实现的主要控制接口如下: 音视频录制开关,为了更细粒度的控制录像,如只需要录纯音频还是纯视频,或者音视频,可以通过下

gb28181状态信息报送解读及android端国标设备接入技术实现_gb28181 notify-爱代码爱编程

今天主要聊聊GB/T28181状态信息报送这块,先回顾下协议规范相关细节,然后再针对代码实现,做个简单的说明。 状态消息报送基本要求 当源设备(包括网关、SIP设备、SIP客户端或联网系统)发现工作异常时,应立即向本 SIP监控域 的SIP服务器发送状态信息;无异常时,应定时向本SIP监控域的SIP服务器发送状态信息。 SIP设备 29 GB/T28

如何在unity下采集音视频实现轻量级rtsp服务(类似于ipc)_videostreamtrack-爱代码爱编程

好多开发者在做虚拟仿真、VR教育等场景的时候,遇到个问题,想把头显里面的画面在内网环境下低延迟的同步出来,又不想单独部署流媒体服务器。为此,我们在Unity下,添加了轻量级RTSP服务模块,通过头显端启动个轻量级RTSP服务,把采集到的音视频数据,通过对外提供RTSP拉流URL的形式,供内网其他终端调用,废话不多说,先上图看效果:  上图展示的是,A

android gb28181接入端实时位置订阅和上报之-爱代码爱编程

我们在做Android平台GB28181的时候,其中实时位置(MobilePosition)订阅和上报这块,涉及到实时经纬度的获取,特别是执法记录、车载系统的那个等场景,几乎就是标配。 今天主要是分享一段实时获取位置的代码: /* * CameraPublishActivity.java * CameraPublishActivit