C语言 封装h264转ps流输出 gb28181

最近刚做了PS流的封装,网上也看了很多但是发现都没有成功最后自己分析ps的抓包,一个一个字节对才发现正确的格式 所以每帧的格式封包如下:

关键帧 封包:PS headle + PS SYS headle + PS map +(pes +h264 的SPS帧 )+( pes +h264 的PPS) +(pes+h264 的I帧)
次要帧 封包PS headle+pes+h264的次要帧数据

然后打rtp发送即可 ,rtp封包网上很多,就不多说了,这里的关键帧封包 我是没有按照顺序(pes +h264的SPS )+( pes +h264 的PPS) +(pes+h264 的I帧)也是可以的

GBT 28181-2016 公共安全视频监控联网系统信息传输、交换、控制技术要求中的封装如下图。
在这里插入图片描述

下面是主要实现,后打rtp发送

       if (h264_stream.nalu_cnt > 1)
       {
             int i = 0;
             len += PS_HDR_LEN + SYS_HDR_LEN + PSM_HDR_LEN;
             for (i = 0; i < h264_stream.nalu_cnt; i++)
             {
                 len += PES_HDR_LEN + h264_stream.nalu[i].length;
             }

             om = allocb(len, 0);
             gb28181_package_for_h264(d, &h264_stream, TRUE, om->b_wptr);
             om->b_wptr += len;
       }
       else if (h264_stream.nalu_cnt == 1)
       {
           len = PS_HDR_LEN + PES_HDR_LEN + h264_stream.nalu[0].length;

           om = allocb(len, 0);
           gb28181_package_for_h264(d, &h264_stream, FALSE, om->b_wptr);
           om->b_wptr += len;
       }
  	   **下面就是打rtp包  注意要分片,关键帧he非关键帧都要分片,不需要重新加头直接超过mtu就分**

封包函数

static int gb28181_package_for_h264(fhVideoReaderData_t *d, msFhH264StreamInfo_t *h264_stream, bool_t is_iframe, char *ps_stream)
{
    int i = 0;
    int stream_pos = 0;

    gb28181_make_ps_header(ps_stream + stream_pos, d->timestamp);
    stream_pos += PS_HDR_LEN;

    if (is_iframe)
    {
        gb28181_make_sys_header(ps_stream + stream_pos);
        stream_pos += SYS_HDR_LEN;

        gb28181_make_psm_header(ps_stream + stream_pos);
        stream_pos += PSM_HDR_LEN;
    }

    for (i = 0; i < h264_stream->nalu_cnt; i++)
    {
        gb28181_make_pes_header(ps_stream + stream_pos, 0xE0, h264_stream->nalu[i].length, d->timestamp, d->timestamp);
        stream_pos += PES_HDR_LEN;

        memcpy(ps_stream + stream_pos, h264_stream->nalu[i].start, h264_stream->nalu[i].length);
        stream_pos += h264_stream->nalu[i].length;
    }

    return 0;

}

各个头的封包格式


int gb28181_make_ps_header(char *pData, unsigned long long s64Scr)
{
    unsigned long long lScrExt = (s64Scr) % 100;

    bits_buffer_s   bitsBuffer;
    bitsBuffer.i_size = PS_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, PS_HDR_LEN);
    bits_write(&bitsBuffer, 32, 0x000001BA);
    bits_write(&bitsBuffer, 2,  1);
    bits_write(&bitsBuffer, 3,  (s64Scr>>30)&0x07);
    bits_write(&bitsBuffer, 1,  1);
    bits_write(&bitsBuffer, 15, (s64Scr>>15)&0x7FFF);
    bits_write(&bitsBuffer, 1,  1);
    bits_write(&bitsBuffer, 15, s64Scr&0x7fff);
    bits_write(&bitsBuffer, 1,  1);
    bits_write(&bitsBuffer, 9,  lScrExt&0x01ff);
    bits_write(&bitsBuffer, 1,  1);
    bits_write(&bitsBuffer, 22, (255)&0x3fffff);
    bits_write(&bitsBuffer, 2,  3);
    bits_write(&bitsBuffer, 5,  0x1f);
    bits_write(&bitsBuffer, 3,  0);

    return 0;

}

