不久前刚实现SkeyeRTMPPusher扩大反对h265推送,过后在网上也查找了很多材料,发现都不尽具体,而官网也没有更新对HEVC(H265,后文统称HEVC)tag的反对,反正是走了不少弯路,当然,在宽广网友以及ffmpeg代码的帮忙下我最终实现了通过SkeyeRTMPPusher推送HEVC视频帧数据到SkeyeSMS,这里我将把实现过程具体的记录下来,供宽广网友参考。

首先, RTMP头部信息封装并没有定义HEVC,咱们采纳CDN联盟的HEVC扩大规范,将HEVC的VideoTagHeader定义为12,详见下图:![在这里插入图片形容](https://img-blog.csdnimg.cn/img_convert/3319b358ebe3b50efd59cb16cb18a292.png)而后,咱们在H264封装的根底上进行改良,以反对HEVC头部的封装,而HEVC头有

SPS PPS VPS,咱们参考ffmpeg的HEVCDecoderConfigurationRecord构造对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;

参考ffmeg对该构造进行初始化如下:

static void hvcc_init(HEVCDecoderConfigurationRecord *hvcc){    memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord));    hvcc->configurationVersion = 1;    hvcc->lengthSizeMinusOne   = 3; // 4 bytes    /*     * The following fields have all their valid bits set by default,     * the ProfileTierLevel parsing code will unset them when needed.     */    hvcc->general_profile_compatibility_flags = 0xffffffff;    hvcc->general_constraint_indicator_flags  = 0xffffffffffff;    /*     * Initialize this field with an invalid value which can be used to detect     * whether we didn't see any VUI (in which case it should be reset to zero).     */    hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1;}

须要留神的是,该构造其余参数咱们其实能够不特地关怀,咱们只须要在HVCCNALUnitArray数组中把HEVC的VPS,SPS和PPS信息填入即可。

最初,填写好Metadata信息后,咱们还须要在发送帧数据的时候做一下批改,将I帧的tag头改成12,P帧tag不变,设置成1即可,如下代码所示:

    int i = 0;    if(bIsKeyFrame)    {        //body[i++] = 0x17;// 2:Pframe  7:AVC        body[i++] =      (m_metadata.nVideoCodec  == FLV_CODECID_HEVC) ? 0x1C:0x17;// 1:Iframe  7:AVC 12:HEVC        if (m_bWaitingKeyFrame)        {            m_bWaitingKeyFrame = false;        }    }    else    {        //body[i++] = 0x27;// 2:Pframe  7:AVC        body[i++] =      (m_metadata.nVideoCodec  == FLV_CODECID_HEVC) ? 0x2C:0x27;// 1:Iframe  7:AVC 12:HEVC    }    body[i++] = 0x01;// AVC NALU    body[i++] = 0x00;    body[i++] = 0x00;    body[i++] = 0x00;    // NALU size    body[i++] = size>>24;    body[i++] = size>>16;    body[i++] = size>>8;    body[i++] = size&0xff;

有相干的技术问题,欢送大家和我进行技术交换:
295222688@qq.com
大家也能够退出SkeyeRTMP直播推流技术 QQ群进行探讨:
102644504