如何使用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媒体服务器?
根据我自己的经验,在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的一部分,您可以将其用作参考.
事实上,RTMP_Write() 似乎要求您已经在 buf 中形成了 RTMP 数据包。
RTMPPacket *pkt = &r->m_write;
...
pkt->m_packetType = *buf++;
Run Code Online (Sandbox Code Playgroud)
因此,您不能只将 flv 数据推送到那里 - 您需要首先将其分离为数据包。
有一个很好的函数 RTMP_ReadPacket(),但它从网络套接字读取。
我和你有同样的问题,希望尽快有解决方案。
编辑:
RTMP_Write() 中存在某些错误。我已经打了补丁,现在可以用了。我要发布那个。
| 归档时间: |
|
| 查看次数: |
11406 次 |
| 最近记录: |