使用C / C ++中的librtmp发布流

时间:2010-12-24 06:19:17

标签: rtmp

如何使用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媒体服务器?

2 个答案:

答案 0 :(得分:6)

根据我自己的经验,在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的一部分,您可以将其作为参考。

答案 1 :(得分:0)

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

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

所以,你不能只在那里推送flv数据 - 你需要先将它与数据包分开。

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

我遇到了和你一样的问题,希望很快能找到解决方案。

编辑:

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