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

dhr*_*uva 7 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);
Run Code Online (Sandbox Code Playgroud)

然后响应来自服务器的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);
   }
}
Run Code Online (Sandbox Code Playgroud)

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

Sir*_*ius 7

根据我自己的经验,在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;
Run Code Online (Sandbox Code Playgroud)

体长和时间戳表示为24位大端整数,并带有一个补充字节,以便在必要时将时间戳扩展到32位(大约在4小时左右).

读完标签标题后,您可以读取正文本身,因为您现在知道它的长度(body_length).

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

您必须在一次 RTMP_Write调用中写入标记标题+正文+之前的标记大小(否则它将无法播放).

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

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


wee*_*ens 0

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

RTMPPacket *pkt = &r->m_write;
...
pkt->m_packetType = *buf++;
Run Code Online (Sandbox Code Playgroud)

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

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

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

编辑:

RTMP_Write() 中存在某些错误。我已经打了补丁,现在可以用了。我要发布那个。