mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-06 03:28:09 +08:00
Merge branch 'master' of https://github.com/ZLMediaKit/ZLMediaKit into feature/transcode2
# Conflicts: # conf/config.ini # src/Codec/Transcode.cpp # src/Common/MediaSource.h # src/Common/MultiMediaSourceMuxer.cpp # src/Common/MultiMediaSourceMuxer.h # src/Common/macros.h # webrtc/WebRtcPusher.cpp # webrtc/WebRtcTransport.cpp # webrtc/WebRtcTransport.h
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2016-2022 The ZLMediaKit project authors. All Rights Reserved.
|
||||
# Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -77,6 +77,31 @@ install(TARGETS mk_api
|
||||
LIBRARY DESTINATION ${INSTALL_PATH_LIB}
|
||||
RUNTIME DESTINATION ${INSTALL_PATH_RUNTIME})
|
||||
|
||||
if(MSVC)
|
||||
set(RESOURCE_FILE "${CMAKE_SOURCE_DIR}/resource.rc")
|
||||
set_source_files_properties(${RESOURCE_FILE} PROPERTIES LANGUAGE RC)
|
||||
target_sources(mk_api PRIVATE ${RESOURCE_FILE})
|
||||
endif()
|
||||
|
||||
#relase 类型时额外输出debug调试信息
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
|
||||
if(UNIX AND ENABLE_OBJCOPY)
|
||||
if("${CMAKE_BUILD_TYPE_LOWER}" STREQUAL "release")
|
||||
find_program(OBJCOPY_FOUND objcopy)
|
||||
if (OBJCOPY_FOUND)
|
||||
add_custom_command(TARGET mk_api
|
||||
POST_BUILD
|
||||
COMMAND objcopy --only-keep-debug ${EXECUTABLE_OUTPUT_PATH}/libmk_api.so ${EXECUTABLE_OUTPUT_PATH}/libmk_api.so.debug
|
||||
COMMAND objcopy --strip-all ${EXECUTABLE_OUTPUT_PATH}/libmk_api.so
|
||||
COMMAND objcopy --add-gnu-debuglink=${EXECUTABLE_OUTPUT_PATH}/libmk_api.so.debug ${EXECUTABLE_OUTPUT_PATH}/libmk_api.so
|
||||
)
|
||||
install(FILES ${EXECUTABLE_OUTPUT_PATH}/libmk_api.so.debug DESTINATION ${INSTALL_PATH_RUNTIME})
|
||||
else()
|
||||
message(STATUS "not found objcopy, generate libmk_api.so.debug skip")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# IOS 跳过测试代码
|
||||
if(IOS)
|
||||
return()
|
||||
|
||||
@@ -259,31 +259,24 @@ API_EXPORT uint16_t API_CALL mk_rtp_server_start(uint16_t port);
|
||||
*/
|
||||
API_EXPORT uint16_t API_CALL mk_rtc_server_start(uint16_t port);
|
||||
|
||||
// 获取webrtc answer sdp回调函数 [AUTO-TRANSLATED:10c93fa9]
|
||||
// Get webrtc answer sdp callback function
|
||||
typedef void(API_CALL *on_mk_webrtc_get_answer_sdp)(void *user_data, const char *answer, const char *err);
|
||||
|
||||
/**
|
||||
* webrtc交换sdp,根据offer sdp生成answer sdp
|
||||
* @param user_data 回调用户指针
|
||||
* @param cb 回调函数
|
||||
* @param type webrtc插件类型,支持echo,play,push
|
||||
* @param offer webrtc offer sdp
|
||||
* @param url rtc url, 例如 rtc://__defaultVhost/app/stream?key1=val1&key2=val2
|
||||
* webrtc exchange sdp, generate answer sdp based on offer sdp
|
||||
* @param user_data Callback user pointer
|
||||
* @param cb Callback function
|
||||
* @param type webrtc plugin type, supports echo, play, push
|
||||
* @param offer webrtc offer sdp
|
||||
* @param url rtc url, for example rtc://__defaultVhost/app/stream?key1=val1&key2=val2
|
||||
|
||||
* [AUTO-TRANSLATED:ea79659b]
|
||||
* 创建websocket[s]信令服务器
|
||||
* @param port websocket监听端口
|
||||
* @param ssl 是否为ssl类型服务器
|
||||
* @return 0:失败,非0:端口号
|
||||
*
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp(void *user_data, on_mk_webrtc_get_answer_sdp cb, const char *type,
|
||||
const char *offer, const char *url);
|
||||
API_EXPORT uint16_t API_CALL mk_signaling_server_start(uint16_t port, int ssl);
|
||||
|
||||
/**
|
||||
* 创建webrtc-ice[s]服务器
|
||||
* @param port websocket监听端口
|
||||
* @return 0:失败,非0:端口号
|
||||
*
|
||||
*/
|
||||
API_EXPORT uint16_t API_CALL mk_ice_server_start(uint16_t port);
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp2(void *user_data, on_user_data_free user_data_free, on_mk_webrtc_get_answer_sdp cb, const char *type,
|
||||
const char *offer, const char *url);
|
||||
|
||||
/**
|
||||
* 创建srt服务器
|
||||
|
||||
@@ -193,6 +193,8 @@ API_EXPORT uint64_t API_CALL mk_media_source_get_alive_second(const mk_media_sou
|
||||
API_EXPORT int API_CALL mk_media_source_close(const mk_media_source ctx,int force);
|
||||
//MediaSource::seekTo()
|
||||
API_EXPORT int API_CALL mk_media_source_seek_to(const mk_media_source ctx,uint32_t stamp);
|
||||
// MediaSource::setSpeed()
|
||||
API_EXPORT void API_CALL mk_media_source_set_speed(const mk_media_source ctx, float speed);
|
||||
|
||||
/**
|
||||
* rtp推流成功与否的回调(第一次成功后,后面将一直重试)
|
||||
|
||||
@@ -343,6 +343,40 @@ API_EXPORT void API_CALL mk_mpeg_muxer_init_complete(mk_mpeg_muxer ctx);
|
||||
*/
|
||||
API_EXPORT int API_CALL mk_mpeg_muxer_input_frame(mk_mpeg_muxer ctx, mk_frame frame);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if defined(ENABLE_RTPPROXY)
|
||||
|
||||
typedef struct mk_ps_decoder_t *mk_ps_decoder;
|
||||
|
||||
typedef void (API_CALL *on_mk_ps_decoder_stream)(void *user_data, int stream, int codecid, const void *ext, size_t ext_len, int finish);
|
||||
typedef void(API_CALL *on_mk_ps_decoder_frame)(void *user_data, int stream, int codecid, int flags, int64_t pts, int64_t dts, const void *data, size_t bytes);
|
||||
|
||||
/**
|
||||
* 创建一个ps解析器
|
||||
* @param scb stream 回调; 可选, 如果明确知道数据类型也许不需要此回调创建track?
|
||||
* @param dcb 数据回调;必填
|
||||
* @param user_data 用户自定义数据
|
||||
* @return
|
||||
*/
|
||||
API_EXPORT mk_ps_decoder API_CALL mk_ps_decoder_create(on_mk_ps_decoder_stream scb, on_mk_ps_decoder_frame dcb, void * user_data);
|
||||
|
||||
/**
|
||||
* 释放ps解析器
|
||||
* @param ctx
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_ps_decoder_release(mk_ps_decoder ctx);
|
||||
|
||||
/**
|
||||
* 输入ps数据
|
||||
* @param ctx ps解析器指针
|
||||
* @param data ps数据指针
|
||||
* @param bytes 数据长度
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_ps_decoder_input(mk_ps_decoder ctx, const char * data, size_t bytes);
|
||||
|
||||
|
||||
# endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -27,5 +27,6 @@
|
||||
#include "mk_frame.h"
|
||||
#include "mk_track.h"
|
||||
#include "mk_transcode.h"
|
||||
#include "mk_webrtc.h"
|
||||
|
||||
#endif /* MK_API_H_ */
|
||||
|
||||
@@ -125,6 +125,21 @@ API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const cha
|
||||
*/
|
||||
API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char *app, const char *stream);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 开始事件视频录制
|
||||
* @param vhost 虚拟主机
|
||||
* @param app 应用名
|
||||
* @param stream 流id
|
||||
* @param path 录像文件保存相对路径,包括名称
|
||||
* @param back_ms 回溯录制时长
|
||||
* @param forward_ms 后续录制时长
|
||||
* @return 1:成功,0:失败
|
||||
* */
|
||||
API_EXPORT int API_CALL mk_recorder_start_task(const char *vhost, const char *app, const char *stream, const char *path, uint32_t back_ms, uint32_t forward_ms);
|
||||
|
||||
|
||||
/**
|
||||
* 加载mp4列表
|
||||
* @param vhost 虚拟主机
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef struct mk_rtp_server_t *mk_rtp_server;
|
||||
* @param port 监听端口,0则为随机
|
||||
* @param tcp_mode tcp模式(0: 不监听端口 1: 监听端口 2: 主动连接到服务端)
|
||||
* @param stream_id 该端口绑定的流id
|
||||
* @param multiple 多路复用RTP服务器 1: 开启 0: 不开启
|
||||
* @return
|
||||
* Create GB28181 RTP server
|
||||
* @param port Listening port, 0 for random
|
||||
@@ -32,6 +33,7 @@ typedef struct mk_rtp_server_t *mk_rtp_server;
|
||||
*/
|
||||
API_EXPORT mk_rtp_server API_CALL mk_rtp_server_create(uint16_t port, int tcp_mode, const char *stream_id);
|
||||
API_EXPORT mk_rtp_server API_CALL mk_rtp_server_create2(uint16_t port, int tcp_mode, const char *vhost, const char *app, const char *stream_id);
|
||||
API_EXPORT mk_rtp_server API_CALL mk_rtp_server_create3(uint16_t port, int tcp_mode, const char *vhost, const char *app, const char *stream_id, int multiplex);
|
||||
|
||||
/**
|
||||
* TCP 主动模式时连接到服务器是否成功的回调
|
||||
@@ -110,6 +112,53 @@ typedef void(API_CALL *on_mk_rtp_server_detach)(void *user_data);
|
||||
API_EXPORT void API_CALL mk_rtp_server_set_on_detach(mk_rtp_server ctx, on_mk_rtp_server_detach cb, void *user_data);
|
||||
API_EXPORT void API_CALL mk_rtp_server_set_on_detach2(mk_rtp_server ctx, on_mk_rtp_server_detach cb, void *user_data, on_user_data_free user_data_free);
|
||||
|
||||
/**
|
||||
* 更新RTP服务器过滤SSRC
|
||||
* @param ctx 服务器对象
|
||||
* @param ssrc 十进制ssrc
|
||||
*
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_rtp_server_update_ssrc(mk_rtp_server ctx, uint32_t ssrc);
|
||||
|
||||
|
||||
/**
|
||||
* rtp信息获取回调
|
||||
* @param exist 存在rtp信息 0: 不存在 1: 存在
|
||||
* @param peer_ip 连接ip
|
||||
* @param peer_port 连接端口
|
||||
* @param local_ip 本地ip
|
||||
* @param local_port 本地端口
|
||||
* @param identifier 身份信息
|
||||
*
|
||||
*/
|
||||
typedef void(API_CALL *on_mk_rtp_get_info)(int exist, const char *peer_ip, uint16_t peer_port, const char *local_ip, uint16_t local_port, const char *identifier);
|
||||
|
||||
/**
|
||||
* 获取rtp推流信息
|
||||
* @param app 应用名
|
||||
* @param stream 流id
|
||||
* @param cb rtp信息获取回调
|
||||
*
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_rtp_get_info(const char *app, const char *stream, on_mk_rtp_get_info cb);
|
||||
|
||||
|
||||
/**
|
||||
* 暂停RTP超时检查
|
||||
* @param app 应用名
|
||||
* @param stream 流id
|
||||
*
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_rtp_pause_check(const char *app, const char *stream);
|
||||
|
||||
/**
|
||||
* 恢复RTP超时检查
|
||||
* @param app 应用名
|
||||
* @param stream 流id
|
||||
*
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_rtp_resume_check(const char *app, const char *stream);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
111
api/include/mk_webrtc.h
Normal file
111
api/include/mk_webrtc.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
|
||||
*
|
||||
* Use of this source code is governed by MIT-like license that can be found in the
|
||||
* LICENSE file in the root of the source tree. All contributing project authors
|
||||
* may be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MK_WEBRTC_H
|
||||
#define MK_WEBRTC_H
|
||||
#include "mk_common.h"
|
||||
#include "mk_proxyplayer.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// 获取webrtc answer sdp回调函数 [AUTO-TRANSLATED:10c93fa9]
|
||||
// Get webrtc answer sdp callback function
|
||||
typedef void(API_CALL *on_mk_webrtc_get_answer_sdp)(void *user_data, const char *answer, const char *err);
|
||||
|
||||
// 获取webrtc proxy player信息回调函数
|
||||
typedef void(API_CALL *on_mk_webrtc_get_proxy_player_info_cb)(const char *info_json, const char *err);
|
||||
|
||||
//WebRTC-注册到信令服务器、WebRTC-从信令服务器注销回调函数
|
||||
typedef void(API_CALL *on_mk_webrtc_room_keeper_info_cb)(void *user_data, const char *room_key, const char *err);
|
||||
|
||||
//获取WebRTC-Peer查看注册信息、WebRTC-信令服务器查看注册信息回调函数
|
||||
typedef void(API_CALL *on_mk_webrtc_room_keeper_data_cb)(const char *data);
|
||||
|
||||
|
||||
/**
|
||||
* webrtc交换sdp,根据offer sdp生成answer sdp
|
||||
* @param user_data 回调用户指针
|
||||
* @param cb 回调函数
|
||||
* @param type webrtc插件类型,支持echo,play,push
|
||||
* @param offer webrtc offer sdp
|
||||
* @param url rtc url, 例如 rtc://__defaultVhost/app/stream?key1=val1&key2=val2
|
||||
* webrtc exchange sdp, generate answer sdp based on offer sdp
|
||||
* @param user_data Callback user pointer
|
||||
* @param cb Callback function
|
||||
* @param type webrtc plugin type, supports echo, play, push
|
||||
* @param offer webrtc offer sdp
|
||||
* @param url rtc url, for example rtc://__defaultVhost/app/stream?key1=val1&key2=val2
|
||||
|
||||
* [AUTO-TRANSLATED:ea79659b]
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp(void *user_data, on_mk_webrtc_get_answer_sdp cb, const char *type, const char *offer, const char *url);
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp2(
|
||||
void *user_data, on_user_data_free user_data_free, on_mk_webrtc_get_answer_sdp cb, const char *type, const char *offer, const char *url);
|
||||
|
||||
/**
|
||||
* 获取webrtc proxy player信息
|
||||
* @param mk_proxy_player 代理
|
||||
* @param cb 回调函数
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_webrtc_get_proxy_player_info(mk_proxy_player ctx, on_mk_webrtc_get_proxy_player_info_cb cb);
|
||||
|
||||
|
||||
/**
|
||||
* WebRTC-注册到信令服务器
|
||||
* @param server_host 信令服务器host
|
||||
* @param server_port 信令服务器port
|
||||
* @param room_id 房间id
|
||||
* @param ssl 是否启用ssl
|
||||
* @param cb 回调函数
|
||||
* @param user_data 用户数据
|
||||
*/
|
||||
API_EXPORT void API_CALL
|
||||
mk_webrtc_add_room_keeper(const char *room_id, const char *server_host, uint16_t server_port, int ssl, on_mk_webrtc_room_keeper_info_cb cb, void *user_data);
|
||||
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_add_room_keeper2(
|
||||
const char *room_id, const char *server_host, uint16_t server_port, int ssl, on_mk_webrtc_room_keeper_info_cb cb, void *user_data,
|
||||
on_user_data_free user_data_free);
|
||||
|
||||
|
||||
/**
|
||||
* WebRTC-从信令服务器注销
|
||||
* @param room_key 房间key
|
||||
* @param cb 回调函数
|
||||
* @param user_data 用户数据
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_webrtc_del_room_keeper(const char *room_key, on_mk_webrtc_room_keeper_info_cb cb, void *user_data);
|
||||
|
||||
API_EXPORT void API_CALL
|
||||
mk_webrtc_del_room_keeper2(const char *room_key, on_mk_webrtc_room_keeper_info_cb cb, void *user_data, on_user_data_free user_data_free);
|
||||
|
||||
|
||||
/**
|
||||
* WebRTC-Peer查看注册信息
|
||||
* @param cb 回调函数
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_webrtc_list_room_keeper(on_mk_webrtc_room_keeper_data_cb cb);
|
||||
|
||||
/**
|
||||
* WebRTC-信令服务器查看注册信息
|
||||
* @param cb 回调函数
|
||||
*/
|
||||
API_EXPORT void API_CALL mk_webrtc_list_rooms(on_mk_webrtc_room_keeper_data_cb cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MK_WEBRTC_H */
|
||||
@@ -29,6 +29,7 @@ using namespace mediakit;
|
||||
static TcpServer::Ptr rtsp_server[2];
|
||||
static TcpServer::Ptr rtmp_server[2];
|
||||
static TcpServer::Ptr http_server[2];
|
||||
static TcpServer::Ptr signaling_server[2];
|
||||
static TcpServer::Ptr shell_server;
|
||||
|
||||
#ifdef ENABLE_RTPPROXY
|
||||
@@ -37,9 +38,14 @@ static RtpServer::Ptr rtpServer;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_WEBRTC
|
||||
#include "../webrtc/WebRtcSession.h"
|
||||
#include "webrtc/WebRtcSession.h"
|
||||
#include "webrtc/IceSession.hpp"
|
||||
#include "webrtc/WebRtcSignalingSession.h"
|
||||
#include "webrtc/WebRtcTransport.h"
|
||||
static UdpServer::Ptr rtcServer_udp;
|
||||
static TcpServer::Ptr rtcServer_tcp;
|
||||
static UdpServer::Ptr iceServer_udp;
|
||||
static TcpServer::Ptr iceServer_tcp;
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_SRT)
|
||||
@@ -76,6 +82,9 @@ API_EXPORT void API_CALL mk_stop_all_server(){
|
||||
#ifdef ENABLE_WEBRTC
|
||||
rtcServer_udp = nullptr;
|
||||
rtcServer_tcp = nullptr;
|
||||
iceServer_udp = nullptr;
|
||||
iceServer_tcp = nullptr;
|
||||
CLEAR_ARR(signaling_server);
|
||||
#endif
|
||||
#ifdef ENABLE_SRT
|
||||
srtServer = nullptr;
|
||||
@@ -288,46 +297,46 @@ API_EXPORT uint16_t API_CALL mk_rtc_server_start(uint16_t port) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WEBRTC
|
||||
class WebRtcArgsUrl : public mediakit::WebRtcArgs {
|
||||
public:
|
||||
WebRtcArgsUrl(std::string url) { _url = std::move(url); }
|
||||
|
||||
toolkit::variant operator[](const std::string &key) const override {
|
||||
if (key == "url") {
|
||||
return _url;
|
||||
API_EXPORT uint16_t API_CALL mk_signaling_server_start(uint16_t port, int ssl) {
|
||||
#ifdef ENABLE_WEBRTC
|
||||
ssl = MAX(0, MIN(ssl, 1));
|
||||
try {
|
||||
signaling_server[ssl] = std::make_shared<TcpServer>();
|
||||
if (ssl) {
|
||||
signaling_server[ssl]->start<WebRtcWebcosktSignalSslSession>(port);
|
||||
} else {
|
||||
signaling_server[ssl]->start<WebRtcWebcosktSignalingSession>(port);
|
||||
}
|
||||
return "";
|
||||
return signaling_server[ssl]->getPort();
|
||||
} catch (std::exception &ex) {
|
||||
signaling_server[ssl] = nullptr;
|
||||
WarnL << ex.what();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _url;
|
||||
};
|
||||
#endif
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp(void *user_data, on_mk_webrtc_get_answer_sdp cb, const char *type,
|
||||
const char *offer, const char *url) {
|
||||
mk_webrtc_get_answer_sdp2(user_data, nullptr, cb, type, offer, url);
|
||||
}
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp2(void *user_data, on_user_data_free user_data_free, on_mk_webrtc_get_answer_sdp cb, const char *type,
|
||||
const char *offer, const char *url) {
|
||||
#ifdef ENABLE_WEBRTC
|
||||
assert(type && offer && url && cb);
|
||||
auto session = std::make_shared<HttpSession>(Socket::createSocket());
|
||||
std::string offer_str = offer;
|
||||
std::shared_ptr<void> ptr(user_data, user_data_free ? user_data_free : [](void *) {});
|
||||
auto args = std::make_shared<WebRtcArgsUrl>(url);
|
||||
WebRtcPluginManager::Instance().negotiateSdp(*session, type, *args, [offer_str, session, ptr, cb](const WebRtcInterface &exchanger) mutable {
|
||||
auto &handler = const_cast<WebRtcInterface &>(exchanger);
|
||||
try {
|
||||
auto sdp_answer = handler.getAnswerSdp(offer_str);
|
||||
cb(ptr.get(), sdp_answer.data(), nullptr);
|
||||
} catch (std::exception &ex) {
|
||||
cb(ptr.get(), nullptr, ex.what());
|
||||
}
|
||||
});
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
API_EXPORT uint16_t API_CALL mk_ice_server_start(uint16_t port){
|
||||
#ifdef ENABLE_WEBRTC
|
||||
try {
|
||||
iceServer_tcp = std::make_shared<TcpServer>();
|
||||
iceServer_udp = std::make_shared<UdpServer>();
|
||||
iceServer_udp->start<IceSession>(port);
|
||||
iceServer_tcp->start<IceSession>(port);
|
||||
return 0;
|
||||
} catch (std::exception &ex) {
|
||||
iceServer_udp = nullptr;
|
||||
iceServer_tcp = nullptr;
|
||||
WarnL << ex.what();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -296,6 +296,13 @@ API_EXPORT int API_CALL mk_media_source_seek_to(const mk_media_source ctx,uint32
|
||||
MediaSource *src = (MediaSource *)ctx;
|
||||
return src->seekTo(stamp);
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_media_source_set_speed(const mk_media_source ctx, float speed) {
|
||||
assert(ctx);
|
||||
MediaSource *src = (MediaSource *)ctx;
|
||||
src->getOwnerPoller()->async([=]() mutable { src->speed(speed); });
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_media_source_start_send_rtp(const mk_media_source ctx, const char *dst_url, uint16_t dst_port, const char *ssrc, int con_type, on_mk_media_source_send_rtp_result cb, void *user_data) {
|
||||
mk_media_source_start_send_rtp2(ctx, dst_url, dst_port, ssrc, con_type, cb, user_data, nullptr);
|
||||
}
|
||||
@@ -347,6 +354,7 @@ API_EXPORT void API_CALL mk_media_source_start_send_rtp4(const mk_media_source c
|
||||
args.close_delay_ms = (*ini_ptr)["close_delay_ms"].empty() ? 0 : (*ini_ptr)["close_delay_ms"].as<int>();
|
||||
args.rtcp_timeout_ms = (*ini_ptr)["rtcp_timeout_ms"].empty() ? 30000 : (*ini_ptr)["rtcp_timeout_ms"].as<int>();
|
||||
args.rtcp_send_interval_ms = (*ini_ptr)["rtcp_send_interval_ms"].empty() ? 5000 : (*ini_ptr)["rtcp_send_interval_ms"].as<int>();
|
||||
args.enable_origin_recv_limit = (*ini_ptr)["enable_origin_recv_limit"].empty() ? false : (*ini_ptr)["enable_origin_recv_limit"].as<bool>();
|
||||
std::shared_ptr<void> ptr(
|
||||
user_data, user_data_free ? user_data_free : [](void *) {});
|
||||
src->getOwnerPoller()->async([=]() mutable {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "mk_frame.h"
|
||||
#include "Record/MPEG.h"
|
||||
#include "Extension/Factory.h"
|
||||
#include "Rtp/PSDecoder.h"
|
||||
|
||||
using namespace mediakit;
|
||||
|
||||
@@ -223,4 +224,36 @@ API_EXPORT int API_CALL mk_mpeg_muxer_input_frame(mk_mpeg_muxer ctx, mk_frame fr
|
||||
assert(ctx && frame);
|
||||
auto ptr = reinterpret_cast<MpegMuxerForC *>(ctx);
|
||||
return ptr->inputFrame(*((Frame::Ptr *) frame));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#if defined(ENABLE_RTPPROXY)
|
||||
|
||||
API_EXPORT mk_ps_decoder API_CALL mk_ps_decoder_create(on_mk_ps_decoder_stream scb, on_mk_ps_decoder_frame dcb, void * user_data) {
|
||||
assert(dcb);
|
||||
auto ps_decoder = new PSDecoder();
|
||||
std::shared_ptr<void> ptr(user_data, [](void *) {});
|
||||
if (scb) {
|
||||
ps_decoder->setOnStream([ptr,scb](int stream, int codecid, const void *extra, size_t bytes, int finish) {
|
||||
scb(ptr.get(), stream, getCodecByMpegId(codecid), extra, bytes, finish);
|
||||
});
|
||||
}
|
||||
ps_decoder->setOnDecode([ptr,dcb](int stream, int codecid, int flags, int64_t pts, int64_t dts, const void *data, size_t bytes) {
|
||||
dcb(ptr.get(), stream,getCodecByMpegId(codecid),flags,pts,dts,data,bytes);
|
||||
});
|
||||
return reinterpret_cast<mk_ps_decoder>(ps_decoder);
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_ps_decoder_release(mk_ps_decoder ctx) {
|
||||
assert(ctx);
|
||||
auto ptr = reinterpret_cast<PSDecoder *>(ctx);
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_ps_decoder_input(mk_ps_decoder ctx, const char * data, size_t bytes) {
|
||||
assert(ctx && data);
|
||||
auto ptr = reinterpret_cast<PSDecoder *>(ctx);
|
||||
ptr->input(reinterpret_cast<const uint8_t *>(data), bytes);
|
||||
}
|
||||
#endif
|
||||
@@ -309,7 +309,7 @@ API_EXPORT void API_CALL mk_media_start_send_rtp2(mk_media ctx, const char *dst_
|
||||
auto ref = *obj;
|
||||
std::shared_ptr<void> ptr(user_data, user_data_free ? user_data_free : [](void *) {});
|
||||
(*obj)->getChannel()->getOwnerPoller(MediaSource::NullMediaSource())->async([args, ref, cb, ptr]() {
|
||||
ref->getChannel()->startSendRtp(MediaSource::NullMediaSource(), args, [cb, ptr](uint16_t local_port, const SockException &ex) {
|
||||
ref->getChannel()->getMuxer(MediaSource::NullMediaSource())->startSendRtp( args, [cb, ptr](uint16_t local_port, const SockException &ex) {
|
||||
if (cb) {
|
||||
cb(ptr.get(), local_port, ex.getErrCode(), ex.what());
|
||||
}
|
||||
@@ -343,13 +343,14 @@ API_EXPORT void API_CALL mk_media_start_send_rtp4(mk_media ctx, const char *dst_
|
||||
args.close_delay_ms = (*ini_ptr)["close_delay_ms"].empty() ? 30000 : (*ini_ptr)["close_delay_ms"].as<int>();
|
||||
args.rtcp_timeout_ms = (*ini_ptr)["rtcp_timeout_ms"].empty() ? 30000 : (*ini_ptr)["rtcp_timeout_ms"].as<int>();
|
||||
args.rtcp_send_interval_ms = (*ini_ptr)["rtcp_send_interval_ms"].empty() ? 5000 : (*ini_ptr)["rtcp_send_interval_ms"].as<int>();
|
||||
args.enable_origin_recv_limit = (*ini_ptr)["enable_origin_recv_limit"].empty() ? false : (*ini_ptr)["enable_origin_recv_limit"].as<bool>();
|
||||
// sender参数无用 [AUTO-TRANSLATED:21590ae5]
|
||||
// The sender parameter is useless
|
||||
auto ref = *obj;
|
||||
std::shared_ptr<void> ptr(
|
||||
user_data, user_data_free ? user_data_free : [](void *) {});
|
||||
(*obj)->getChannel()->getOwnerPoller(MediaSource::NullMediaSource())->async([args, ref, cb, ptr]() {
|
||||
ref->getChannel()->startSendRtp(MediaSource::NullMediaSource(), args, [cb, ptr](uint16_t local_port, const SockException &ex) {
|
||||
ref->getChannel()->getMuxer(MediaSource::NullMediaSource())->startSendRtp(args, [cb, ptr](uint16_t local_port, const SockException &ex) {
|
||||
if (cb) {
|
||||
cb(ptr.get(), local_port, ex.getErrCode(), ex.what());
|
||||
}
|
||||
@@ -365,7 +366,7 @@ API_EXPORT void API_CALL mk_media_stop_send_rtp(mk_media ctx, const char *ssrc)
|
||||
auto ref = *obj;
|
||||
string ssrc_str = ssrc ? ssrc : "";
|
||||
(*obj)->getChannel()->getOwnerPoller(MediaSource::NullMediaSource())->async([ref, ssrc_str]() {
|
||||
ref->getChannel()->stopSendRtp(MediaSource::NullMediaSource(), ssrc_str);
|
||||
ref->getChannel()->getMuxer(MediaSource::NullMediaSource())->stopSendRtp(ssrc_str);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,27 @@ API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char
|
||||
return stopRecord((Recorder::type)type,vhost,app,stream);
|
||||
}
|
||||
|
||||
API_EXPORT int API_CALL mk_recorder_start_task(const char *vhost, const char *app, const char *stream, const char *path, uint32_t back_ms, uint32_t forward_ms) {
|
||||
assert(vhost && app && stream);
|
||||
auto src = MediaSource::find(vhost, app, stream);
|
||||
if (!src) {
|
||||
WarnL << "未找到相关的MediaSource,startRecordTask失败:" << vhost << "/" << app << "/" << stream;
|
||||
return false;
|
||||
}
|
||||
bool ret;
|
||||
src->getOwnerPoller()->async([=]() mutable {
|
||||
std::string err;
|
||||
try {
|
||||
src->getMuxer()->startRecord(path, back_ms, forward_ms);
|
||||
} catch (std::exception &ex) {
|
||||
err = ex.what();
|
||||
WarnL << "MediaSource开启startRecordTask失败:" << vhost << "/" << app << "/" << stream << " what: " << err;
|
||||
}
|
||||
ret = err.empty();
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_load_mp4_file(const char *vhost, const char *app, const char *stream, const char *file_path, int file_repeat) {
|
||||
mINI ini;
|
||||
mk_load_mp4_file2(vhost, app, stream, file_path, file_repeat, (mk_ini)&ini);
|
||||
|
||||
@@ -31,6 +31,13 @@ API_EXPORT mk_rtp_server API_CALL mk_rtp_server_create2(uint16_t port, int tcp_m
|
||||
return (mk_rtp_server)server;
|
||||
}
|
||||
|
||||
API_EXPORT mk_rtp_server API_CALL mk_rtp_server_create3(uint16_t port, int tcp_mode, const char *vhost, const char *app, const char *stream_id, int multiplex) {
|
||||
RtpServer::Ptr *server = new RtpServer::Ptr(new RtpServer);
|
||||
GET_CONFIG(std::string, local_ip, General::kListenIP)
|
||||
(*server)->start(port, local_ip.c_str(), MediaTuple { vhost, app, stream_id, "" }, (RtpServer::TcpMode)tcp_mode,multiplex);
|
||||
return (mk_rtp_server)server;
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_rtp_server_connect(mk_rtp_server ctx, const char *dst_url, uint16_t dst_port, on_mk_rtp_server_connected cb, void *user_data) {
|
||||
mk_rtp_server_connect2(ctx, dst_url, dst_port, cb, user_data, nullptr);
|
||||
}
|
||||
@@ -73,6 +80,41 @@ API_EXPORT void API_CALL mk_rtp_server_set_on_detach2(mk_rtp_server ctx, on_mk_r
|
||||
}
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_rtp_server_update_ssrc(mk_rtp_server ctx, uint32_t ssrc) {
|
||||
assert(ctx);
|
||||
RtpServer::Ptr *server = (RtpServer::Ptr *)ctx;
|
||||
(*server)->updateSSRC(ssrc);
|
||||
}
|
||||
|
||||
|
||||
API_EXPORT void API_CALL mk_rtp_get_info(const char *app, const char *stream, on_mk_rtp_get_info cb) {
|
||||
assert(cb);
|
||||
auto src = MediaSource::find(DEFAULT_VHOST, app, stream);
|
||||
auto process = src ? src->getRtpProcess() : nullptr;
|
||||
if (!process) {
|
||||
cb(0, nullptr, 0, nullptr, 0, nullptr);
|
||||
return;
|
||||
}
|
||||
SockInfo *info = process.get();
|
||||
cb(1, info->get_local_ip().c_str(), info->get_peer_port(), info->get_local_ip().c_str(), info->get_local_port(), info->getIdentifier().c_str());
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_rtp_pause_check(const char *app, const char *stream) {
|
||||
auto src = MediaSource::find(DEFAULT_VHOST, app, stream);
|
||||
auto process = src ? src->getRtpProcess() : nullptr;
|
||||
if (process) {
|
||||
process->pauseRtpTimeout(true);
|
||||
}
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_rtp_resume_check(const char *app, const char *stream) {
|
||||
auto src = MediaSource::find(DEFAULT_VHOST, app, stream);
|
||||
auto process = src ? src->getRtpProcess() : nullptr;
|
||||
if (process) {
|
||||
process->pauseRtpTimeout(false);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
API_EXPORT mk_rtp_server API_CALL mk_rtp_server_create(uint16_t port, int enable_tcp, const char *stream_id) {
|
||||
|
||||
190
api/source/mk_webrtc.cpp
Normal file
190
api/source/mk_webrtc.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
|
||||
*
|
||||
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
|
||||
*
|
||||
* Use of this source code is governed by MIT-like license that can be found in the
|
||||
* LICENSE file in the root of the source tree. All contributing project authors
|
||||
* may be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "mk_webrtc.h"
|
||||
#include "mk_util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <unordered_map>
|
||||
#include "Util/logger.h"
|
||||
#include "Util/SSLBox.h"
|
||||
#include "Util/File.h"
|
||||
#include "Network/TcpServer.h"
|
||||
#include "Network/UdpServer.h"
|
||||
#include "Thread/WorkThreadPool.h"
|
||||
|
||||
#include "Rtsp/RtspSession.h"
|
||||
#include "Rtmp/RtmpSession.h"
|
||||
#include "Http/HttpSession.h"
|
||||
#include "Shell/ShellSession.h"
|
||||
#include "Player/PlayerProxy.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
using namespace mediakit;
|
||||
|
||||
#ifdef ENABLE_WEBRTC
|
||||
|
||||
#include "webrtc/WebRtcProxyPlayer.h"
|
||||
#include "webrtc/WebRtcProxyPlayerImp.h"
|
||||
#include "webrtc/WebRtcSignalingPeer.h"
|
||||
#include "webrtc/WebRtcSignalingSession.h"
|
||||
#include "webrtc/WebRtcSession.h"
|
||||
|
||||
static UdpServer::Ptr rtcServer_udp;
|
||||
static TcpServer::Ptr rtcServer_tcp;
|
||||
class WebRtcArgsUrl : public mediakit::WebRtcArgs {
|
||||
public:
|
||||
WebRtcArgsUrl(std::string url) { _url = std::move(url); }
|
||||
|
||||
toolkit::variant operator[](const std::string &key) const override {
|
||||
if (key == "url") {
|
||||
return _url;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _url;
|
||||
};
|
||||
#endif
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp(void *user_data, on_mk_webrtc_get_answer_sdp cb, const char *type, const char *offer, const char *url) {
|
||||
mk_webrtc_get_answer_sdp2(user_data, nullptr, cb, type, offer, url);
|
||||
}
|
||||
API_EXPORT void API_CALL mk_webrtc_get_answer_sdp2(
|
||||
void *user_data, on_user_data_free user_data_free, on_mk_webrtc_get_answer_sdp cb, const char *type, const char *offer, const char *url) {
|
||||
#ifdef ENABLE_WEBRTC
|
||||
assert(type && offer && url && cb);
|
||||
auto session = std::make_shared<HttpSession>(Socket::createSocket());
|
||||
std::string offer_str = offer;
|
||||
std::shared_ptr<void> ptr(user_data, user_data_free ? user_data_free : [](void *) {});
|
||||
auto args = std::make_shared<WebRtcArgsUrl>(url);
|
||||
WebRtcPluginManager::Instance().negotiateSdp(*session, type, *args, [offer_str, session, ptr, cb](const WebRtcInterface &exchanger) mutable {
|
||||
auto &handler = const_cast<WebRtcInterface &>(exchanger);
|
||||
try {
|
||||
auto sdp_answer = handler.getAnswerSdp(offer_str);
|
||||
cb(ptr.get(), sdp_answer.data(), nullptr);
|
||||
} catch (std::exception &ex) {
|
||||
cb(ptr.get(), nullptr, ex.what());
|
||||
}
|
||||
});
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
#endif
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_get_proxy_player_info(mk_proxy_player ctx, on_mk_webrtc_get_proxy_player_info_cb cb) {
|
||||
#ifdef ENABLE_WEBRTC
|
||||
assert(ctx && cb);
|
||||
PlayerProxy::Ptr *obj = (PlayerProxy::Ptr *)ctx;
|
||||
auto media_player = obj->get()->getDelegate();
|
||||
if (!media_player) {
|
||||
cb(nullptr, "Media player not found");
|
||||
return;
|
||||
}
|
||||
|
||||
auto webrtc_player_imp = std::dynamic_pointer_cast<WebRtcProxyPlayerImp>(media_player);
|
||||
if (!webrtc_player_imp) {
|
||||
cb(nullptr, "Stream proxy is not WebRTC type");
|
||||
return;
|
||||
}
|
||||
|
||||
auto webrtc_transport = webrtc_player_imp->getWebRtcTransport();
|
||||
if (!webrtc_transport) {
|
||||
cb(nullptr, "WebRTC transport not available");
|
||||
return;
|
||||
}
|
||||
|
||||
webrtc_transport->getTransportInfo([cb](Json::Value transport_info) mutable {
|
||||
if (transport_info.isMember("error")) {
|
||||
cb(nullptr, strdup(transport_info["error"].asCString()));
|
||||
return;
|
||||
}
|
||||
cb(strdup(transport_info.toStyledString().c_str()), "");
|
||||
});
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
#endif
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_add_room_keeper(
|
||||
const char *room_id, const char *server_host, uint16_t server_port, int ssl, on_mk_webrtc_room_keeper_info_cb cb, void *user_data) {
|
||||
mk_webrtc_add_room_keeper2(room_id, server_host, server_port, ssl, cb, user_data, nullptr);
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_add_room_keeper2(
|
||||
const char *room_id, const char *server_host, uint16_t server_port, int ssl, on_mk_webrtc_room_keeper_info_cb cb, void *user_data,
|
||||
on_user_data_free user_data_free) {
|
||||
#ifdef ENABLE_WEBRTC
|
||||
assert(server_host && server_port && room_id && cb);
|
||||
// server_host: 信令服务器host
|
||||
// server_post: 信令服务器host
|
||||
// room_id: 注册的id,信令服务器会对该id进行唯一性检查
|
||||
std::string server_host_str(server_host), room_id_str(room_id);
|
||||
std::shared_ptr<void> ptr(user_data, user_data_free ? user_data_free : [](void *) {});
|
||||
addWebrtcRoomKeeper(server_host_str, server_port, room_id_str, ssl, [ptr,cb](const SockException &ex, const string &key) mutable {
|
||||
if (ex) {
|
||||
cb(ptr.get(), nullptr, ex.what());
|
||||
} else {
|
||||
cb(ptr.get(), key.c_str(), nullptr);
|
||||
}
|
||||
});
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
#endif
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_del_room_keeper(const char *room_key, on_mk_webrtc_room_keeper_info_cb cb, void *user_data) {
|
||||
mk_webrtc_del_room_keeper2(room_key,cb,user_data,nullptr);
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL
|
||||
mk_webrtc_del_room_keeper2(const char *room_key, on_mk_webrtc_room_keeper_info_cb cb, void *user_data, on_user_data_free user_data_free) {
|
||||
#ifdef ENABLE_WEBRTC
|
||||
assert(room_key && cb);
|
||||
std::string room_key_str(room_key);
|
||||
std::shared_ptr<void> ptr(user_data, user_data_free ? user_data_free : [](void *) {});
|
||||
delWebrtcRoomKeeper(room_key_str, [room_key_str, ptr, cb](const SockException &ex) mutable {
|
||||
if (ex) {
|
||||
cb(ptr.get(), room_key_str.c_str(), ex.what());
|
||||
}
|
||||
cb(ptr.get(), room_key_str.c_str(), nullptr);
|
||||
});
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
#endif
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_list_room_keeper(on_mk_webrtc_room_keeper_data_cb cb) {
|
||||
#ifdef ENABLE_WEBRTC
|
||||
assert(cb);
|
||||
listWebrtcRoomKeepers([cb](const std::string &key, const WebRtcSignalingPeer::Ptr &p) {
|
||||
Json::Value item = ToJson(p);
|
||||
item["room_key"] = key;
|
||||
cb(strdup(item.toStyledString().c_str()));
|
||||
});
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
#endif
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_webrtc_list_rooms(on_mk_webrtc_room_keeper_data_cb cb){
|
||||
#ifdef ENABLE_WEBRTC
|
||||
assert(cb);
|
||||
listWebrtcRooms([cb](const std::string &key, const WebRtcSignalingSession::Ptr &p) {
|
||||
Json::Value item = ToJson(p);
|
||||
item["room_id"] = key;
|
||||
cb(strdup(item.toStyledString().c_str()));
|
||||
});
|
||||
#else
|
||||
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||
#endif
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2016-2022 The ZLMediaKit project authors. All Rights Reserved.
|
||||
# Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -64,7 +64,8 @@ void API_CALL on_mk_push_event_func(void *user_data,int err_code,const char *err
|
||||
void API_CALL on_mk_media_source_regist_func(void *user_data, mk_media_source sender, int regist){
|
||||
Context *ctx = (Context *) user_data;
|
||||
const char *schema = mk_media_source_get_schema(sender);
|
||||
if (strncmp(schema, ctx->push_url, strlen(schema)) == 0) {
|
||||
if (strncmp(schema, ctx->push_url, strlen(schema)) == 0 ||
|
||||
(!strncmp(ctx->push_url, "webrtc", 5) && !strcmp(schema, "rtsp")) ) {
|
||||
// 判断是否为推流协议相关的流注册或注销事件 [AUTO-TRANSLATED:00a88a17]
|
||||
// Determine if it is a stream registration or deregistration event related to the streaming protocol
|
||||
release_pusher(&(ctx->pusher));
|
||||
|
||||
Reference in New Issue
Block a user