mirror of
https://gitee.com/xia-chu/ZLMediaKit.git
synced 2026-05-26 03:27:49 +08:00
Compare commits
7 Commits
7534a70f34
...
def8bb53f2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
def8bb53f2 | ||
|
|
26e9ad32ba | ||
|
|
33c61613dc | ||
|
|
386e18e233 | ||
|
|
d0a86924b7 | ||
|
|
da9deb352c | ||
|
|
6e485ad31a |
@ -396,6 +396,12 @@ Track::Ptr getTrackBySdp(const SdpTrack::Ptr &track) {
|
|||||||
// If aac config information cannot be obtained from sdp, then it cannot be obtained from rtp either, so ignore this Track
|
// If aac config information cannot be obtained from sdp, then it cannot be obtained from rtp either, so ignore this Track
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
while (aac_cfg_str.size() < 4) {
|
||||||
|
aac_cfg_str = '0' + aac_cfg_str;
|
||||||
|
}
|
||||||
|
if (aac_cfg_str.size() > 4) {
|
||||||
|
aac_cfg_str = aac_cfg_str.substr(0, 4);
|
||||||
|
}
|
||||||
string aac_cfg;
|
string aac_cfg;
|
||||||
for (size_t i = 0; i < aac_cfg_str.size() / 2; ++i) {
|
for (size_t i = 0; i < aac_cfg_str.size() / 2; ++i) {
|
||||||
unsigned int cfg;
|
unsigned int cfg;
|
||||||
|
|||||||
@ -63,20 +63,20 @@ def on_exit():
|
|||||||
mk_logger.log_info("on_exit")
|
mk_logger.log_info("on_exit")
|
||||||
|
|
||||||
def on_publish(type: str, args: dict, invoker, sender: dict) -> bool:
|
def on_publish(type: str, args: dict, invoker, sender: dict) -> bool:
|
||||||
mk_logger.log_info(f"args: {type}, args: {args}, sender: {sender}")
|
mk_logger.log_info(f"type: {type}, args: {args}, sender: {sender}")
|
||||||
# opt 控制转协议,请参考配置文件[protocol]下字段
|
# opt 控制转协议,请参考配置文件[protocol]下字段
|
||||||
opt = {
|
opt = {
|
||||||
"enable_rtmp": "1"
|
"enable_rtmp": "1"
|
||||||
}
|
}
|
||||||
# 响应推流鉴权结果
|
# 响应推流鉴权结果
|
||||||
mk_loader.publish_auth_invoker_do(invoker, "", opt);
|
mk_loader.publish_auth_invoker_do(invoker, "", opt)
|
||||||
# 返回True代表此事件被python拦截
|
# 返回True代表此事件被python拦截
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_play(args: dict, invoker, sender: dict) -> bool:
|
def on_play(args: dict, invoker, sender: dict) -> bool:
|
||||||
mk_logger.log_info(f"args: {args}, sender: {sender}")
|
mk_logger.log_info(f"args: {args}, sender: {sender}")
|
||||||
# 响应播放鉴权结果
|
# 响应播放鉴权结果
|
||||||
mk_loader.auth_invoker_do(invoker, "");
|
mk_loader.play_auth_invoker_do(invoker, "")
|
||||||
# 返回True代表此事件被python拦截
|
# 返回True代表此事件被python拦截
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -85,5 +85,43 @@ def on_flow_report(args: dict, totalBytes: int, totalDuration: int, isPlayer: bo
|
|||||||
# 返回True代表此事件被python拦截
|
# 返回True代表此事件被python拦截
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def on_media_changed(is_register: bool, sender) -> bool:
|
||||||
|
mk_logger.log_info(f"is_register: {is_register}, sender: {sender.getUrl()}")
|
||||||
|
# 该事件在c++中也处理下
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_player_proxy_failed(url, media_tuple, ex) -> bool:
|
||||||
|
mk_logger.log_info(f"on_player_proxy_failed: {url}, {media_tuple.shortUrl()}, {ex.what()}")
|
||||||
|
# 该事件在c++中也处理下
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_get_rtsp_realm(args: dict, invoker, sender) -> bool:
|
||||||
|
mk_logger.log_info(f"on_get_rtsp_realm, args: {args}, sender: {sender}")
|
||||||
|
mk_loader.rtsp_get_realm_invoker_do(invoker, "zlmediakit")
|
||||||
|
# 返回True代表此事件被python拦截
|
||||||
|
return True
|
||||||
|
|
||||||
|
def on_rtsp_auth(args: dict, realm: str, user_name: str, must_no_encrypt: bool, invoker, sender:dict) -> bool:
|
||||||
|
mk_logger.log_info(f"on_rtsp_auth, args: {args}, realm: {realm}, user_name: {user_name}, must_no_encrypt: {must_no_encrypt}, sender: {sender}")
|
||||||
|
mk_loader.rtsp_auth_invoker_do(invoker, False, "zlmediakit")
|
||||||
|
# 返回True代表此事件被python拦截
|
||||||
|
return True
|
||||||
|
|
||||||
|
def on_stream_not_found(args: dict, sender:dict, invoker) -> bool:
|
||||||
|
mk_logger.log_info(f"on_stream_not_found, args: {args}, sender: {sender}")
|
||||||
|
# 立即通知播放器流不存在并关闭
|
||||||
|
mk_loader.close_player_invoker_do(invoker)
|
||||||
|
# 返回True代表此事件被python拦截
|
||||||
|
return True
|
||||||
|
|
||||||
|
def on_record_mp4(info: dict) -> bool:
|
||||||
|
mk_logger.log_info(f"on_record_mp4, info: {info}")
|
||||||
|
# 返回True代表此事件被python拦截
|
||||||
|
return True
|
||||||
|
def on_record_ts(info: dict) -> bool:
|
||||||
|
mk_logger.log_info(f"on_record_ts, info: {info}")
|
||||||
|
# 返回True代表此事件被python拦截
|
||||||
|
return True
|
||||||
|
|
||||||
def on_reload_config():
|
def on_reload_config():
|
||||||
mk_logger.log_info(f"on_reload_config")
|
mk_logger.log_info(f"on_reload_config")
|
||||||
@ -359,6 +359,19 @@ static mINI jsonToMini(const Value &obj) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArgsType getRecordInfo(const RecordInfo &info) {
|
||||||
|
ArgsType body;
|
||||||
|
body["start_time"] = (Json::UInt64)info.start_time;
|
||||||
|
body["file_size"] = (Json::UInt64)info.file_size;
|
||||||
|
body["time_len"] = info.time_len;
|
||||||
|
body["file_path"] = info.file_path;
|
||||||
|
body["file_name"] = info.file_name;
|
||||||
|
body["folder"] = info.folder;
|
||||||
|
body["url"] = info.url;
|
||||||
|
dumpMediaTuple(info, body);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
void installWebHook() {
|
void installWebHook() {
|
||||||
GET_CONFIG(bool, hook_enable, Hook::kEnable);
|
GET_CONFIG(bool, hook_enable, Hook::kEnable);
|
||||||
|
|
||||||
@ -444,6 +457,11 @@ void installWebHook() {
|
|||||||
// 监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问 [AUTO-TRANSLATED:00dc9fa3]
|
// 监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问 [AUTO-TRANSLATED:00dc9fa3]
|
||||||
// Listen to the kBroadcastOnGetRtspRealm event to determine whether the rtsp link needs authentication (traditional rtsp authentication scheme) to access
|
// Listen to the kBroadcastOnGetRtspRealm event to determine whether the rtsp link needs authentication (traditional rtsp authentication scheme) to access
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastOnGetRtspRealm, [](BroadcastOnGetRtspRealmArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastOnGetRtspRealm, [](BroadcastOnGetRtspRealmArgs) {
|
||||||
|
#if defined(ENABLE_PYTHON)
|
||||||
|
if (PythonInvoker::Instance().on_get_rtsp_realm(args, invoker, sender)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
GET_CONFIG(string, hook_rtsp_realm, Hook::kOnRtspRealm);
|
GET_CONFIG(string, hook_rtsp_realm, Hook::kOnRtspRealm);
|
||||||
if (!hook_enable || hook_rtsp_realm.empty()) {
|
if (!hook_enable || hook_rtsp_realm.empty()) {
|
||||||
// 无需认证 [AUTO-TRANSLATED:77728e07]
|
// 无需认证 [AUTO-TRANSLATED:77728e07]
|
||||||
@ -471,6 +489,11 @@ void installWebHook() {
|
|||||||
// 监听kBroadcastOnRtspAuth事件返回正确的rtsp鉴权用户密码 [AUTO-TRANSLATED:bcf1754e]
|
// 监听kBroadcastOnRtspAuth事件返回正确的rtsp鉴权用户密码 [AUTO-TRANSLATED:bcf1754e]
|
||||||
// Listen to the kBroadcastOnRtspAuth event to return the correct rtsp authentication username and password
|
// Listen to the kBroadcastOnRtspAuth event to return the correct rtsp authentication username and password
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastOnRtspAuth, [](BroadcastOnRtspAuthArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastOnRtspAuth, [](BroadcastOnRtspAuthArgs) {
|
||||||
|
#if defined(ENABLE_PYTHON)
|
||||||
|
if (PythonInvoker::Instance().on_rtsp_auth(args, realm, user_name, must_no_encrypt, invoker, sender)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
GET_CONFIG(string, hook_rtsp_auth, Hook::kOnRtspAuth);
|
GET_CONFIG(string, hook_rtsp_auth, Hook::kOnRtspAuth);
|
||||||
if (unAuthedRealm == realm || !hook_enable || hook_rtsp_auth.empty()) {
|
if (unAuthedRealm == realm || !hook_enable || hook_rtsp_auth.empty()) {
|
||||||
// 认证失败 [AUTO-TRANSLATED:70cf56ff]
|
// 认证失败 [AUTO-TRANSLATED:70cf56ff]
|
||||||
@ -571,6 +594,12 @@ void installWebHook() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ENABLE_PYTHON)
|
||||||
|
if (PythonInvoker::Instance().on_stream_not_found(args, sender, closePlayer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GET_CONFIG(string, hook_stream_not_found, Hook::kOnStreamNotFound);
|
GET_CONFIG(string, hook_stream_not_found, Hook::kOnStreamNotFound);
|
||||||
if (!hook_enable || hook_stream_not_found.empty()) {
|
if (!hook_enable || hook_stream_not_found.empty()) {
|
||||||
return;
|
return;
|
||||||
@ -594,23 +623,15 @@ void installWebHook() {
|
|||||||
do_http_hook(hook_stream_not_found, body, res_cb);
|
do_http_hook(hook_stream_not_found, body, res_cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
static auto getRecordInfo = [](const RecordInfo &info) {
|
|
||||||
ArgsType body;
|
|
||||||
body["start_time"] = (Json::UInt64)info.start_time;
|
|
||||||
body["file_size"] = (Json::UInt64)info.file_size;
|
|
||||||
body["time_len"] = info.time_len;
|
|
||||||
body["file_path"] = info.file_path;
|
|
||||||
body["file_name"] = info.file_name;
|
|
||||||
body["folder"] = info.folder;
|
|
||||||
body["url"] = info.url;
|
|
||||||
dumpMediaTuple(info, body);
|
|
||||||
return body;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef ENABLE_MP4
|
#ifdef ENABLE_MP4
|
||||||
// 录制mp4文件成功后广播 [AUTO-TRANSLATED:479ec954]
|
// 录制mp4文件成功后广播 [AUTO-TRANSLATED:479ec954]
|
||||||
// Broadcast after recording the mp4 file successfully
|
// Broadcast after recording the mp4 file successfully
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastRecordMP4, [](BroadcastRecordMP4Args) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastRecordMP4, [](BroadcastRecordMP4Args) {
|
||||||
|
#if defined(ENABLE_PYTHON)
|
||||||
|
if (PythonInvoker::Instance().on_record_mp4(info)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
GET_CONFIG(string, hook_record_mp4, Hook::kOnRecordMp4);
|
GET_CONFIG(string, hook_record_mp4, Hook::kOnRecordMp4);
|
||||||
if (!hook_enable || hook_record_mp4.empty()) {
|
if (!hook_enable || hook_record_mp4.empty()) {
|
||||||
return;
|
return;
|
||||||
@ -622,6 +643,11 @@ void installWebHook() {
|
|||||||
#endif // ENABLE_MP4
|
#endif // ENABLE_MP4
|
||||||
|
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastRecordTs, [](BroadcastRecordTsArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastRecordTs, [](BroadcastRecordTsArgs) {
|
||||||
|
#if defined(ENABLE_PYTHON)
|
||||||
|
if (PythonInvoker::Instance().on_record_ts(info)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
GET_CONFIG(string, hook_record_ts, Hook::kOnRecordTs);
|
GET_CONFIG(string, hook_record_ts, Hook::kOnRecordTs);
|
||||||
if (!hook_enable || hook_record_ts.empty()) {
|
if (!hook_enable || hook_record_ts.empty()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -19,6 +19,7 @@ using namespace mediakit;
|
|||||||
|
|
||||||
extern ArgsType make_json(const MediaInfo &args);
|
extern ArgsType make_json(const MediaInfo &args);
|
||||||
extern void fillSockInfo(Json::Value & val, SockInfo* info);
|
extern void fillSockInfo(Json::Value & val, SockInfo* info);
|
||||||
|
extern ArgsType getRecordInfo(const RecordInfo &info);
|
||||||
extern std::string g_ini_file;
|
extern std::string g_ini_file;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -73,8 +74,12 @@ py::dict to_python(const SockInfo &info) {
|
|||||||
return jsonToPython(json);
|
return jsonToPython(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
py::dict to_python(const RecordInfo &info) {
|
||||||
|
return jsonToPython(getRecordInfo(info));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::shared_ptr<T> to_python2(const T &t) {
|
std::shared_ptr<T> to_python_ref(const T &t) {
|
||||||
return std::shared_ptr<T>(const_cast<T *>(&t), py::nodelete());
|
return std::shared_ptr<T>(const_cast<T *>(&t), py::nodelete());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,13 +208,34 @@ PYBIND11_EMBEDDED_MODULE(mk_loader, m) {
|
|||||||
invoker(err, option);
|
invoker(err, option);
|
||||||
});
|
});
|
||||||
|
|
||||||
m.def("auth_invoker_do", [](const py::capsule &cap, const std::string &err) {
|
m.def("play_auth_invoker_do", [](const py::capsule &cap, const std::string &err) {
|
||||||
// 执行c++代码时释放gil锁
|
// 执行c++代码时释放gil锁
|
||||||
py::gil_scoped_release release;
|
py::gil_scoped_release release;
|
||||||
auto &invoker = to_native<Broadcast::AuthInvoker>(cap);
|
auto &invoker = to_native<Broadcast::AuthInvoker>(cap);
|
||||||
invoker(err);
|
invoker(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m.def("rtsp_get_realm_invoker_do", [](const py::capsule &cap, const std::string &realm) {
|
||||||
|
// 执行c++代码时释放gil锁
|
||||||
|
py::gil_scoped_release release;
|
||||||
|
auto &invoker = to_native<RtspSession::onGetRealm>(cap);
|
||||||
|
invoker(realm);
|
||||||
|
});
|
||||||
|
|
||||||
|
m.def("rtsp_auth_invoker_do", [](const py::capsule &cap, bool encrypted, const std::string &pwd_or_md5) {
|
||||||
|
// 执行c++代码时释放gil锁
|
||||||
|
py::gil_scoped_release release;
|
||||||
|
auto &invoker = to_native<RtspSession::onAuth>(cap);
|
||||||
|
invoker(encrypted, pwd_or_md5);
|
||||||
|
});
|
||||||
|
|
||||||
|
m.def("close_player_invoker_do", [](const py::capsule &cap) {
|
||||||
|
// 执行c++代码时释放gil锁
|
||||||
|
py::gil_scoped_release release;
|
||||||
|
auto &invoker = to_native<std::function<void()>>(cap);
|
||||||
|
invoker();
|
||||||
|
});
|
||||||
|
|
||||||
m.def("set_fastapi", [](const py::object &check_route, const py::object &submit_coro) {
|
m.def("set_fastapi", [](const py::object &check_route, const py::object &submit_coro) {
|
||||||
static void *fastapi_tag = nullptr;
|
static void *fastapi_tag = nullptr;
|
||||||
NoticeCenter::Instance().delListener(&fastapi_tag, Broadcast::kBroadcastHttpRequest);
|
NoticeCenter::Instance().delListener(&fastapi_tag, Broadcast::kBroadcastHttpRequest);
|
||||||
@ -323,13 +349,18 @@ PythonInvoker::~PythonInvoker() {
|
|||||||
if (_on_exit) {
|
if (_on_exit) {
|
||||||
_on_exit();
|
_on_exit();
|
||||||
}
|
}
|
||||||
_on_exit = py::object();
|
_on_exit = py::function();
|
||||||
_on_publish = py::object();
|
_on_publish = py::function();
|
||||||
_on_play = py::object();
|
_on_play = py::function();
|
||||||
_on_flow_report = py::object();
|
_on_flow_report = py::function();
|
||||||
_on_reload_config = py::object();
|
_on_reload_config = py::function();
|
||||||
_on_media_changed = py::object();
|
_on_media_changed = py::function();
|
||||||
_on_player_proxy_failed = py::object();
|
_on_player_proxy_failed = py::function();
|
||||||
|
_on_get_rtsp_realm = py::function();
|
||||||
|
_on_rtsp_auth = py::function();
|
||||||
|
_on_stream_not_found = py::function();
|
||||||
|
_on_record_mp4 = py::function();
|
||||||
|
_on_record_ts = py::function();
|
||||||
_module = py::module();
|
_module = py::module();
|
||||||
}
|
}
|
||||||
delete _rel;
|
delete _rel;
|
||||||
@ -352,6 +383,11 @@ void PythonInvoker::load(const std::string &module_name) {
|
|||||||
GET_FUNC(_module, on_reload_config);
|
GET_FUNC(_module, on_reload_config);
|
||||||
GET_FUNC(_module, on_media_changed);
|
GET_FUNC(_module, on_media_changed);
|
||||||
GET_FUNC(_module, on_player_proxy_failed);
|
GET_FUNC(_module, on_player_proxy_failed);
|
||||||
|
GET_FUNC(_module, on_get_rtsp_realm);
|
||||||
|
GET_FUNC(_module, on_rtsp_auth);
|
||||||
|
GET_FUNC(_module, on_stream_not_found);
|
||||||
|
GET_FUNC(_module, on_record_mp4);
|
||||||
|
GET_FUNC(_module, on_record_ts);
|
||||||
|
|
||||||
if (hasattr(_module, "on_start")) {
|
if (hasattr(_module, "on_start")) {
|
||||||
py::object on_start = _module.attr("on_start");
|
py::object on_start = _module.attr("on_start");
|
||||||
@ -393,7 +429,7 @@ bool PythonInvoker::on_media_changed(BroadcastMediaChangedArgs) const {
|
|||||||
if (!_on_media_changed) {
|
if (!_on_media_changed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _on_media_changed(bRegist, to_python2(sender)).cast<bool>();
|
return _on_media_changed(bRegist, to_python_ref(sender)).cast<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonInvoker::on_player_proxy_failed(BroadcastPlayerProxyFailedArgs) const {
|
bool PythonInvoker::on_player_proxy_failed(BroadcastPlayerProxyFailedArgs) const {
|
||||||
@ -401,7 +437,47 @@ bool PythonInvoker::on_player_proxy_failed(BroadcastPlayerProxyFailedArgs) const
|
|||||||
if (!_on_player_proxy_failed) {
|
if (!_on_player_proxy_failed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _on_player_proxy_failed(sender.getUrl(), to_python2(sender.getMediaTuple()), to_python2(ex)).cast<bool>();
|
return _on_player_proxy_failed(sender.getUrl(), to_python_ref(sender.getMediaTuple()), to_python_ref(ex)).cast<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PythonInvoker::on_get_rtsp_realm(BroadcastOnGetRtspRealmArgs) const {
|
||||||
|
py::gil_scoped_acquire gil; // 确保在 Python 调用期间持有 GIL
|
||||||
|
if (!_on_get_rtsp_realm) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _on_get_rtsp_realm(to_python(args), to_python(invoker), to_python(sender)).cast<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PythonInvoker::on_rtsp_auth(BroadcastOnRtspAuthArgs) const {
|
||||||
|
py::gil_scoped_acquire gil; // 确保在 Python 调用期间持有 GIL
|
||||||
|
if (!_on_rtsp_auth) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _on_rtsp_auth(to_python(args), realm, user_name, must_no_encrypt, to_python(invoker), to_python(sender)).cast<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PythonInvoker::on_stream_not_found(BroadcastNotFoundStreamArgs) const {
|
||||||
|
py::gil_scoped_acquire gil; // 确保在 Python 调用期间持有 GIL
|
||||||
|
if (!_on_stream_not_found) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _on_stream_not_found(to_python(args), to_python(sender), to_python(closePlayer)).cast<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PythonInvoker::on_record_mp4(BroadcastRecordMP4Args) const {
|
||||||
|
py::gil_scoped_acquire gil; // 确保在 Python 调用期间持有 GIL
|
||||||
|
if (!_on_record_mp4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _on_record_mp4(to_python(info)).cast<bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PythonInvoker::on_record_ts(BroadcastRecordTsArgs) const {
|
||||||
|
py::gil_scoped_acquire gil; // 确保在 Python 调用期间持有 GIL
|
||||||
|
if (!_on_record_ts) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _on_record_ts(to_python(info)).cast<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mediakit
|
} // namespace mediakit
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
#include "Common/MediaSource.h"
|
#include "Common/MediaSource.h"
|
||||||
#include "Player/PlayerProxy.h"
|
#include "Player/PlayerProxy.h"
|
||||||
|
#include "Rtsp/RtspSession.h"
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
|
|
||||||
@ -30,6 +31,11 @@ public:
|
|||||||
bool on_flow_report(BroadcastFlowReportArgs) const;
|
bool on_flow_report(BroadcastFlowReportArgs) const;
|
||||||
bool on_media_changed(BroadcastMediaChangedArgs) const;
|
bool on_media_changed(BroadcastMediaChangedArgs) const;
|
||||||
bool on_player_proxy_failed(BroadcastPlayerProxyFailedArgs) const;
|
bool on_player_proxy_failed(BroadcastPlayerProxyFailedArgs) const;
|
||||||
|
bool on_get_rtsp_realm(BroadcastOnGetRtspRealmArgs) const;
|
||||||
|
bool on_rtsp_auth(BroadcastOnRtspAuthArgs) const;
|
||||||
|
bool on_stream_not_found(BroadcastNotFoundStreamArgs) const;
|
||||||
|
bool on_record_mp4(BroadcastRecordMP4Args) const;
|
||||||
|
bool on_record_ts(BroadcastRecordTsArgs) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PythonInvoker();
|
PythonInvoker();
|
||||||
@ -41,19 +47,31 @@ private:
|
|||||||
py::module _module;
|
py::module _module;
|
||||||
|
|
||||||
// 程序退出
|
// 程序退出
|
||||||
py::object _on_exit;
|
py::function _on_exit;
|
||||||
// 推流鉴权
|
// 推流鉴权
|
||||||
py::object _on_publish;
|
py::function _on_publish;
|
||||||
// 播放鉴权
|
// 播放鉴权
|
||||||
py::object _on_play;
|
py::function _on_play;
|
||||||
// 流量汇报接口
|
// 流量汇报接口
|
||||||
py::object _on_flow_report;
|
py::function _on_flow_report;
|
||||||
// 配置文件热更新回调
|
// 配置文件热更新回调
|
||||||
py::object _on_reload_config;
|
py::function _on_reload_config;
|
||||||
// 媒体注册注销
|
// 媒体注册注销
|
||||||
py::object _on_media_changed;
|
py::function _on_media_changed;
|
||||||
// 拉流代理失败
|
// 拉流代理失败
|
||||||
py::object _on_player_proxy_failed;
|
py::function _on_player_proxy_failed;
|
||||||
|
// rtsp播放是否开启专属鉴权
|
||||||
|
py::function _on_get_rtsp_realm;
|
||||||
|
// rtsp播放或推流鉴权回调
|
||||||
|
py::function _on_rtsp_auth;
|
||||||
|
// 播放一个不存在的流时触发
|
||||||
|
py::function _on_stream_not_found;
|
||||||
|
// 生成mp4录制文件回调
|
||||||
|
py::function _on_record_mp4;
|
||||||
|
// 生成hls ts/fmp4切片文件回调
|
||||||
|
py::function _on_record_ts;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mediakit
|
} // namespace mediakit
|
||||||
|
|||||||
@ -51,9 +51,9 @@ void RtpSender::startSend(const MediaSourceEvent &sender, const MediaSourceEvent
|
|||||||
// Do not recreate the object when reconnecting
|
// Do not recreate the object when reconnecting
|
||||||
auto lam = [this](std::shared_ptr<List<Buffer::Ptr>> list) { onFlushRtpList(std::move(list)); };
|
auto lam = [this](std::shared_ptr<List<Buffer::Ptr>> list) { onFlushRtpList(std::move(list)); };
|
||||||
switch (args.data_type) {
|
switch (args.data_type) {
|
||||||
case MediaSourceEvent::SendRtpArgs::kRtpPS: _interface = std::make_shared<RtpCachePS>(lam, atoi(args.ssrc.data()), args.pt, true); break;
|
case MediaSourceEvent::SendRtpArgs::kRtpPS: _interface = std::make_shared<RtpCachePS>(lam, stoll(args.ssrc), args.pt, true); break;
|
||||||
case MediaSourceEvent::SendRtpArgs::kRtpTS: _interface = std::make_shared<RtpCachePS>(lam, atoi(args.ssrc.data()), args.pt, false); break;
|
case MediaSourceEvent::SendRtpArgs::kRtpTS: _interface = std::make_shared<RtpCachePS>(lam, stoll(args.ssrc), args.pt, false); break;
|
||||||
case MediaSourceEvent::SendRtpArgs::kRtpES: _interface = std::make_shared<RtpCacheRaw>(lam, atoi(args.ssrc.data()), args.pt, args.only_audio); break;
|
case MediaSourceEvent::SendRtpArgs::kRtpES: _interface = std::make_shared<RtpCacheRaw>(lam, stoll(args.ssrc), args.pt, args.only_audio); break;
|
||||||
default: CHECK(0, "invalid rtp type: " + to_string(args.data_type)); break;
|
default: CHECK(0, "invalid rtp type: " + to_string(args.data_type)); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,7 +386,7 @@ void RtpSender::onSendRtpUdp(const toolkit::Buffer::Ptr &buf, bool check) {
|
|||||||
_rtcp_send_ticker.resetTime();
|
_rtcp_send_ticker.resetTime();
|
||||||
// rtcp ssrc为rtp ssrc + 1 [AUTO-TRANSLATED:318fada3]
|
// rtcp ssrc为rtp ssrc + 1 [AUTO-TRANSLATED:318fada3]
|
||||||
// rtcp ssrc is rtp ssrc + 1
|
// rtcp ssrc is rtp ssrc + 1
|
||||||
auto sr = _rtcp_context->createRtcpSR(atoi(_args.ssrc.data()) + 1);
|
auto sr = _rtcp_context->createRtcpSR(stoll(_args.ssrc) + 1);
|
||||||
// send sender report rtcp
|
// send sender report rtcp
|
||||||
_socket_rtcp->send(sr);
|
_socket_rtcp->send(sr);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user