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:
cqm
2026-04-03 09:35:50 +08:00
283 changed files with 42056 additions and 13083 deletions

View File

@@ -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()

View File

@@ -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服务器

View File

@@ -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推流成功与否的回调(第一次成功后,后面将一直重试)

View File

@@ -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

View File

@@ -27,5 +27,6 @@
#include "mk_frame.h"
#include "mk_track.h"
#include "mk_transcode.h"
#include "mk_webrtc.h"
#endif /* MK_API_H_ */

View File

@@ -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 虚拟主机

View File

@@ -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
View 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 */

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);
});
}

View File

@@ -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);

View File

@@ -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
View 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
}

View File

@@ -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

View File

@@ -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));