易百纳Hi3516DV300开发板推流摄像头数据

易百纳Hi3516DV300开发板推流摄像头数据 Mrs Wu 2024-01-18 15:33:56 874

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

上篇:基于Hi3516DV300rtmp交叉编译移植

移植需求

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

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编码组成结构

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

  • START CODE:一般是00 00 01 或者 00 00 00 01,你可以理解为一个NALU的开始,用以区分是不是有另一组NALU要传递过来了。
  • NALU HEADER:这个更好理解了,说白了就是功能码,不同的值说明了 RBSP功能 NALU HEADER更像标题,而RBSP就是实施方案。
  • 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格式的文件代码,比较小可以复制。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
Mrs Wu
红包 点赞 1 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
Mrs Wu
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区