我们在对接Linux平台RTMP|RTSP播放的时候,有遇到这样的技术需求,合作企业在做无人机视觉分析场景的时候,除了需要低延迟的拿到解码后的RGB|YUV数据,然后投递给他们自己的视觉算法处理模块外,还需要播放器支持SEI的回调,拿到无人机通过SEI扩展发送的一些重要信息,比如经纬度、高度或一些监测数据。
实际上,SEI数据回调这块,我们一直都有,我们还有自己的H.264 SEI扩展发送模块,如果需要回调H.264 SEI,只需要在StartPlay之前,调用下SetSEIDataCallBack即可。
具体代码示例如下:
cpp
player_api.SetSEIDataCallBack(handle, nullptr, on_player_sdk_sei_data);
on_player_sdk_sei_data设计如下,为了演示方便,我们仅把数据打印出来前面一些字节,实际上,SEI和RGB|YUV数据回调一样,我们也带了timestamp,方便数据帧和SEI对的起来:
cpp
extern "C" void on_player_sdk_sei_data(NT_HANDLE handle, NT_PVOID user_data,
NT_BYTE* data,
NT_UINT32 size,
NT_UINT64 timestamp,
NT_UINT64 reserve1,
NT_INT64 reserve2,
NT_PVOID reserve3
) {
if (!data || size < 1)
return;
std::ostringstream ss;
char buffer[8];
int print_len = size < 64 ? size : 64;
for (auto i = 0; i < print_len; ++i) {
sprintf(buffer, "%02x,", data[i]);
ss << buffer;
}
fprintf(stdout, "on_sdk_sei:size:%d, data:%s\n", size, ss.str().c_str());
fflush(stdout);
}
如果需要回调RGB数据,设置如下:
cpp
/*
* single_player_demo.cpp
* Created by daniusdk.com (C) All rights reserved.
*/
//player_api.SetVideoFrameCallBack(handle, NT_SP_E_VIDEO_FRAME_FROMAT_I420, nullptr, &NT_SDK_SDKVideoFrameCallBack);
player_api.SetVideoFrameCallBackV2(handle, 640, 360, 3, NT_SP_E_VIDEO_FRAME_FORMAT_RGB32, nullptr, &NT_SDK_SDKVideoFrameCallBack);
player_api.SetFastStartup(handle, 1);
player_api.SetLowLatencyMode(handle, 0);
if (NT_ERC_OK != player_api.StartPlay(handle))
{
player_api.Close(handle);
handle = nullptr;
player_api.UnInit();
fprintf(stderr, "player_api.StartPlay failed!\n");
XDestroyWindow(display, sub_wid);
XDestroyWindow(display, main_wid_);
XCloseDisplay(display);
return 0;
}
可以看到,除了正常的回调yuv或rgb的接口外,我们还有扩展的指定分辨率输出的回调接口设计,方便让开发者更方便的处理数据。
cpp
/*
* single_player_demo.cpp
* Created by daniusdk.com (C) All rights reserved.
*/
extern "C" void NT_SDK_SDKVideoFrameCallBack(NT_HANDLE handle, NT_PVOID user_data, NT_UINT32 status,
const NT_SP_VideoFrame* frame)
{
if (!frame)
return;
fprintf(stdout, "OnSDKVideoFrameCallBack handle:%p frame:%p, timestamp:%llu\n", handle, frame, frame->timestamp_);
#if NEED_SAVE_BITMAP
if (NT_SP_E_VIDEO_FRAME_FORMAT_RGB32 == frame->format_
|| NT_SP_E_VIDEO_FRAME_FORMAT_ARGB == frame->format_) {
struct timeval tv;
if (gettimeofday(&tv, nullptr) != 0) {
fprintf(stderr, "save bitmap file call gettimeofday failed");
return;
}
uint64_t local_time_us = tv.tv_sec*UINT64_C(1000000) + tv.tv_usec;
char file_name[128] = { 0 };
sprintf(file_name, "./outbitmaps/%llu.bmp", (unsigned long long)local_time_us);
if (!save_bitmap_file(frame->width_, frame->height_, frame->plane0_, frame->stride0_, frame->stride0_*frame->height_, file_name))
fprintf(stderr, "save bitmap file failed, name:%s", file_name);
else
g_bitmap_file_names_.emplace_back(file_name);
while (g_bitmap_file_names_.size() > 32) {
remove(g_bitmap_file_names_.front().c_str());
g_bitmap_file_names_.pop_front();
}
}
#endif // NEED_SAVE_BITMAP
}
以RTMP|RTSP播放器为例,Linux平台我们设计的功能如下:
- 音频:AAC/PCMA/PCMU/SPEEX;
- 视频:H.264;
- 播放协议:RTMP;
- 支持纯音频、纯视频、音视频播放;
- 支持多实例播放;
- [RTSP协议]支持RTSP TCP/UDP模式设置;
- [RTSP协议]支持RTSP TCP、UDP模式自动切换;
- [RTSP协议]支持RTSP超时时间设置,单位:秒;
- 支持buffer时间设置,单位:毫秒;
- 支持超低延迟模式;
- 断网自动重连,支持视频追赶;
- 支持视频view实时旋转(0° 90° 180° 270°);
- 支持视频view水平反转、垂直反转;
- 支持buffer状态等回调;
- 支持H.264 SEI扩展数据回调;
- 支持实时音量调节;
- 支持实时快照功能;
- 支持实时录像功能;
- 支持yuv或rgb数据回调;
- 支持unity接口;
- 支持x86_64|aarch64架构(需要glibc-2.21及以上版本的Linux系统, 需要libX11.so.6, 需安装 libstdc++.so.6.0.21、GLIBCXX_3.4.21、 CXXABI_1.3.9)。