基于Linux平台的多实例RTSP|RTMP直播播放器深度解析与技术实现

​一、引言

在Linux平台上实现一个高性能、高并发的多实例播放器,是许多流媒体应用的核心需求。本文将结合大牛直播SDK的Linux平台RTSP/RTMP播放器功能,深入解析其实现原理、关键技术点以及优化策略。通过对代码的详细分析和实际应用的结合,帮助开发者更好地理解和应用该技术。

二、项目概述

本文基于以下代码实现了一个多实例播放器:

  • multi_player_demo.cpp:主程序,负责初始化SDK、创建播放器实例、管理窗口布局以及事件处理。

  • nt_player_sdk_wrapper.cppnt_player_sdk_wrapper.h:封装了播放器SDK的核心功能,提供了简洁的接口供主程序调用。

  • nt_sdk_handle_wrapper.cppnt_sdk_handle_wrapper.h:封装了SDK的句柄管理功能,负责处理SDK的事件回调。

三、技术解析

1. SDK初始化与日志管理

multi_player_demo.cpp中,通过调用NT_SDKLogInit()函数初始化日志系统,设置日志级别为SL_INFO_LEVEL,并将日志输出路径设置为当前目录。这为后续的调试和问题排查提供了便利。

scss 复制代码
void NT_SDKLogInit()
{
    SmartLogAPI log_api;
    memset(&log_api, 0, sizeof(log_api));
    GetSmartLogAPI(&log_api);

    log_api.SetLevel(SL_INFO_LEVEL);
    log_api.SetPath((NT_PVOID)"./");
}

2. 播放器SDK初始化

通过调用NT_PlayerSDKInit()函数初始化播放器SDK。该函数首先获取SDK的API接口,然后调用Init()函数进行初始化。如果初始化失败,会输出错误信息并返回false

c 复制代码
bool NT_PlayerSDKInit(SmartPlayerSDKAPI& player_api)
{
    memset(&player_api, 0, sizeof(player_api));
    GetSmartPlayerSDKAPI(&player_api);

    auto ret = player_api.Init(0, nullptr);
    if (NT_ERC_OK != ret)
    {
        fprintf(stderr, "player_api.Init failed!\n");
        return false;
    }
    else
    {
        fprintf(stdout, "player_api.Init ok!\n");
    }

    return true;
}

3. 窗口布局管理

multi_player_demo.cpp中,通过调用SubWindowsLayout()函数计算子窗口的布局。该函数根据主窗口的宽高、边框宽度以及播放器实例的数量,动态计算每个子窗口的位置和大小。布局策略为将主窗口划分为多个子窗口,每个子窗口的大小和位置根据实例数量动态调整。

ini 复制代码
void SubWindowsLayout(int w, int h, int border, int count, std::vector<NT_LayoutRect>& rects)
{
    rects.clear();

    if (w < 20 || h < 20)
    {
        NT_LayoutRect c;
        c.x_ = 0;
        c.y_ = 0;
        c.w_ = 2;
        c.h_ = 2;

        for (auto i = 0; i < count; ++i)
        {
            rects.push_back(c);
        }

        return;
    }

    if (1 == count)
    {
        NT_LayoutRect c1;
        c1.x_ = 0;
        c1.y_ = 0;
        c1.w_ = w - 2 * border;
        c1.h_ = h - 2 * border;

        rects.push_back(c1);
        return;
    }

    auto sub_h = h / 2;
    auto sub_w = w / 2;
    auto cur_y = 0;
    auto t_h = 0;

    auto rows = (count + 1) / 2;

    for (auto i = 0; i < rows; ++i)
    {
        NT_LayoutRect c1, c2;

        c1.x_ = 0;
        c1.y_ = cur_y;
        c1.w_ = sub_w;
        c1.h_ = sub_h;

        c2.x_ = c1.w_;
        c2.y_ = cur_y;
        c2.w_ = w - c1.w_;
        c2.h_ = sub_h;

        if (i == (rows - 1))
        {
            c1.h_ = h - t_h;
            c2.h_ = h - t_h;
        }

        cur_y += c1.h_;
        t_h += c1.h_;

        c1.w_ -= 2 * border;
        c1.h_ -= 2 * border;
        c2.w_ -= 2 * border;
        c2.h_ -= 2 * border;

        rects.push_back(c1);
        rects.push_back(c2);
    }

    if (static_cast<int>(rects.size()) > count)
    {
        rects.pop_back();
    }
}

4. 播放器实例管理

multi_player_demo.cpp中,通过创建NT_PlayerSDKWrapper实例来管理每个播放器。每个实例对应一个RTSP或RTMP流地址。通过调用Start()函数启动播放器,并设置相关参数,如缓冲区大小、是否静音、渲染模式等。

scss 复制代码
for (auto url : players_url_)
{
    auto i = std::make_shared<NT_PlayerSDKWrapper>(&player_api);
    i->SetDisplay(display);
    i->SetScreen(screen);
    i->SetURL(url);
    players.push_back(i);

    if (players.size() > 3)
        break;
}

5. 事件处理机制

通过MY_X11_Pending()函数检测是否有待处理的X11事件。如果有事件,调用XNextEvent()获取事件并处理。主要处理的事件包括窗口大小调整(ConfigureNotify)和按键事件(KeyPress)。在按键事件中,检测到ESC键按下时,停止所有播放器实例并退出程序。

