tencent cloud

文档反馈

媒体传输 SDK(TMIO SDK)

最后更新时间:2023-11-24 15:01:48

    简单介绍

    TMIO SDK(Tencent Media IO SDK)是针对当前日益丰富的流媒体传输协议,对主流协议进行整合优化和扩展,为用户可以开发出稳定可用的媒体应用提供服务方便,摆脱繁重的多种协议的开发调试工作。 TMIO SDK 当前已对 SRT、QUIC 等主流媒体协议 进行了优化扩展,同时新增自研传输控制协议 ETC(全称:Elastic Transmission Control),后续将会持续增加其他主流协议的优化扩展。

    能力优势

    多平台支持:包括 Android、iOS、Linux、Mac 和 windows。
    灵活的选择接入方式
    零代码入侵的代理模式, 请参见 接入简介
    依托简单的 API 设计,可实现快速接入替换原有传输协议,请参见 接入简介
    API 接口设计简单,兼容性灵活性强
    提供简单易用的接口设计。
    可根据业务需求场景选择合适的模式和策略。
    可扩展其他协议的定制优化。
    整合多种传输协议扩展优化
    SRT、QUIC 等新一代主流传输协议和自研传输控制协议 ETC 支持
    可适用于多种业务场景的不同需求选择
    基于 UDP 的低延时、安全可靠的传输设计
    多链路加速优势,保证传输更稳定、流畅

    效果展示(以TMIO SRT 为例)

    TMIO 支持 SRT 协议,可用于弱网、远距离传输场景中,提高上行稳定性和下行流畅度。 如下测试场景中,RTMP推流在10%丢包率时已播放卡顿,SRT推流在10%甚至30%丢包率时仍能保持稳定和低延迟。
    
    

    功能介绍

    基于 SRT 的流媒体传输功能
    抗随机丢包能力强
    基于 ARQ 及超时策略的重传机制。
    基于 UDT 的低延时、安全可靠的传输设计
    多链路传输功能,在原基础上新增扩展链路聚合功能: 多链路传输功能可配置多条链路来实现数据的传输,特别是在当前4G/5G网络普遍的情况下,移动终端设备既可以使用 Wi-Fi,又可以使用数据网络来进行数据的传输,这样即使单一网络突然中断,只要有一条链路可用就可以保证链路的稳定性。
    功能模式
    说明
    广播模式
    可配置多个链接实现冗余发送,保证数据的完整性和连接可靠性。
    主备模式
    基于链路稳定性和可靠性做参考,同一时间只有一路链接的活跃,实时选择更优质的链路来实现数据传输。既保证了链路的稳定性和可靠性,又能够减少冗余数据带来的带宽消耗。
    聚合模式
    对于高码率、带宽要求的场景,当单一链路带宽无法满足其需求时,聚合模式可将数据通过多链路来拆分发送,同时在接收侧重组,以达到增大带宽的目的。
    基于 QUIC 的流媒体传输功能
    自适应拥塞控制算法
    支持网络连接迁移,平滑无感知
    支持下一代HTTP3基础传输协议
    带宽受限、抖动环境下,发送冗余数据更低,更加节约带宽成本,优势明显
    自研传输控制协议ETC
    纯自研,轻量级,跨平台。
    支持IoT设备,适合端到端通信。
    快启动、低时延且高带宽利用率。
    迅速、准确地感知链路状态变化,并及时调整到最佳传输策略。
    与主流传输协议并存时,能更公平、更稳定地利用带宽。

    接入方法

    以 RTMP over SRT 协议为例:

    选择代理模式

    Tmio Proxy 模式接入方式

    
    
    

    操作步骤

    1. 创建 Tmio Proxy
    std::unique_ptr<tmio::TmioProxy> proxy_ = tmio::TmioProxy::createUnique();
    2. 设置监听
    void setListener(TmioProxyListener *listener);
    TmioProxyListener 监听接口如下:
    Tmio 配置回调
    TmioProxy 启动回调
    错误信息回调
    用户可在此回调内对 Tmio 做参数配置,简单配置可使用 tmio-preset.h 提供的辅助方法
    /*
    void onTmioConfig(Tmio *tmio);
    */
    void onTmioConfig(tmio::Tmio *tmio) override {
    auto protocol = tmio->getProtocol();
    if (protocol == tmio::Protocol::SRT) {
    tmio::SrtPreset::rtmp(tmio);
    } else if (protocol == tmio::Protocol::RIST) {
    tmio->setIntOption(tmio::base_options::RECV_SEND_FLAGS,
    tmio::base_options::FLAG_SEND);
    }
    }
    /*
    void onStart(const char *local_addr, uint16_t local_port);
    */
    void onStart(const char *addr, uint16_t port) override {
    LOGFI("ip %s, port %" PRIu16, addr, port);
    }
    收到此回调代表连接远程服务器成功,并且 TCP 本地端口绑定成功,可以启动推流。
    /*
    void onError(ErrorType type, const std::error_code &err);
    */
    void onError(tmio::TmioProxyListener::ErrorType type,
    const std::error_code &err) override {
    LOGFE("error type %s, %s, %d", tmio::TmioProxyListener::errorType(type),
    err.message().c_str(), err.value());
    }
    用户可通过 ErrorType 来区分是本地 IO 错误还是远程 IO 错误。本地 IO 通常是 RTMP 推流主动触发的,如结束推流,一般可忽略,而远程 IO 错误一般不可忽略。
    3. 启动代理
    std::error_code start(const std::string &local_url, const std::string &remote_url, void * config=nullptr)
    接口参数
    参数
    说明
    local_url
    只支持 TCP Scheme,格式为 tcp://${ip}:${port}。port 可以为0,为0时会绑定到随机端口,然后通过 onStart() 回调把绑定成功后的端口号返回给应用。使用0端口可以避免端口被占用、无权限等导致的绑定失败问题。
    remote_url
    远程服务器 URL。
    config
    配置参数,此参数在 SRT bonding 功能和 QUIC H3 协议启用时使用,具体定义请依据 tmio.h 下 TmioFeatureConfig 结构体定义。
    单链路(代码示例)
    proxy_->start(local_url, remote_url, NULL);
    bonding 多链路(代码示例)
    tmio::TmioFeatureConfig option;
    option_.protocol = tmio::Protocol::SRT;
    option_.trans_mode = static_cast<int>(tmio::SrtTransMode::SRT_TRANS_BACKUP);
    /*-----------------------------------------------------------*/
    {
    //根据当前需要建立的链路数可添加多个链路
    option_.addAvailableNet(net_name, local_addr, remote_url, 0, weight, -1);
    }
    /*-----------------------------------------------------------*/
    
    proxy_->start(local_url, remote_url, &option_);
    
    4. 停止
    /*
    void stop();
    */
    proxy_.stop();

    内部集成

    Tmio SDK 内部集成接入方式

    
    
    

    接入流程

    1. 创建 Tmio&配置参数(代码示例):
    tmio_ = tmio::TmioFactory::createUnique(tmio::Protocol::SRT);
    tmio::SrtPreset::mpegTsLossless(tmio_.get());
    tmio_->setIntOption(tmio::srt_options::CONNECT_TIMEOUT, 4000);
    tmio_->setBoolOption(tmio::base_options::THREAD_SAFE_CHECK, true);
    创建 Tmio:通过 TmioFactory 来创建。
    参数配置:根据不同参数选择不同的接口来实现配置:
    参数名:请参见 tmio-option.h
    简单配置:请参见tmio-preset.h
    //根据不同参数属性选择合适的配置
    bool setBoolOption(const std::string &optname, bool value);
    bool setIntOption(const std::string &optname, int64_t value);
    bool setDoubleOption(const std::string &optname, double value);
    bool setStrOption(const std::string &optname, const std::string &value);
    ...
    2. 开始连接(代码示例):
    /**
    * open the stream specified by url
    *
    * @param config protocol dependent
    */
    virtual std::error_code open(const std::string &url,
    void *config = nullptr) = 0;
    单链路(config 可为 NULL)
    //默认单链路
    auto err = tmio->open(TMIO_SRT_URL);
    if (err) {
    LOGE("open failed, %d, %s", err.value(), err.message().c_str());
    }
    多链路 bonding(当前仅支持 SRT 协议)
    config 设置时 SRT bonding 配置参数可参见 tmio.h 文件结构中 TmioFeatureConfig 定义。
    tmio::TmioFeatureConfig option_;
    option_.protocol = tmio::Protocol::SRT;
    option_.trans_mode = static_cast<int>(tmio::SrtTransMode::SRT_TRANS_BACKUP);
    option_.addAvailableNet(net_name, local_addr, remote_url, 0, weight, -1);
    //bonding 多链路
    auto err = tmio_->open(TMIO_SRT_URL, &option_);
    if (err) {
    LOGE("open failed, %d, %s", err.value(), err.message().c_str());
    }
    多链路 bonding open 接口还可以用来对 group 组添加新的链路用于传输。
    3. 发送数据
    int ret = tmio_->send(buf.data(), datalen, err);
    if (ret < 0) {
    LOGE("send failed, %d, %s", err.value(), err.message().c_str());
    break;
    }
    4. 接收数据
    如果是需要交互的协议(如 RTMP), 此时需要启用接收接口来读取数据完成协议交互,这里提供两个接口调用:
    /**
    * receive data
    *
    * @param err return error details
    * @return number of bytes which were received, or < 0 to indicate error
    */
    virtual int recv(uint8_t *buf, int len, std::error_code &err) = 0;
    
    using RecvCallback = std::function<bool(const uint8_t *buf, int len, const std::error_code &err)>;
    /**
    * receive data in event loop
    *
    * recvLoop() block current thread, receive data in a loop and pass the data to recvCallback
    * @param recvCallback return true to continue the receive loop, false for break
    */
    virtual void recvLoop(const RecvCallback &recvCallback) = 0;
    上层应用循环读取
    while (true) {
    ret = tmio_->recv(buf.data(), buf.size(), err);
    if (ret < 0) {
    LOGE("recv error: %d, %s", err.value(), err.message().c_str());
    break;
    }
    ...
    }
    回调读取
    FILE *file = fopen(output_path, "w");
    tmio_->recvLoop([file](const uint8_t *buf, int len,
    const std::error_code &err) {
    if (len < 0) {
    fwrite(buf, 1, len, file);
    } else if (len < 0) {
    LOGE("recv error: %d, %s", err.value(), err.message().c_str());
    }
    return true;
    });
    5. 关闭 Tmio
    tmio_->close();
    6. 其他: 获取当前链路状态(应用可根据此状态信息调整推流策略)。
    tmio::PerfStats stats_;
    tmio_->control(tmio::ControlCmd::GET_STATS, &stats_);

    最新 API 接口及 Demo 详细说明

    接入 TMIO SDK,可参考最新 API 接口和 Demo 说明, 详情请参见 TMIO 接入详情

    常见问题解答

    是不是所有的设备都可以使用 SRT bonding 多链路功能?

    多链路功能的前提是设备有多个可用的网络接口,同时针对 Android 设备其系统需要在6.0(api level >=23)以上才可使用。

    Android 手机在已连接 Wi-Fi 的情况下,如何启用4G/5G数据网络?

    Android 手机在已连接 Wi-Fi 的情况下,是无法直接使用4G/5G网络来实现数据传输的,此时如果想启用数据网络则需要申请数据网络权限,代码如下:
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest request = new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .build();
    
    ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback(){
    @Override
    public void onAvailable(@NonNull Network network) {
    Log.d(TAG, "移动数据网络通道已开启.");
    super.onAvailable(network);
    }
    }
    
    联系我们

    联系我们,为您的业务提供专属服务。

    技术支持

    如果你想寻求进一步的帮助,通过工单与我们进行联络。我们提供7x24的工单服务。

    7x24 电话支持