解决方案)
不久前我们已经在RTMP推送端扩展支持了HEVC(H.265 后文统称H265)编码格式但是由于RTMP官方指定的协议格式已经不再更新官方的播放器的Flash播放器并不支持H265格式的编码数据进行解码播放现在我们需要在播放器端解析RTMP流时对H265编码格式进行扩展支持。首先我们可以通过扩展ffmpeg让其支持拉H265封装的RTMP流进行解码播放我们可以通过金山云对FFmepg的扩展支持H265来解决。然后我们通过修改SkeyeRTMPClient的代码实现对H265 的支持因为我们已经实现了推送端的扩展支持所以播放端支持则相对比较简单不过依然有几个方面我们需要注意下面将对整个扩展流程进行介绍。1. 扩展编码ID和推送端一样需要先扩展支持H265的编码ID我们定义为12如下代码所示enum FlvVideoCodecId { e_FlvVideoCodecId_None 0, e_FlvVideoCodecId_Jpeg 1, e_FlvVideoCodecId_H263 2, e_FlvVideoCodecId_Screen 3, e_FlvVideoCodecId_Vp6 4, e_FlvVideoCodecId_Vp6Alpha 5, e_FlvVideoCodecId_ScreenV2 6, e_FlvVideoCodecId_Avc 7, // RTMP扩展支持HEVC(H.265) e_FlvVideoCodecId_Hevc 12, }; enum FlvCodeId { FlvCodeId_Jpeg 1, FlvCodeId_Sorenson 2, FlvCodeId_ScreenVideo 3, FlvCodeId_On2Vp6 4, FlvCodeId_On2Vp6Alpha 5, FlvCodeId_ScreenVideoV2 6, FlvCodeId_AVC 7, // RTMP扩展支持HEVC(H.265) FlvCodeId_Hevc 12, };2. 扩展H265特有头部数据结构VPS因为H264只有SPS和PPS所以在兼容H265的时候我们需要定义其特有的头VPS:char vps_buf_[MAX_VPS_LEN];//256 int vps_len_;3. MetaData解析扩展支持H265在推送端我们扩展H265发送的MetaData结构定义如下typedef struct HVCCNALUnitArray { uint8_t array_completeness; uint8_t NAL_unit_type; uint16_t numNalus; uint16_t *nalUnitLength; uint8_t **nalUnit; } HVCCNALUnitArray; typedef struct HEVCDecoderConfigurationRecord { uint8_t configurationVersion; uint8_t general_profile_space; uint8_t general_tier_flag; uint8_t general_profile_idc; uint32_t general_profile_compatibility_flags; uint64_t general_constraint_indicator_flags; uint8_t general_level_idc; uint16_t min_spatial_segmentation_idc; uint8_t parallelismType; uint8_t chromaFormat; uint8_t bitDepthLumaMinus8; uint8_t bitDepthChromaMinus8; uint16_t avgFrameRate; uint8_t constantFrameRate; uint8_t numTemporalLayers; uint8_t temporalIdNested; uint8_t lengthSizeMinusOne; uint8_t numOfArrays; HVCCNALUnitArray *array; } HEVCDecoderConfigurationRecord;现在我们需要从MetaData里面讲VPSSPS和PPS解析出来首先判断视频编码格式parser_VideoTag *video_tag (parser_VideoTag*)(bufparser_offset); FlvCodeId video_code_id (FlvCodeId)(video_tag-code_id0x0f); if (video_code_id FlvCodeId_Hevc) { av_frame.u32AVFrameFlag SKEYE_SDK_VIDEO_CODEC_H265;// HEVC; } else { av_frame.u32AVFrameFlag SKEYE_SDK_VIDEO_CODEC_H264;// 默认h264, 其他类型是否需要判断?!; }然后判断视频帧格式为H265后我们从MetaData中获取VPS,SPS和PPS如下代码所示char *parser_config buf; Parser_HEVCDecoderConfigurationRecord *decoder_header (Parser_HEVCDecoderConfigurationRecord*)((char*)parser_config); parser_offset sizeof(Parser_HEVCDecoderConfigurationRecord); int nNumOfArrays decoder_header-numOfArrays; for (int i0; inNumOfArrays; i) { Parser_HVCCNALUnitArray* pNALUnit (Parser_HVCCNALUnitArray*)((char *)parser_configparser_offset); parser_offset sizeof(Parser_HVCCNALUnitArray); int numNalus ntohs(*(unsigned short *)((char *)parser_config parser_offset)); parser_offset 2; for (int nI0; nInumNalus; nI) { // uint16_t *nalUnitLength; // uint8_t **nalUnit; ps_len *pNALUnit[i]-nalUnitLength; if (pNALUnit[nI]-NAL_unit_type 0x20) { //获取VPS memcpy(vps_buf_, *pNALUnit[i]-nalUnit, ps_len); vps_len_ ps_len; } else if (pNALUnit[nI]-NAL_unit_type 0x021) { //获取SPS memcpy(sps_buf_,*pNALUnit[i]-nalUnit, ps_len); sps_len_ ps_len; } else if (pNALUnit[nI]-NAL_unit_type 0x22) { //获取PPS memcpy(pps_buf_,*pNALUnit[i]-nalUnit, ps_len); pps_len_ ps_len; } parser_offset ps_len; } } //从H265的SPS头部结构中取得视频长宽 rtmpclient_h265_decode_sps((unsigned char *)sps_buf_, sps_len_, width_, height_);4. 视频数据帧Nalu解析扩展支持H265首先判断如果是H265视频帧则需要解析视频帧是否携带VPSif(av_frame.u32AVFrameFlag SKEYE_SDK_VIDEO_CODEC_H265) { nalu_type (buf[parse_offset] 1) 0x3F; if(nalu_type e_H265_NAL_UNIT_VPS) { memcpy(vps_buf_,buf parse_offset,nalu_len); vps_len_ nalu_len; parse_offset nalu_len; continue; } }else{ nalu_type buf[parse_offset]0x1F; }然后对于SPS和PPS以及Idr帧、P帧的nalu数据单元的解析该部分解析和H264解析方法一致就不做过多赘述。下面我们通过SkeyeScreenLive来推H265编码格式的RTMP流到SkeyeSMS通过skeyplayerffmpeg拉流和skeyeexpeedplayer(SkeyeRTMPClient拉流)播放如下图所示我们发现通过网页播放我们推送的基于H265编码的RTMP是播放不了的而通过SkeyePlayer则成功播放了出来说明我们通过SkeyeRTMPClient拉取RTMP流扩展支持H265的方案已经完美解决。欢迎大家下载SkeyePlayer测试播放支持H265的RTMP流https://gitee.com/visual-opening/skeyplayerhttps://gitee.com/visual-opening/skeyeexspeedplayer有任何技术问题欢迎大家和我进行技术交流295222688qq.com大家也可以加入SkeyePlayer流媒体播放器 QQ群进行讨论102644504