在 C/C++ 中使用 librtmp 发布流 [英] Publishing a stream using librtmp in C/C++

查看:86
本文介绍了在 C/C++ 中使用 librtmp 发布流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用 librtmp 库发布流?我阅读了 librtmp 手册页并使用了 RTMP_Write() 进行发布.

我就是这样做的.

//代码//初始化RTMP代码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/其他消息,我使用一个线程来响应如下:

//线程While (ThreadIsRunning && RTMP_IsConnected(r) && RTMP_ReadPacket(r, &packet)){如果 (RTMPPacket_IsReady(&packet)){如果(!packet.m_nBodySize)继续;RTMP_ClientPacket(r, &packet);//这负责处理ping/其他消息RTMPPacket_Free(&packet);}}

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

解决方案

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

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

棘手的部分是了解 FLV 文件是如何制作的.官方规范可在此处获得:http://www.adobe.com/devnet/f4v.html>

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

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

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

typedef struct __flv_tag {uint8 类型;uint24_be body_length;/* 以字节为单位,总标签大小减去 11 */uint24_be 时间戳;/* 毫秒 */uint8 时间戳扩展;/* 时间戳扩展 */uint24_be stream_id;/* 保留,必须是 "\0\0\0" *//* 接下来是身体 */} flv_tag;

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

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

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

您必须在one RTMP_Write 调用中写入标签标题 + 正文 + 前一个标签大小(否则不会播放).

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

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

How to publish a stream using librtmp library? I read the librtmp man page and for publishing , RTMP_Write() is used.

I am doing like this.

//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);

Then to respond to ping/other messages from server, I am using a thread to respond like following:

//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);
   }
}

After this I am stuck at how to use RTMP_Write() to publish a file to Wowza media server?

解决方案

In my own experience, streaming video data to an RTMP server is actually pretty simple on the librtmp side. The tricky part is to correctly packetize video/audio data and read it at the correct rate.

Assuming you are using FLV video files, as long as you can correctly isolate each tag in the file and send each one using one RTMP_Write call, you don't even need to handle incoming packets.

The tricky part is to understand how FLV files are made. The official specification is available here: http://www.adobe.com/devnet/f4v.html

First, there's a header, that is made of 9 bytes. This header must not be sent to the server, but only read through in order to make sure the file is really FLV.

Then there is a stream of tags. Each tag has a 11 bytes header that contains the tag type (video/audio/metadata), the body length, and the tag's timestamp, among other things.

The tag header can be described using this structure:

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;

The body length and timestamp are presented as 24-bit big endian integers, with a supplementary byte to extend the timestamp to 32 bits if necessary (that's approximatively around the 4 hours mark).

Once you have read the tag header, you can read the body itself as you now know its length (body_length).

After that there is a 32-bit big endian integer value that contains the complete length of the tag (11 bytes + body_length).

You must write the tag header + body + previous tag size in one RTMP_Write call (else it won't play).

Also, be careful to send packets at the nominal frame rate of the video, else playback will suffer greatly.

I have written a complete FLV file demuxer as part of my GPL project FLVmeta that you can use as reference.

这篇关于在 C/C++ 中使用 librtmp 发布流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