海思A182-Hi3516DV300推流摄像头数据

思A182-Hi3516DV300推流摄像头数据

如果已经按照上一篇文章移植成功了opendump说明你已经成功了一大半,但是下面的一半也不是随随便便成功的,在你想要把librtmp库移植到你的开发板上面,你会遇到各种问题,我就不把遇到各种问题详细说出来了,尽量按照正确调试步骤去走。

移植需求

在移植的过程你要考虑一下,你想实现的要求,实现这个要求,你要满足甚么条件

1. rtmp推流的需求

首先这里说一下,经过多方打听,了解到rtmp协议貌似只能推送封装好的.FLV文件,好吧!这下可怎么办 ?我们摄像头编码完以后可是H264或者H265的流文件,这里你就要考虑一下,.FLV是甚么?.H264又是个甚么了?如何把H264的编码文件封装成FLV的视频文件?

1.1 H264封装FLV

封装前其实还是需要对这两块有一些浅显的认识,不认识也没关系,对你调试来说肯定会造成一些麻烦、在这里我还是简单介绍一下吧:
h264是一个个NALU单元组成的,每个单元以00 00 01 或者 00 00 00 01分隔开来,每2个00 00 00 01之间就是一个NALU单元。我们实际上就是将一个个NALU单元封装进FLV文件。

H264编码组成结构

在这里插入图片描述

													  图1(NALU介绍图)

从上图可以看出H264存储方式是一个个NALU组成:一个NALU包含 START CODE、NALU HEADER、RBSP
看了挺多资料很多时候容易被误导,每次看别的博主介绍的时候,我总是误以为所有的NALU都是一样的,其实不是,上面说了一个NALU包含 START CODE、NALU HEADER、RBSP

  1. START CODE:一般是00 00 01 或者 00 00 00 01,你可以理解为一个NALU的开始,用以区分是不是有另一组NALU要传递过来了。
  2. NALU HEADER:这个更好理解了,说白了就是功能码,不同的值说明了 RBSP功能 NALU HEADER更像标题,而RBSP就是实施方案。
  3. RBSP:实施方案。

这里我不对RBSP多做介绍,因为我也是刚研究,具体需要挺多时间去学习研究,先搞明白NALU有哪三部分组成,如果能理解NALU大致组成就可以去具体说明一帧图片的组成原理,不说废话上图:
在这里插入图片描述
说了半天,那到底一帧图有什么组成嘛?别着急,我来慢慢说清楚,一帧图是有一个个NALU组成,就如同说一个坦克连队是由一名名士兵组成,这样说是没问题的,既然是坦克连是不是要能驾驶并且能够开发挥坦克的功能,那这里就需要把士兵们封装成一个个小组,也就是我们所说的序列(sequence),那士兵有什么职能也就等价于 NALU HEADER 取值多少,在这里我把这种等价关系说一下:
一个坦克连=多个坦克小组
一个坦克小组 = 主驾驶员,填炮手,发炮手,机枪手,外加随从坦克人员,可以是一个也可以是多个,随从人员你可以认为是PDR,士兵负责甚么工作,由NALU HEADER 来决定
0X67:主驾驶员
0X68:填炮手
0X06:发炮手
0X65:机枪手
0X61:随从坦克人员
所以说一帧图是由一个个NALU组成,但是是需要NALU按照一定的规约顺序排列起来,组成一个个序列发送过来。

总结