int gb28181_make_sys_header(char *pData)
{
    bits_buffer_s   bitsBuffer;
    bitsBuffer.i_size = SYS_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, SYS_HDR_LEN);

    bits_write( &bitsBuffer, 32, 0x000001BB);
    bits_write( &bitsBuffer, 16, SYS_HDR_LEN-6);
    bits_write( &bitsBuffer, 1,  1);
    bits_write( &bitsBuffer, 22, 50000);
    bits_write( &bitsBuffer, 1,  1);
    bits_write( &bitsBuffer, 6,  1);
    bits_write( &bitsBuffer, 1,  0);
    bits_write( &bitsBuffer, 1,  1);
    bits_write( &bitsBuffer, 1,  1);
    bits_write( &bitsBuffer, 1,  1);
    bits_write( &bitsBuffer, 1,  1);
    bits_write( &bitsBuffer, 5,  1);
    bits_write( &bitsBuffer, 1,  0);
    bits_write( &bitsBuffer, 7,  0x7F);

    bits_write( &bitsBuffer, 8,  0xC0);
    bits_write( &bitsBuffer, 2,  3);
    bits_write( &bitsBuffer, 1,  0);
    bits_write( &bitsBuffer, 13, 512);

    bits_write( &bitsBuffer, 8,  0xE0);
    bits_write( &bitsBuffer, 2,  3);
    bits_write( &bitsBuffer, 1,  1);
    bits_write( &bitsBuffer, 13, 2048);

    return 0;

}

int gb28181_make_psm_header(char *pData)
{

    bits_buffer_s   bitsBuffer;
    bitsBuffer.i_size = PSM_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, PSM_HDR_LEN);
    bits_write(&bitsBuffer, 24,0x000001);
    bits_write(&bitsBuffer, 8, 0xBC);
    bits_write(&bitsBuffer, 16,18);
    bits_write(&bitsBuffer, 1, 1);
    bits_write(&bitsBuffer, 2, 3);
    bits_write(&bitsBuffer, 5, 0);
    bits_write(&bitsBuffer, 7, 0x7F);
    bits_write(&bitsBuffer, 1, 1);
    bits_write(&bitsBuffer, 16,0);
    bits_write(&bitsBuffer, 16, 8);

    bits_write(&bitsBuffer, 8, 0x90);
    bits_write(&bitsBuffer, 8, 0xC0);
    bits_write(&bitsBuffer, 16, 0);

    bits_write(&bitsBuffer, 8, 0x1B);
    bits_write(&bitsBuffer, 8, 0xE0);
    bits_write(&bitsBuffer, 16, 0);

    bits_write(&bitsBuffer, 8, 0x45);
    bits_write(&bitsBuffer, 8, 0xBD);
    bits_write(&bitsBuffer, 8, 0xDC);
    bits_write(&bitsBuffer, 8, 0xF4);

    return 0;

}

