Video streaming 如何在H265/HEVC的RTP数据(通过UDP)中解除碎片帧的打包?

Video streaming 如何在H265/HEVC的RTP数据(通过UDP)中解除碎片帧的打包?,video-streaming,rtp,hevc,video-codecs,h.265,Video Streaming,Rtp,Hevc,Video Codecs,H.265,我正在尝试对原始RTP H265流进行解包并重建它,以便解码器可以读取它。 通过识别NAL和FU细节,我已经能够从RTP缓冲区中提取单个和碎片单元。但是,我找不到关于处理要放在碎片单元缓冲区前面的NAL的确切细节 以下是我的工作: 当有效负载头类型为49时,我知道它是一个碎片单元 然后我查找第三个字节,其尾部的6个字节为FU type/NAL类型,前两位告诉您它是帧的开始还是结束片段。 以下是重建NAL的代码: if(类型==49){ 无符号字符fu_头=(无符号字符)*(rtpPayloadP

我正在尝试对原始RTP H265流进行解包并重建它,以便解码器可以读取它。 通过识别NAL和FU细节,我已经能够从RTP缓冲区中提取单个和碎片单元。但是,我找不到关于处理要放在碎片单元缓冲区前面的NAL的确切细节

以下是我的工作:

  • 当有效负载头类型为49时,我知道它是一个碎片单元

  • 然后我查找第三个字节,其尾部的6个字节为FU type/NAL类型,前两位告诉您它是帧的开始还是结束片段。 以下是重建NAL的代码:

  • if(类型==49){
    无符号字符fu_头=(无符号字符)*(rtpPayloadPos+2);
    无符号字符fu_head_se=(fu_header&0xC0)>>6;
    nal_type=fu_头&0x3F;
    开关(前端){
    案例0x02://nal开始
    {
    payloadType=RTP\u有效载荷\u FU\u启动\u H265\u NAL;
    *h265DataPos=rtpPlayloadPos-3;
    *(*h265DataPos)=0x00;
    *((*h265DataPos)+1)=0x00;
    *((*h265DataPos)+2)=0x00;
    *((*h265DataPos)+3)=0x01;
    *((*h265DataPos)+4)=(fu_headerRFC规范中包含了这方面的所有细节

    要遵循的简单步骤:

  • 删除12字节的RTP头和3字节的FU头
  • 合并所有FU分组,直到找到/接收到来自视频编码帧的结束分组
  • 组合的所有包(如果多个包形成一个帧)形成视频帧,可以将其馈送到解码器

  • 感谢您的输入。我已经过了那个阶段。我已经将所有FU数据包合并并写入H265文件。但是当我在ffplay上查看此文件时,它会说:“cu_qp_delta-57超出了有效范围”。这看起来像是对PPS参数中QP范围的引用。但是,如果我使用ffplay直接从流中保存文件,并将我的文件与使用ffplay录制的文件进行比较,它们的VPS、SP和PPS看起来是相同的。但是由于某些原因,我的视频无法使用相同的ffplay正确播放。这使我认为我没有处理FU Info正确。确保编码器输出和解码器输入转储相同。您可以将它们转储到文件并进行二进制比较-验证是否相同。我修复了问题。问题是,在碎片单元的中间和最后一个切片中,我应该删除前三个字节,然后追加它们。但是,我删除了前两个字节太奇怪了,因为ffplay一直在抱怨cu_qp_delta让我偏离了轨道。谢谢@mail2subhajit的帮助
    if(type == 49){
    
        unsigned char fu_header = (unsigned char) *(rtpPayloadPos+2);
        unsigned char fu_head_se = (fu_header & 0xC0) >> 6;
        nal_type = fu_header & 0x3F;
    
        switch(fu_head_se){
    
        case 0x02:         //nal start
        {
            payloadType = RTP_PAYLOAD_FU_START_H265_NAL;
            *h265DataPos = rtpPlayloadPos-3;
            *(*h265DataPos) = 0x00;
            *((*h265DataPos)+1) = 0x00;
            *((*h265DataPos)+2) = 0x00;
            *((*h265DataPos)+3) = 0x01;
            *((*h265DataPos)+4) = (fu_header << 1);
            *((*h265DataPos)+5) = 0x01;
            h265Len = len - headLen + 3; 
        }
        break;
    
        case 0x00:     //nal middle
        {
            *h265DataPos = rtpPlayloadPos+2;
            h265Len = len - headLen - 2;
            payloadType = RTP_PAYLOAD_FU_MIDDLE_H265_NAL;
        }
        break;
    
        case 0x01:     //nal end
        {
            *h265DataPos = rtpPlayloadPos+2;
            h265Len = len - headLen - 2;
            payloadType = RTP_PAYLOAD_FU_END_H265_NAL;
        }
        break;
    
        default:
            printf("Unknown fu head\n");
            return -1;
    
    }