上述都能基本理解的情况下,你只需要获得两个功能代码,一个是RTMP推流FLV代码,一个是H264转FLV代码,甚么原因前面已经说过了RTMP只能推流FLV格式的文件

   RTMP rtmp = { 0 };



    FILE* pFile = fopen("rtmp_test.flv", "rb");
    printf("文件打开成功\r\n");
    // 初使化RTMP上下文
    RTMP* pRTMP =&rtmp;
    RTMP_Init(pRTMP);

    printf("初始化pRTMP成功\r\n");
        // 设置推流地址
    pRTMP->Link.timeout = 10;
    RTMP_SetupURL(pRTMP, (char*)"rtmp://192.168.8.153:1935/live");
    printf("连接成功\r\n");

        // 开启推流标志
    RTMP_EnableWrite(pRTMP);
    printf("推流开启成功\r\n");
 
    // 连接服务器
    if ( !RTMP_Connect(pRTMP, NULL))
    {
        printf("connect failed! \n");
        return -1;
    }
        printf("连接服务器成功\r\n");
    // 连接流地址
    if (!RTMP_ConnectStream(pRTMP, 0))
    {
        printf("connect stream failed! \n");
        return -1;
    }
    printf("连接流地址成功\r\n");
 

    // 跳过FLV文件头的13个字节
    
    fseek(pFile, 9, SEEK_SET);
    fseek(pFile, 4, SEEK_CUR);
    printf("跳过头文件\r\n");
    // 初使化RTMP报文
    RTMPPacket packet= { 0 };
    RTMPPacket_Reset(&packet);
    packet.m_body = NULL;
    packet.m_chunk = NULL;
 
    packet.m_nInfoField2 = pRTMP->m_stream_id;
    printf("初始化报文成功\r\n");
    uint32_t starttime = RTMP_GetTime();
     while (1)
    {
        // 读取TAG头
 
        uint8_t type = 0;
        if (!ReadU8(&type, pFile))
            break;
         printf("读取type成功:%x\r\n",type);
 
        uint32_t datalen = 0;
        if (!ReadU24(&datalen, pFile))
            break;
        printf("读取datalen成功:%x\r\n",datalen);
        
        uint32_t timestamp = 0;
        if (!ReadTime(&timestamp, pFile))
            break;
         printf("读取timestamp成功:%x\r\n",timestamp);
 
        uint32_t streamid = 0;
        if (!ReadU24(&streamid, pFile))
            break;
         printf("读取streamid成功:%x\r\n",streamid);
/*
        // 跳过0x12 Script
        if (type != 0x08 && type != 0x09)
        {
            fseek(pFile, datalen + 4, SEEK_CUR);
            continue;
        }
*/
 

        printf("准备初始化了Alloc\r\n");
        RTMPPacket_Alloc(&packet, datalen);
 
        if (fread(packet.m_body, 1, datalen, pFile) != datalen)
            break;
        // 组织报文并发送
        packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
        packet.m_packetType = type;
        packet.m_hasAbsTimestamp = 0;
        packet.m_nChannel = 6;
        packet.m_nTimeStamp = timestamp;
        packet.m_nBodySize = datalen;

/*         packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
        packet.m_packetType = 0x12;
        packet.m_hasAbsTimestamp = 0;
        packet.m_nChannel = 6;
        packet.m_nTimeStamp = 0;
        packet.m_nBodySize = 0x170; */
 
 
        if (!RTMP_SendPacket(pRTMP, &packet, 0))
        {
            printf("Send Error! \n");
            break;
        }
 
        printf("send type:[%d] timestamp:[%d] datasize:[%d] \n", type, timestamp, datalen);
 
        // 跳过PreTag
        uint32_t pretagsize = 0;
        if (!ReadU32(&pretagsize, pFile))
            break;
 
        // 延时,避免发送太快
        uint32_t timeago = (RTMP_GetTime() - starttime);
        if (timestamp > 1000 && timeago < timestamp - 1000)
        {
            printf("sleep...\n");
            usleep(100000);
        }
 
        RTMPPacket_Free(&packet);
    }
 
    // 关闭连接,释放RTMP上下文
    RTMP_Close(pRTMP);
    RTMP_Free(pRTMP);
 
    fclose(pFile);
 
    return 0;

上述是利用RTMP推送FLV格式的文件代码,比较小可以复制。
H264代码是一个文件,我想看我博客的基本都是易百纳群里的群友,下载不下来,可以直接找我要。能下载下来的可以直接,在我博客直接下载,也可以私信我,单独发给有需求的兄弟。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值