一直以来,GB28181-2022之前的规范版本让人诟病的一点:没有明确针对H.265的说明,特别是监控摄像机,H.265已然成为标配,GB/T28181-2022规范,终于针对H.265做了明确的说明,让我们来一起解读下规范:
基于RTP的PS封装首先按照ISO/IEC 13818-1:2019将视音频流封装成PS包,再将PS包以负载的方式封装成RTP包。
进行PS封装时,应将母个悦team Map),系统头和PSM放置于PS包头之后、第一十 ti(System Header)和 PSM(Program Stream Map),系统头和PSM放置于PS包头之后、第一个PES包之前。
典型的视频关键帧PS包结构如图C.1所示,其中 PESV为视频PES包,PESA为音频PES包,视频非关键帧的PS包结构中一般不包含系统头和PSM。PS包中各部分的具体数据结构参见ISO/IEC13818-1 :2019中的相关描述。
系统头应包含对PS包中码流种类的描述,其中视频和音频的流ID(stream_id)取值如下: 视频流ID:0xEO;
针对本文件规定的几种视音频格式,PSM中流类型(stream_type)的取值如下: H.265视频流:0x24;
H.265视频流的RTP封装
H.265的RTP载荷格式应符合IETF RFC 7798的相关规定。
H.265视频流RTP包的负载类型(Payload Type)标识号选定:从IETF RFC3551协议表5的动态范围(96~~127)中选择,建议定为100,根据实际需要填充。
采用H.265标准的视频编码应至少支持ITU-T H.265(2019)视频标准的主档次(MainProfile),水平(Level)应至少支持到Level 2,标清应用宜扩展支持到Level 3,高清应用宜扩展支持到Level 4;视频解码所支持的档次和水平应不低于编码支持的最高档次和水平,至少应支持到H.265视频标准主档次的Level 4。视频解码宜扩展支持 H.265主档次(Main Profile)中的B帧工具,且相邻两Р帧间的B帧个数不大于2。
H.265主档次视频编码标准的具体描述详见ITU-T H.265(2019)的相关规定。
H.265主档次支持的选项和工具主要有:
a)比特深度限制为8 bit;
b)采样限制为4∶ 2∶ 0;
c)CTB的大小从16×16到64×64;
d)在水平(Level)支持的最大分辨率下﹐解码图像的缓存容量限制为6幅图像﹐若水平(Level)下
分辨率变小,解码图像的缓存容量可大于6幅图像,但不应超过16幅图像;
e)允许选择波前和片划分方式,但是不能同时选择。
采用H.265编码标准的视频流应为H.265主档次视频流,编码应支持上述主档次选项和工具中的部分或全部;H.265的解码至少应支持上述全部选项和工具。
多参考帧编码时,P片的参考帧数一般不大于两帧,且不应超过15帧。
为了保证码流解析的效率,比特流中应当在每个Ⅰ帧之前都出现相应的视频参数集(Video Param-eter Set,VPS)、序列参数集(Sequence Parameter Set, SPS)和图像参数集(Picture Parameter Set,PPS)。
实际上,我们在实现GB28181-2016的时候,就已经针对H.265做了设定:
设置如下:
//视频编码类型选择++++++++++
videoEncodeTypeSelector = (Spinner)findViewById(R.id.videoEncodeTypeSelector);
final String[] videoEncodeTypes = new String[]{"软编(H.264)", "硬编(H.264)", "硬编(H.265)"};
ArrayAdapter adapterVideoEncodeType = new ArrayAdapter(this,
android.R.layout.simple_spinner_item, videoEncodeTypes);
adapterVideoEncodeType.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
videoEncodeTypeSelector.setAdapter(adapterVideoEncodeType);
videoEncodeTypeSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView> parent, View view,
int position, long id) {
if (isRTSPPublisherRunning || isPushingRtmp || isGB28181StreamRunning || isRecording) {
Log.e(TAG, "Could not switch video encoder type during publishing..");
return;
}
videoEncodeType = position;
Log.i(TAG, "[视频编码类型]Currently choosing: " + videoEncodeTypes[position] + ", videoEncodeType: " + videoEncodeType);
}
@Override
public void onNothingSelected(AdapterView> parent) {
}
});
考虑到Android端设备编码性能,Android平台H.265编码,我们仅支持硬编码,如果需要H.265硬编,只需要调用SetSmartPublisherVideoHevcHWEncoder()接口即可,其中,第二个参数是针对编码码率的设定。
/**
* Author: daniusdk.com
* Set Video H.265(hevc) hardware encoder, if support H.265(hevc) hardware encoder, it will return 0(设置H.265硬编码)
*
* @param kbps: the kbps of different resolution.
*
* @return {0} if successful
*/
public native int SetSmartPublisherVideoHevcHWEncoder(long handle, int kbps);
当然也可以使用Native Media NDK硬编码,需要注意的是,Native Media NDK硬编码,需要Android 5.0以上系统,而且接口并不像原生那么全:
/**
* 设置视频硬编码是否使用 Native Media NDK, 默认是不使用, 安卓5.0以下设备不支持
* @param handle
* @param is_native: 0表示不使用, 1表示使用, sdk默认是0.
* @return {0} if successful
*/
public native int SetNativeMediaNDK(long handle, int is_native);
针对H.265硬编码,其他接口设计如下:
/*
* 设置视频硬编码码率控制模式
* @param hw_bitrate_mode: -1表示使用默认值, 不设置也会使用默认值, 0:CQ, 1:VBR, 2:CBR, 3:CBR_FD, 请参考:android.media.MediaCodecInfo.EncoderCapabilities
* 注意硬编码和手机硬件有关,多数手机只支持部分码率模式, 另外硬编码设备差异很大,不同设备同一码率控制模式效果可能不一样
* @return {0} if successful
*/
public native int SetVideoHWEncoderBitrateMode(long handle, int hw_bitrate_mode);
/*
* 设置视频硬编码复杂度, 安卓5.0及以上支持
* @param hw_complexity: -1表示不设置, 请参考:android.media.MediaCodecInfo.EncoderCapabilities.getComplexityRange() 和 android.media.MediaFormat.KEY_COMPLEXITY
* 注意硬编码和手机硬件有关,部分手机可能不支持此设置
* @return {0} if successful
*/
public native int SetVideoHWEncoderComplexity(long handle, int hw_complexity);
/*
* 设置视频硬编码质量, 安卓9及以上支持, 仅当硬编码器码率控制模式(BitrateMode)是CQ(constant-quality mode)时才有效
* @param hw_quality: -1表示不设置, 请参考:android.media.MediaCodecInfo.EncoderCapabilities.getQualityRange() 和 android.media.MediaFormat.KEY_QUALITY
* 注意硬编码和手机硬件有关,部分手机可能不支持此设置
* @return {0} if successful
*/
public native int SetVideoHWEncoderQuality(long handle, int hw_quality);
/*
* 设置视频硬编码最大码率, 安卓没有相关文档说明, 所以不建议设置,
* @param hw_max_bitrate: 每秒最大码率, 单位bps
* @return {0} if successful
*/
public native int SetVideoHWEncoderMaxBitrate(long handle, long hw_max_bitrate);
相关调用如下:
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, 0);
libPublisher.SetVideoHWEncoderBitrateMode(publisherHandle, 0); // 0:CQ, 1:VBR, 2:CBR
libPublisher.SetVideoHWEncoderQuality(publisherHandle, 39);
// libPublisher.SetVideoHWEncoderMaxBitrate(publisherHandle, ((long)hevcHWKbps)*1200);
Log.i(TAG, "Great, it supports hevc hardware encoder!");
}
GB28181-2022针对H.265描述,是2016的补充,随着今年七月份开始针对2022的实施推广,相信GB28181这块会应用到各行各业,如执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终端等场景。GB28181设备接入端支持H.265难度不大,平台侧如果需要web播放,一般来说是需要转H.264在播放,对国标平台侧的专门性能提高了要求,如果是cs架构,问题不大。