int gb28181_make_pes_header(char *pData, int stream_id, int payload_len, unsigned long long pts, unsigned long long dts)
{
    bits_buffer_s   bitsBuffer;
    bitsBuffer.i_size = PES_HDR_LEN;
    bitsBuffer.i_data = 0;
    bitsBuffer.i_mask = 0x80;
    bitsBuffer.p_data = (unsigned char *)(pData);
    memset(bitsBuffer.p_data, 0, PES_HDR_LEN);

    bits_write( &bitsBuffer, 24,0x000001);
    bits_write( &bitsBuffer, 8, (stream_id));
    bits_write( &bitsBuffer, 16,(payload_len)+13);
    bits_write( &bitsBuffer, 2, 2 );
    bits_write( &bitsBuffer, 2, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 1 );
    bits_write( &bitsBuffer, 1, 1 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 1, 0 );
    bits_write( &bitsBuffer, 8, 10);

    bits_write( &bitsBuffer, 4, 3 );
    bits_write( &bitsBuffer, 3, ((pts)>>30)&0x07 );
    bits_write( &bitsBuffer, 1, 1 );
    bits_write( &bitsBuffer, 15,((pts)>>15)&0x7FFF);
    bits_write( &bitsBuffer, 1, 1 );
    bits_write( &bitsBuffer, 15,(pts)&0x7FFF);
    bits_write( &bitsBuffer, 1, 1 );
    bits_write( &bitsBuffer, 4, 1 );
    bits_write( &bitsBuffer, 3, ((dts)>>30)&0x07 );
    bits_write( &bitsBuffer, 1, 1 );
    bits_write( &bitsBuffer, 15,((dts)>>15)&0x7FFF);
    bits_write( &bitsBuffer, 1, 1 );
    bits_write( &bitsBuffer, 15,(dts)&0x7FFF);
    bits_write( &bitsBuffer, 1, 1 );

    return 0;

}

格式长度
#define PS_HDR_LEN  14
#define SYS_HDR_LEN 18
#define PSM_HDR_LEN 24
#define PES_HDR_LEN 19

typedef struct
{
    unsigned char* p_data;
    unsigned char  i_mask;
    int i_size;
    int i_data;
}bits_buffer_s;
//字节按位压缩
#define bits_write(buffer, count, bits)\
{\
  bits_buffer_s *p_buffer = (buffer);\
  int i_count = (count);\
  uint64_t i_bits = (bits);\
  while( i_count > 0 )\
  {\
    i_count--;\
    if( ( i_bits >> i_count )&0x01 )\
    {\
      p_buffer->p_data[p_buffer->i_data] |= p_buffer->i_mask;\
    }\
    else\
    {\
      p_buffer->p_data[p_buffer->i_data] &= ~p_buffer->i_mask;\
    }\
    p_buffer->i_mask >>= 1;\
    if( p_buffer->i_mask == 0 )\
    {\
      p_buffer->i_data++;\
      p_buffer->i_mask = 0x80;\
    }\
  }\
}

负载包数据
在这里插入图片描述

PS的格式网上也有很多,可以自己抓包看格式,对得上的话基本就没问题
也可以自己写到本地,看播放是否成功

嵌入式GB28181是一种在嵌入式系统上实现的基于IP网络的视频监控通信协议,它可以实现视频监控设备之间的互联互通。在C语言中实现嵌入式GB28181可以通过以下步骤。 首先,我们需要了解GB28181协议,包括其格式和通信程。然后,我们可以使用C语言编写代码以实现协议的各个部分。 在编写代码时,我们需要使用TCP/IP协议栈来进行网络通信。可以使用C语言中的socket库来创建套接字并进行网络通信。 在嵌入式系统中,我们需要对底层硬件进行配置和管理。可以使用C语言中的GPIO库来控制嵌入式设备的输入输出。 对于媒体数据的处理,我们可以使用C语言中的多媒体库,例如FFmpeg,来进行视频和音频数据的解码和编码。 在实现嵌入式GB28181时,我们还需要实现协议中定义的各种消息和功能,例如设备注册、实时视频传输、录像回放等。 在开发过程中,我们需要对整个系统进行测试和调试。可以使用C语言的调试工具和模拟器进行代码的调试和测试。 最后,为了使系统更加稳定和可靠,我们可以使用C语言的内存管理和错误处理机制来进行内存的管理和异常的处理。 总结:通过使用C语言,我们可以实现嵌入式GB28181协议,实现视频监控设备之间的互联互通。通过理解协议规范、使用网络通信库、控制硬件、处理媒体数据和实现各种功能,我们可以开发出一套功能完善的嵌入式GB28181系统。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值