scss 复制代码
while (MY_X11_Pending(display, 10))
{
    XEvent xev;
    memset(&xev, 0, sizeof(xev));
    XNextEvent(display, &xev);

    if (xev.type == ConfigureNotify)
    {
        if (xev.xconfigure.window == main_wid)
        {
            if (xev.xconfigure.width != main_w || xev.xconfigure.height != main_h)
            {
                main_w = xev.xconfigure.width;
                main_h = xev.xconfigure.height;

                SubWindowsLayout(main_w, main_h, border_w, static_cast<int>(players.size()), layout_rects);

                for (auto i = 0; i < static_cast<int>(players.size()); ++i)
                {
                    if (players[i]->GetWindow())
                    {
                        XMoveResizeWindow(display, players[i]->GetWindow(), layout_rects[i].x_, layout_rects[i].y_, layout_rects[i].w_, layout_rects[i].h_);
                    }
                }
            }
        }
        else
        {
            for (const auto& i : players)
            {
                assert(i);
                if (i->GetWindow() && i->GetWindow() == xev.xconfigure.window)
                {
                    i->OnWindowSize(xev.xconfigure.width, xev.xconfigure.height);
                }
            }
        }
    }
    else if (xev.type == KeyPress)
    {
        if (xev.xkey.keycode == XKeysymToKeycode(display, XK_Escape))
        {
            fprintf(stdout, "ESC Key Press\n");

            for (const auto& i : players)
            {
                i->Stop();

                if (i->GetWindow())
                {
                    XDestroyWindow(display, i->GetWindow());
                    i->SetWindow(None);
                }
            }

            players.clear();

            XDestroyWindow(display, main_wid);
            XCloseDisplay(display);

            player_api.UnInit();

            fprintf(stdout, "Close Players....\n");
            return 0;
        }
    }
}

6. 功能说明

如不单独说明,系Windows、Linux(含x86_64|aarch64)、Android、iOS全平台支持。

  • 支持播放协议\]高稳定、超低延迟(毫秒级,行业内几无效果接近的播放端)、业内领先的RTMP直播播放器SDK;

  • 事件回调\]支持网络状态、buffer状态等回调;

  • 音频格式\]支持AAC/PCMA/PCMU/Speex;

  • H.264硬解码\]Windows/Android/iOS支持特定机型H.264硬解;

  • H.264/H.265硬解码\]Android支持设置Surface模式硬解和普通模式硬解码;

  • 首屏秒开\]支持首屏秒开模式;

  • 复杂网络处理\]支持断网重连等各种网络环境自动适配;

  • 音视频多种render机制\]Android平台,视频:SurfaceView/GLSurfaceView,音频:AudioTrack/OpenSL ES;

  • 实时音量调节\]支持播放过程中实时调节音量;

  • 只播关键帧\]Windows平台支持实时设置是否只播放关键帧;

  • 渲染镜像\]支持水平反转、垂直反转模式设置;

  • 实时下载速度更新\]支持当前下载速度实时回调(支持设置回调时间间隔);

  • 解码前视频数据回调\]支持H.264/H.265数据回调;

  • 解码后视频数据缩放回调\]Windows平台支持指定回调图像大小的接口(可以对原视图像缩放后再回调到上层);

  • 音视频自适应\]支持播放过程中,音视频信息改变后自适应;

  • Linux平台支持x64_64架构、aarch64架构(需要glibc-2.21及以上版本的Linux系统, 需要libX11.so.6, 需要GLib--2.0, 需安装 libstdc++.so.6.0.21、GLIBCXX_3.4.21、 CXXABI_1.3.9);

四、总结

本文详细解析了基于Linux平台的多实例播放器的实现原理和关键技术点,并提出了优化和改进的方向。通过结合大牛直播SDK的功能,开发者可以快速实现一个高性能、高并发的多实例播放器,满足各种流媒体应用的需求。希望本文能够为开发者提供有价值的参考和启发。

相关推荐
chenchao_shenzhen3 天前
RK3568嵌入式音视频硬件编解码4K 60帧 rkmpp FFmpeg7.1 音视频开发
ffmpeg·音视频·rk3588·音视频开发·嵌入式开发·瑞芯微rk3568·硬件编解码
码流怪侠5 天前
Google SoundStream音频编解码器技术解析
深度学习·音视频开发
字节跳动视频云技术团队5 天前
基于 DiT 大模型与字体级分割的视频字幕无痕擦除方案,助力短剧出海
aigc·音视频开发·视频编码
音视频牛哥7 天前
跨平台轻量级RTSP服务模块技术详解与内网低延迟直播实践
音视频开发·视频编码·直播
aqi008 天前
FFmpeg开发笔记(八十)使用百变魔音AiSound实现变声特效
android·ffmpeg·音视频·直播·流媒体
aqi009 天前
FFmpeg开发笔记(七十九)专注于视频弹幕功能的国产弹弹播放器
android·ffmpeg·音视频·直播·流媒体
音视频牛哥11 天前
SmartMediaKit 模块化音视频框架实战指南:场景链路 + 能力矩阵全解析
音视频开发·视频编码·直播
子龙_12 天前
JS解析wav音频数据并使用wasm加速
前端·javascript·音视频开发
泉城老铁13 天前
Spring Boot + Vue + ZLMediaKit 实现 RTSP 拉流播放的完整方案
java·vue.js·音视频开发