【问题标题】:Publishing a stream using librtmp in C/C++在 C/C++ 中使用 librtmp 发布流
【发布时间】:2011-05-30 07:16:42
【问题描述】:

如何使用 librtmp 库发布流? 我阅读了 librtmp 手册页并在发布时使用了 RTMP_Write()。

我就是这样做的。

//Code
//Init RTMP code
RTMP *r;
char uri[]="rtmp://localhost:1935/live/desktop";
r= RTMP_Alloc();
RTMP_Init(r);
RTMP_SetupURL(r, (char*)uri);
RTMP_EnableWrite(r);
RTMP_Connect(r, NULL);
RTMP_ConnectStream(r,0);

然后为了响应来自服务器的 ping/其他消息,我使用一个线程来响应如下:

//Thread
While (ThreadIsRunning && RTMP_IsConnected(r) && RTMP_ReadPacket(r, &packet))
{
   if (RTMPPacket_IsReady(&packet))
   {
 if (!packet.m_nBodySize)
         continue;
    RTMP_ClientPacket(r, &packet); //This takes care of handling ping/other messages
    RTMPPacket_Free(&packet);
   }
}

在这之后我被困在如何使用 RTMP_Write() 将文件发布到 Wowza 媒体服务器?

【问题讨论】:

    标签: rtmp


    【解决方案1】:

    根据我自己的经验,在 librtmp 端,将视频数据流式传输到 RTMP 服务器实际上非常简单。棘手的部分是正确打包视频/音频数据并以正确的速率读取。

    假设您使用的是 FLV 视频文件,只要您可以正确隔离文件中的每个标签并使用一个 RTMP_Write 调用发送每个标签,您甚至不需要处理传入的数据包。

    棘手的部分是了解 FLV 文件是如何制作的。 官方规范在这里:http://www.adobe.com/devnet/f4v.html

    首先,有一个标题,它由 9 个字节组成。此标头不得发送到服务器,而只能通读以确保文件确实是 FLV。

    然后是标签流。每个标签都有一个 11 字节的标头,其中包含标签类型(视频/音频/元数据)、正文长度和标签的时间戳等。

    标签头可以用这个结构来描述:

    typedef struct __flv_tag {
      uint8       type;
      uint24_be   body_length; /* in bytes, total tag size minus 11 */
      uint24_be   timestamp; /* milli-seconds */
      uint8       timestamp_extended; /* timestamp extension */
      uint24_be   stream_id; /* reserved, must be "\0\0\0" */
      /* body comes next */
    } flv_tag;
    

    正文长度和时间戳显示为 24 位大端整数,如有必要,可使用一个补充字节将时间戳扩展到 32 位(大约在 4 小时左右)。

    一旦您阅读了标签标题,您就可以阅读正文本身,因为您现在知道它的长度 (body_length)。

    之后有一个 32 位大端整数值,其中包含标签的完整长度(11 个字节 + body_length)。

    你必须在一个RTMP_Write调用中写标签头+正文+之前的标签大小(否则它不会播放)。

    另外,请注意以视频的标称帧速率发送数据包,否则播放会受到很大影响。

    我已经编写了一个完整的 FLV 文件解复用器,作为我的 GPL 项目 FLVmeta 的一部分,您可以将其用作参考。

    【讨论】:

      【解决方案2】:

      实际上,RTMP_Write() 似乎要求你已经在 buf 中形成了 RTMP 数据包。

      RTMPPacket *pkt = &r->m_write;
      ...
      pkt->m_packetType = *buf++;
      

      因此,您不能只将 flv 数据推送到那里 - 您需要先将其分成数据包。

      有一个不错的函数,RTMP_ReadPacket(),但它从网络套接字读取。

      我和你有同样的问题,希望尽快有解决方案。

      编辑:

      RTMP_Write() 中存在某些错误。我做了一个补丁,现在它可以工作了。我要发布它。

      【讨论】:

      • 你发现了什么错误?你在哪里发布的?
      • 酷,谢谢,我会看看你的代码。但事实上,我实际上花了一些时间来分析 RTMP_Write 函数,并认为你所说的不正确;因为它不希望您有一个已经形成的数据包,而是解析存储在 buf 中的文件的内容并在此过程中组成数据包。
      • 是的,这是真的。您不需要对流进行打包,只需将字节推送到 RTMP_Write()。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-25
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多