gpt4 book ai didi

c - librtmp 示例 c 编程?

转载 作者:行者123 更新时间:2023-12-02 07:28:37 25 4
gpt4 key购买 nike

大家好,我是 c 编程的新手,想知道是否有人有一个非常简单的示例来打开 .flv 文件并使用 librtmp 发送到 wowza 服务器。

我发现很多代码可以使用该库进行连接,但在发布 flv 时却没有很多。

基本上:

初始化 librtmp -> 启用写入 -> 连接 -> 打包 flv -> 发送数据包直到完成

编辑:

好的,所以我必须先打开我的 flv 文件并隔离 flv 文件中的每个数据包以将其发送到 librtmp。到目前为止,我发现了这段代码:

https://github.com/noirotm/flvmeta/blob/master/src/flv.c

最佳答案

这是 FLVMeta 的作者在这里。

您可能想看看我对 this question 的回答: https://stackoverflow.com/a/13803143/393701

除了这些信息之外,我还可以解释我编写的 C++ 软件的某些部分(遗憾的是目前不是开源的),其目的是将 FLV 文件流式传输到 RTMP 服务器。

这已经过测试,并且可以与 Wowza、nginx-rtmp 以及 Dailymotion 直播服务器一起正常工作。

初始化

std::string rtmp_url = "rtmp://server/app/stream";
// add this if doing live streaming:
rtmp_url.append(" live=1");

RTMP * rtmp = RTMP_Alloc();
if (!rtmp) {
std::cerr << "Unable to create rtmp object\n";
return;
}

RTMP_Init(rtmp);
RTMP_LogSetLevel(RTMP_LOGINFO);
RTMP_LogSetOutput(stderr);
RTMP_SetupURL(rtmp, const_cast<char*>(rtmp_url.c_str())); // librtmp is a mess
RTMP_EnableWrite(rtmp);

奇怪的 const_cast是因为 librtmp 的设计很奇怪,并且使用了非常量 char *作为 URL,即使它可能不会被库实际修改。
此外,只要 RTMP 对象存在,缓冲区就会一直使用,因此在删除 RTMP 对象之前不得释放字符串。

连接
// connect to server
if (!RTMP_Connect(rtmp, NULL)) {
std::cerr << "Unable to connect to server\n";
RTMP_Free(rtmp);
return;
}
RTMP_Connect 的第二个参数是一个可选指针,指向要作为参数发送到连接的 RTMP 数据包,而不是 librtmp 发送的默认连接数据包。当连接到“普通”RTMP 服务器时,通常不应使用此选项。
// connect to stream (this will be the stream specified in the RTMP URL)
if (!RTMP_ConnectStream(rtmp, 0)) {
cerr << "Unable to connect to stream\n";
RTMP_Free(rtmp);
return;
}
RTMP_ConnectStream 的第二个参数是一个整数,表示播放视频时要查找的时间戳。发布时,使用 0是一个安全的选择。

发布数据包

本节假定使用 FLVMeta 项目中的 FLV 代码(参见 https://github.com/noirotm/flvmeta/blob/master/src/flv.h#L175)。
flv_stream * flvin = flv_open(input_file.c_str());
if (!flvin) {
std::cerr << "Unable to open " << input_file << '\n';
return;
}

首先,确保我们打开了一个真正的 FLV 文件是个好主意。
flv_header header;
int res = flv_read_header(flvin, &header);
if (res == FLV_ERROR_NO_FLV || res == FLV_ERROR_EOF) {
std::cerr << "Input file is not an FLV video\n";
flv_close(flvin);
return;
}

现在读取文件中的每个标签,并将它们发送到 RTMP 服务器。
// 10 MB copy buffer should be enough
#define BUFFER_SIZE 10000000
char buffer[BUFFER_SIZE];

flv_tag tag;
while (flv_read_tag(flvin, &tag) != FLV_ERROR_EOF) {
// copy tag header
flv_copy_tag(buffer, &tag, FLVSTREAMER_BUFFER_SIZE);

// copy tag body
size_t data_size = flv_read_tag_body(flvin, buffer + FLV_TAG_SIZE, BUFFER_SIZE - FLV_TAG_SIZE);

// copy previous tag size
uint32 pts;
flv_read_prev_tag_size(flvin, &pts);
flv_copy_prev_tag_size(
buffer + FLV_TAG_SIZE + flv_tag_get_body_length(tag),
pts,
BUFFER_SIZE - (FLV_TAG_SIZE + flv_tag_get_body_length(tag))
);

// write the packet
int size = FLV_TAG_SIZE + data_size + sizeof(uint32);
if (RTMP_Write(rtmp, buffer, size) <= 0) {
std::cerr << "Unable to write to server" << endl;
break;
}
}

各种 flv_*函数负责处理 FLV 格式的特殊性,例如字节顺序问题,以及最终的数据格式错误,因此如果您的程序与 GPL 许可证兼容,我建议您使用它们。
如果不是的话,使用标准I/O来遍历标签并不复杂,只要对FLV格式很好理解即可。

同样重要的是要注意不能发送 FLV 文件头。 librtmp 将检测任何发送 FLV header 的尝试并阻止它。

发布时读取传入的 RTMP 数据包不是强制性的,但如果您想正确处理协议(protocol),建议使用 @szatmary 在他的代码中使用的方法。

此处未处理的另一个重要方面是,在发布直播流时,必须实现某种形式的节流才能以视频的标称比特率发送数据,否则 RTMP 服务器将跳过数据包,视频播放将受到影响大大。
解决这个问题的一个常见方法是读取每个标签的时间戳,如果我们写得太快就休眠。

打扫干净
flv_close(flvin);
RTMP_Free(rtmp);
RTMP_Free函数将负责关闭流、连接并释放任何分配的内存。

关于c - librtmp 示例 c 编程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24749032/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com