mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 10:40:05 +08:00
整理webrtc c接口
This commit is contained in:
parent
426d76f05c
commit
a916760ac3
@ -28,7 +28,7 @@ file(GLOB API_SRC_LIST
|
|||||||
source/*.cpp
|
source/*.cpp
|
||||||
source/*.h)
|
source/*.h)
|
||||||
|
|
||||||
set(LINK_LIBRARIES ${MK_LINK_LIBRARIES} jsoncpp)
|
set(LINK_LIBRARIES ${MK_LINK_LIBRARIES})
|
||||||
|
|
||||||
if(IOS)
|
if(IOS)
|
||||||
add_library(mk_api STATIC ${API_SRC_LIST})
|
add_library(mk_api STATIC ${API_SRC_LIST})
|
||||||
@ -62,7 +62,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
|||||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Android")
|
elseif(CMAKE_SYSTEM_NAME MATCHES "Android")
|
||||||
target_link_libraries(mk_api log -Wl,--start-group ${LINK_LIBRARIES} -Wl,--end-group)
|
target_link_libraries(mk_api log -Wl,--start-group ${LINK_LIBRARIES} -Wl,--end-group)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(mk_api jsoncpp ${LINK_LIBRARIES})
|
target_link_libraries(mk_api ${LINK_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
generate_export_header(mk_api
|
generate_export_header(mk_api
|
||||||
|
@ -167,6 +167,20 @@ 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);
|
API_EXPORT uint16_t API_CALL mk_rtc_server_start(uint16_t port);
|
||||||
|
|
||||||
|
//获取webrtc answer sdp回调函数
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建srt服务器
|
* 创建srt服务器
|
||||||
* @param port srt监听端口
|
* @param port srt监听端口
|
||||||
|
@ -82,8 +82,6 @@ API_EXPORT uint16_t API_CALL mk_media_info_get_port(const mk_media_info ctx);
|
|||||||
typedef void* mk_media_source;
|
typedef void* mk_media_source;
|
||||||
//查找MediaSource的回调函数
|
//查找MediaSource的回调函数
|
||||||
typedef void(API_CALL *on_mk_media_source_find_cb)(void *user_data, const mk_media_source ctx);
|
typedef void(API_CALL *on_mk_media_source_find_cb)(void *user_data, const mk_media_source ctx);
|
||||||
//生成AnswerSdp回调函数
|
|
||||||
typedef void(API_CALL *on_mk_media_source_answersdp_cb)(void *user_data, const mk_media_source ctx, const char *answer, const char *err);
|
|
||||||
|
|
||||||
//MediaSource::getSchema()
|
//MediaSource::getSchema()
|
||||||
API_EXPORT const char* API_CALL mk_media_source_get_schema(const mk_media_source ctx);
|
API_EXPORT const char* API_CALL mk_media_source_get_schema(const mk_media_source ctx);
|
||||||
@ -136,9 +134,6 @@ API_EXPORT void API_CALL mk_media_source_find(const char *schema,
|
|||||||
//MediaSource::for_each_media()
|
//MediaSource::for_each_media()
|
||||||
API_EXPORT void API_CALL mk_media_source_for_each(void *user_data, on_mk_media_source_find_cb cb, const char *schema,
|
API_EXPORT void API_CALL mk_media_source_for_each(void *user_data, on_mk_media_source_find_cb cb, const char *schema,
|
||||||
const char *vhost, const char *app, const char *stream);
|
const char *vhost, const char *app, const char *stream);
|
||||||
//MediaSource::find() + WebRtcPlayer::create + getOffer
|
|
||||||
API_EXPORT void API_CALL mk_media_source_answersdp(void *user_data, on_mk_media_source_answersdp_cb cb, const char *offer,
|
|
||||||
const char *schema, const char *vhost, const char *app, const char *stream, int from_mp4);
|
|
||||||
|
|
||||||
///////////////////////////////////////////HttpBody/////////////////////////////////////////////
|
///////////////////////////////////////////HttpBody/////////////////////////////////////////////
|
||||||
//HttpBody对象的C映射
|
//HttpBody对象的C映射
|
||||||
@ -182,14 +177,6 @@ API_EXPORT void API_CALL mk_http_response_invoker_do(const mk_http_response_invo
|
|||||||
int response_code,
|
int response_code,
|
||||||
const char **response_header,
|
const char **response_header,
|
||||||
const mk_http_body response_body);
|
const mk_http_body response_body);
|
||||||
/**
|
|
||||||
* HttpSession::HttpResponseInvoker(const string &codeOut, const StrCaseMap &headerOut, const HttpBody::Ptr &body);
|
|
||||||
Parser();
|
|
||||||
SockInfo();
|
|
||||||
*/
|
|
||||||
API_EXPORT void API_CALL mk_webrtc_http_response_invoker_do( const mk_http_response_invoker invoker,
|
|
||||||
const mk_parser parser,
|
|
||||||
const mk_sock_info sender);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HttpSession::HttpResponseInvoker(const string &codeOut, const StrCaseMap &headerOut, const string &body);
|
* HttpSession::HttpResponseInvoker(const string &codeOut, const StrCaseMap &headerOut, const string &body);
|
||||||
|
@ -261,11 +261,48 @@ API_EXPORT uint16_t API_CALL mk_rtc_server_start(uint16_t port) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
WarnL << "未启用该功能!";
|
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WebRtcArgsUrl : public mediakit::WebRtcArgs {
|
||||||
|
public:
|
||||||
|
WebRtcArgsUrl(std::string url) { _url = std::move(url); }
|
||||||
|
~WebRtcArgsUrl() = default;
|
||||||
|
|
||||||
|
toolkit::variant operator[](const std::string &key) const override {
|
||||||
|
if (key == "url") {
|
||||||
|
return _url;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _url;
|
||||||
|
};
|
||||||
|
|
||||||
|
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) {
|
||||||
|
#ifdef ENABLE_WEBRTC
|
||||||
|
assert(type && offer && url && cb);
|
||||||
|
auto session = std::make_shared<HttpSession>(Socket::createSocket());
|
||||||
|
std::string offer_str = offer;
|
||||||
|
WebRtcPluginManager::Instance().getAnswerSdp(*session, type, WebRtcArgsUrl(url),
|
||||||
|
[offer_str, session, user_data, cb](const WebRtcInterface &exchanger) mutable {
|
||||||
|
std::string sdp_answer;
|
||||||
|
try {
|
||||||
|
sdp_answer = const_cast<WebRtcInterface &>(exchanger).getAnswerSdp(offer_str);
|
||||||
|
cb(user_data, sdp_answer.data(), nullptr);
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
cb(user_data, nullptr, ex.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
WarnL << "未启用webrtc功能, 编译时请开启ENABLE_WEBRTC";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORT uint16_t API_CALL mk_srt_server_start(uint16_t port) {
|
API_EXPORT uint16_t API_CALL mk_srt_server_start(uint16_t port) {
|
||||||
#ifdef ENABLE_SRT
|
#ifdef ENABLE_SRT
|
||||||
try {
|
try {
|
||||||
|
@ -18,11 +18,6 @@
|
|||||||
#include "Http/HttpClient.h"
|
#include "Http/HttpClient.h"
|
||||||
#include "Rtsp/RtspSession.h"
|
#include "Rtsp/RtspSession.h"
|
||||||
|
|
||||||
#ifdef ENABLE_WEBRTC
|
|
||||||
#include "jsoncpp/json.h"
|
|
||||||
#include "mk_webrtc_private.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
using namespace mediakit;
|
using namespace mediakit;
|
||||||
|
|
||||||
@ -257,25 +252,6 @@ API_EXPORT void API_CALL mk_media_source_for_each(void *user_data, on_mk_media_s
|
|||||||
}, schema ? schema : "", vhost ? vhost : "", app ? app : "", stream ? stream : "");
|
}, schema ? schema : "", vhost ? vhost : "", app ? app : "", stream ? stream : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_media_source_answersdp(void *user_data, on_mk_media_source_answersdp_cb cb, const char *offer,
|
|
||||||
const char *schema, const char *vhost, const char *app, const char *stream, int from_mp4) {
|
|
||||||
#ifdef ENABLE_WEBRTC
|
|
||||||
assert(offer && schema && vhost && app && stream && cb);
|
|
||||||
auto srcfound = MediaSource::find(schema, vhost, app, stream, from_mp4);
|
|
||||||
mediakit::MediaInfo info;
|
|
||||||
info._schema = RTC_SCHEMA;
|
|
||||||
info._host = vhost;
|
|
||||||
info._app = app;
|
|
||||||
info._streamid = stream;
|
|
||||||
try {
|
|
||||||
auto rtc = WebRtcPlayer::create(EventPollerPool::Instance().getPoller(), std::dynamic_pointer_cast<RtspMediaSource>(srcfound), info);
|
|
||||||
cb(user_data, srcfound.get(), rtc->getAnswerSdp(offer).c_str(), "");
|
|
||||||
} catch (std::exception &ex) {
|
|
||||||
cb(user_data, nullptr, nullptr, ex.what());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////HttpBody/////////////////////////////////////////////
|
///////////////////////////////////////////HttpBody/////////////////////////////////////////////
|
||||||
API_EXPORT mk_http_body API_CALL mk_http_body_from_string(const char *str, size_t len){
|
API_EXPORT mk_http_body API_CALL mk_http_body_from_string(const char *str, size_t len){
|
||||||
assert(str);
|
assert(str);
|
||||||
@ -349,53 +325,6 @@ API_EXPORT void API_CALL mk_http_response_invoker_do(const mk_http_response_invo
|
|||||||
(*invoker)(response_code,header,*body);
|
(*invoker)(response_code,header,*body);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_webrtc_http_response_invoker_do(const mk_http_response_invoker ctx_invoker,
|
|
||||||
const mk_parser ctx_parser,
|
|
||||||
const mk_sock_info ctx_sock ) {
|
|
||||||
assert(ctx_parser && ctx_invoker && ctx_sock);
|
|
||||||
#ifdef ENABLE_WEBRTC
|
|
||||||
static auto webrtc_cb = [](API_ARGS_STRING_ASYNC){
|
|
||||||
CHECK_ARGS("type");
|
|
||||||
auto type = allArgs["type"];
|
|
||||||
auto offer = allArgs.getArgs();
|
|
||||||
CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty");
|
|
||||||
|
|
||||||
WebRtcPluginManager::Instance().getAnswerSdp(
|
|
||||||
*(static_cast<Session *>(&sender)), type, offer, WebRtcArgsImp(allArgs, sender.getIdentifier()),
|
|
||||||
[invoker, val, offer, headerOut](const WebRtcInterface &exchanger) mutable {
|
|
||||||
//设置返回类型
|
|
||||||
headerOut["Content-Type"] = HttpFileManager::getContentType(".json");
|
|
||||||
//设置跨域
|
|
||||||
headerOut["Access-Control-Allow-Origin"] = "*";
|
|
||||||
|
|
||||||
try {
|
|
||||||
val["sdp"] = const_cast<WebRtcInterface &>(exchanger).getAnswerSdp(offer);
|
|
||||||
val["id"] = exchanger.getIdentifier();
|
|
||||||
val["type"] = "answer";
|
|
||||||
invoker(200, headerOut, val.toStyledString());
|
|
||||||
} catch (std::exception &ex) {
|
|
||||||
val["code"] = API::Exception;
|
|
||||||
val["msg"] = ex.what();
|
|
||||||
invoker(200, headerOut, val.toStyledString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Parser *parser = (Parser *)ctx_parser;
|
|
||||||
HttpSession::HttpResponseInvoker *invoker = (HttpSession::HttpResponseInvoker *)ctx_invoker;
|
|
||||||
SockInfo* sender = (SockInfo*)ctx_sock;
|
|
||||||
|
|
||||||
GET_CONFIG(std::string, charSet, Http::kCharSet);
|
|
||||||
HttpSession::KeyValue headerOut;
|
|
||||||
headerOut["Content-Type"] = std::string("application/json; charset=") + charSet;
|
|
||||||
|
|
||||||
Json::Value val;
|
|
||||||
val["code"] = API::Success;
|
|
||||||
|
|
||||||
webrtc_cb(*sender, headerOut, HttpAllArgs<std::string>(*parser, (std::string &)parser->Content()), val, *invoker);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
API_EXPORT mk_http_response_invoker API_CALL mk_http_response_invoker_clone(const mk_http_response_invoker ctx){
|
API_EXPORT mk_http_response_invoker API_CALL mk_http_response_invoker_clone(const mk_http_response_invoker ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
HttpSession::HttpResponseInvoker *invoker = (HttpSession::HttpResponseInvoker *)ctx;
|
HttpSession::HttpResponseInvoker *invoker = (HttpSession::HttpResponseInvoker *)ctx;
|
||||||
|
@ -1,228 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by MIT 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef ENABLE_WEBRTC
|
|
||||||
#ifndef MK_WEBRTC_API_H
|
|
||||||
#define MK_WEBRTC_API_H
|
|
||||||
|
|
||||||
#include "Common/Parser.h"
|
|
||||||
#include "Http/HttpSession.h"
|
|
||||||
#include "Network/Socket.h"
|
|
||||||
#include "jsoncpp/json.h"
|
|
||||||
#include <functional>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "../webrtc/WebRtcEchoTest.h"
|
|
||||||
#include "../webrtc/WebRtcPlayer.h"
|
|
||||||
#include "../webrtc/WebRtcPusher.h"
|
|
||||||
#include "../webrtc/WebRtcTransport.h"
|
|
||||||
|
|
||||||
using namespace mediakit;
|
|
||||||
|
|
||||||
namespace API {
|
|
||||||
typedef enum {
|
|
||||||
NotFound = -500, //未找到
|
|
||||||
Exception = -400, //代码抛异常
|
|
||||||
InvalidArgs = -300, //参数不合法
|
|
||||||
SqlFailed = -200, // sql执行失败
|
|
||||||
AuthFailed = -100, //鉴权失败
|
|
||||||
OtherFailed = -1, //业务代码执行失败,
|
|
||||||
Success = 0 //执行成功
|
|
||||||
} ApiErr;
|
|
||||||
} // namespace API
|
|
||||||
|
|
||||||
class ApiRetException : public std::runtime_error {
|
|
||||||
public:
|
|
||||||
ApiRetException(const char *str = "success", int code = API::Success)
|
|
||||||
: runtime_error(str) {
|
|
||||||
_code = code;
|
|
||||||
}
|
|
||||||
~ApiRetException() = default;
|
|
||||||
int code() { return _code; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
int _code;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AuthException : public ApiRetException {
|
|
||||||
public:
|
|
||||||
AuthException(const char *str)
|
|
||||||
: ApiRetException(str, API::AuthFailed) {}
|
|
||||||
~AuthException() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class InvalidArgsException : public ApiRetException {
|
|
||||||
public:
|
|
||||||
InvalidArgsException(const char *str)
|
|
||||||
: ApiRetException(str, API::InvalidArgs) {}
|
|
||||||
~InvalidArgsException() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SuccessException : public ApiRetException {
|
|
||||||
public:
|
|
||||||
SuccessException()
|
|
||||||
: ApiRetException("success", API::Success) {}
|
|
||||||
~SuccessException() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ApiArgsType = std::map<std::string, std::string, mediakit::StrCaseCompare>;
|
|
||||||
template <typename Args, typename First>
|
|
||||||
std::string getValue(Args &args, const First &first) {
|
|
||||||
return args[first];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename First>
|
|
||||||
std::string getValue(Json::Value &args, const First &first) {
|
|
||||||
return args[first].asString();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename First>
|
|
||||||
std::string getValue(std::string &args, const First &first) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename First>
|
|
||||||
std::string getValue(const mediakit::Parser &parser, const First &first) {
|
|
||||||
auto ret = parser.getUrlArgs()[first];
|
|
||||||
if (!ret.empty()) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return parser.getHeader()[first];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename First>
|
|
||||||
std::string getValue(mediakit::Parser &parser, const First &first) {
|
|
||||||
return getValue((const mediakit::Parser &)parser, first);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Args, typename First>
|
|
||||||
std::string getValue(const mediakit::Parser &parser, Args &args, const First &first) {
|
|
||||||
auto ret = getValue(args, first);
|
|
||||||
if (!ret.empty()) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return getValue(parser, first);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Args>
|
|
||||||
class HttpAllArgs {
|
|
||||||
public:
|
|
||||||
HttpAllArgs(const mediakit::Parser &parser, Args &args) {
|
|
||||||
_get_args = [&args]() { return (void *)&args; };
|
|
||||||
_get_parser = [&parser]() -> const mediakit::Parser & { return parser; };
|
|
||||||
_get_value
|
|
||||||
= [](HttpAllArgs &that, const std::string &key) { return getValue(that.getParser(), that.getArgs(), key); };
|
|
||||||
_clone = [&](HttpAllArgs &that) {
|
|
||||||
that._get_args = [args]() { return (void *)&args; };
|
|
||||||
that._get_parser = [parser]() -> const mediakit::Parser & { return parser; };
|
|
||||||
that._get_value = [](HttpAllArgs &that, const std::string &key) {
|
|
||||||
return getValue(that.getParser(), that.getArgs(), key);
|
|
||||||
};
|
|
||||||
that._cache_able = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpAllArgs(const HttpAllArgs &that) {
|
|
||||||
if (that._cache_able) {
|
|
||||||
_get_args = that._get_args;
|
|
||||||
_get_parser = that._get_parser;
|
|
||||||
_get_value = that._get_value;
|
|
||||||
_cache_able = true;
|
|
||||||
} else {
|
|
||||||
that._clone(*this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~HttpAllArgs() = default;
|
|
||||||
|
|
||||||
template <typename Key>
|
|
||||||
toolkit::variant operator[](const Key &key) const {
|
|
||||||
return (toolkit::variant)_get_value(*(HttpAllArgs *)this, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mediakit::Parser &getParser() const { return _get_parser(); }
|
|
||||||
|
|
||||||
Args &getArgs() { return *((Args *)_get_args()); }
|
|
||||||
|
|
||||||
const Args &getArgs() const { return *((Args *)_get_args()); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool _cache_able = false;
|
|
||||||
std::function<void *()> _get_args;
|
|
||||||
std::function<const mediakit::Parser &()> _get_parser;
|
|
||||||
std::function<std::string(HttpAllArgs &that, const std::string &key)> _get_value;
|
|
||||||
std::function<void(HttpAllArgs &that)> _clone;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define API_ARGS_MAP \
|
|
||||||
toolkit::SockInfo &sender, mediakit::HttpSession::KeyValue &headerOut, const HttpAllArgs<ApiArgsType> &allArgs, \
|
|
||||||
Json::Value &val
|
|
||||||
#define API_ARGS_MAP_ASYNC API_ARGS_MAP, const mediakit::HttpSession::HttpResponseInvoker &invoker
|
|
||||||
#define API_ARGS_JSON \
|
|
||||||
toolkit::SockInfo &sender, mediakit::HttpSession::KeyValue &headerOut, const HttpAllArgs<Json::Value> &allArgs, \
|
|
||||||
Json::Value &val
|
|
||||||
#define API_ARGS_JSON_ASYNC API_ARGS_JSON, const mediakit::HttpSession::HttpResponseInvoker &invoker
|
|
||||||
#define API_ARGS_STRING \
|
|
||||||
toolkit::SockInfo &sender, mediakit::HttpSession::KeyValue &headerOut, const HttpAllArgs<std::string> &allArgs, \
|
|
||||||
Json::Value &val
|
|
||||||
#define API_ARGS_STRING_ASYNC API_ARGS_STRING, const mediakit::HttpSession::HttpResponseInvoker &invoker
|
|
||||||
#define API_ARGS_VALUE sender, headerOut, allArgs, val
|
|
||||||
|
|
||||||
//注册http请求参数是http原始请求信息的异步回复的http api
|
|
||||||
void api_regist(const std::string &api_path, const std::function<void(API_ARGS_STRING_ASYNC)> &func);
|
|
||||||
|
|
||||||
template <typename Args, typename First>
|
|
||||||
bool checkArgs(Args &args, const First &first) {
|
|
||||||
return !args[first].empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Args, typename First, typename... KeyTypes>
|
|
||||||
bool checkArgs(Args &args, const First &first, const KeyTypes &...keys) {
|
|
||||||
return checkArgs(args, first) && checkArgs(args, keys...);
|
|
||||||
}
|
|
||||||
|
|
||||||
//检查http url中或body中或http header参数是否为空的宏
|
|
||||||
#define CHECK_ARGS(...) \
|
|
||||||
if (!checkArgs(allArgs, ##__VA_ARGS__)) { \
|
|
||||||
throw InvalidArgsException("缺少必要参数:" #__VA_ARGS__); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_WEBRTC
|
|
||||||
class WebRtcArgsImp : public WebRtcArgs {
|
|
||||||
public:
|
|
||||||
WebRtcArgsImp(const HttpAllArgs<std::string> &args, std::string session_id)
|
|
||||||
: _args(args)
|
|
||||||
, _session_id(std::move(session_id)) {}
|
|
||||||
~WebRtcArgsImp() override = default;
|
|
||||||
|
|
||||||
variant operator[](const std::string &key) const override {
|
|
||||||
if (key == "url") {
|
|
||||||
return getUrl();
|
|
||||||
}
|
|
||||||
return _args[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string getUrl() const {
|
|
||||||
auto &allArgs = _args;
|
|
||||||
CHECK_ARGS("app", "stream");
|
|
||||||
|
|
||||||
return StrPrinter << RTC_SCHEMA << "://" << _args["Host"] << "/" << _args["app"] << "/" << _args["stream"]
|
|
||||||
<< "?" << _args.getParser().Params() + "&session=" + _session_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
HttpAllArgs<std::string> _args;
|
|
||||||
std::string _session_id;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // MK_WEBRTC_API_H
|
|
||||||
#endif // ENABLE_WEBRTC
|
|
@ -122,6 +122,72 @@ void API_CALL on_mk_media_no_reader(const mk_media_source sender) {
|
|||||||
mk_media_source_get_stream(sender));
|
mk_media_source_get_stream(sender));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//按照json转义规则转义webrtc answer sdp
|
||||||
|
static char *escape_string(const char *ptr){
|
||||||
|
char *escaped = malloc(2 * strlen(ptr));
|
||||||
|
char *ptr_escaped = escaped;
|
||||||
|
while (1) {
|
||||||
|
switch (*ptr) {
|
||||||
|
case '\r': {
|
||||||
|
*(ptr_escaped++) = '\\';
|
||||||
|
*(ptr_escaped++) = 'r';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '\n': {
|
||||||
|
*(ptr_escaped++) = '\\';
|
||||||
|
*(ptr_escaped++) = 'n';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '\t': {
|
||||||
|
*(ptr_escaped++) = '\\';
|
||||||
|
*(ptr_escaped++) = 't';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
*(ptr_escaped++) = *ptr;
|
||||||
|
if (!*ptr) {
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_mk_webrtc_get_answer_sdp_func(void *user_data, const char *answer, const char *err) {
|
||||||
|
const char *response_header[] = { "Content-Type", "application/json", "Access-Control-Allow-Origin", "*" , NULL};
|
||||||
|
if (answer) {
|
||||||
|
answer = escape_string(answer);
|
||||||
|
}
|
||||||
|
size_t len = answer ? 2 * strlen(answer) : 1024;
|
||||||
|
char *response_content = (char *)malloc(len);
|
||||||
|
|
||||||
|
if (answer) {
|
||||||
|
snprintf(response_content, len,
|
||||||
|
"{"
|
||||||
|
"\"sdp\":\"%s\","
|
||||||
|
"\"type\":\"answer\","
|
||||||
|
"\"code\":0"
|
||||||
|
"}",
|
||||||
|
answer);
|
||||||
|
} else {
|
||||||
|
snprintf(response_content, len,
|
||||||
|
"{"
|
||||||
|
"\"msg\":\"%s\","
|
||||||
|
"\"code\":-1"
|
||||||
|
"}",
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
|
||||||
|
mk_http_response_invoker_do_string(user_data, 200, response_header, response_content);
|
||||||
|
mk_http_response_invoker_clone_release(user_data);
|
||||||
|
free(response_content);
|
||||||
|
if (answer) {
|
||||||
|
free(answer);
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 收到http api请求广播(包括GET/POST)
|
* 收到http api请求广播(包括GET/POST)
|
||||||
* @param parser http请求内容对象
|
* @param parser http请求内容对象
|
||||||
@ -156,7 +222,7 @@ void API_CALL on_mk_http_request(const mk_parser parser,
|
|||||||
*consumed = 1;
|
*consumed = 1;
|
||||||
|
|
||||||
//拦截api: /api/test
|
//拦截api: /api/test
|
||||||
if(strcmp(url,"/api/test") == 0) {
|
if (strcmp(url, "/api/test") == 0) {
|
||||||
const char *response_header[] = { "Content-Type", "text/html", NULL };
|
const char *response_header[] = { "Content-Type", "text/html", NULL };
|
||||||
const char *content = "<html>"
|
const char *content = "<html>"
|
||||||
"<head>"
|
"<head>"
|
||||||
@ -171,12 +237,16 @@ void API_CALL on_mk_http_request(const mk_parser parser,
|
|||||||
mk_http_body body = mk_http_body_from_string(content, 0);
|
mk_http_body body = mk_http_body_from_string(content, 0);
|
||||||
mk_http_response_invoker_do(invoker, 200, response_header, body);
|
mk_http_response_invoker_do(invoker, 200, response_header, body);
|
||||||
mk_http_body_release(body);
|
mk_http_body_release(body);
|
||||||
}
|
} else if (strcmp(url, "/index/api/webrtc") == 0) {
|
||||||
//拦截api: /index/api/webrtc
|
//拦截api: /index/api/webrtc
|
||||||
else if(strcmp(url,"/index/api/webrtc") == 0){
|
char rtc_url[1024];
|
||||||
mk_webrtc_http_response_invoker_do(invoker,parser,sender);
|
snprintf(rtc_url, sizeof(rtc_url), "rtc://%s/%s/%s?%s", mk_parser_get_header(parser, "Host"),
|
||||||
}
|
mk_parser_get_url_param(parser, "app"), mk_parser_get_url_param(parser, "stream"),
|
||||||
else{
|
mk_parser_get_url_params(parser));
|
||||||
|
|
||||||
|
mk_webrtc_get_answer_sdp(mk_http_response_invoker_clone(invoker), on_mk_webrtc_get_answer_sdp_func,
|
||||||
|
mk_parser_get_url_param(parser, "type"), mk_parser_get_content(parser, NULL), rtc_url);
|
||||||
|
} else {
|
||||||
*consumed = 0;
|
*consumed = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1578,9 +1578,9 @@ void installWebApi() {
|
|||||||
auto offer = allArgs.getArgs();
|
auto offer = allArgs.getArgs();
|
||||||
CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty");
|
CHECK(!offer.empty(), "http body(webrtc offer sdp) is empty");
|
||||||
|
|
||||||
WebRtcPluginManager::Instance().getAnswerSdp(
|
WebRtcPluginManager::Instance().getAnswerSdp(*(static_cast<Session *>(&sender)), type,
|
||||||
*(static_cast<Session *>(&sender)), type, offer, WebRtcArgsImp(allArgs, sender.getIdentifier()),
|
WebRtcArgsImp(allArgs, sender.getIdentifier()),
|
||||||
[invoker, val, offer, headerOut](const WebRtcInterface &exchanger) mutable {
|
[invoker, val, offer, headerOut](const WebRtcInterface &exchanger) mutable {
|
||||||
//设置返回类型
|
//设置返回类型
|
||||||
headerOut["Content-Type"] = HttpFileManager::getContentType(".json");
|
headerOut["Content-Type"] = HttpFileManager::getContentType(".json");
|
||||||
//设置跨域
|
//设置跨域
|
||||||
|
@ -1114,27 +1114,23 @@ void WebRtcPluginManager::registerPlugin(const string &type, Plugin cb) {
|
|||||||
_map_creator[type] = std::move(cb);
|
_map_creator[type] = std::move(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRtcPluginManager::getAnswerSdp(
|
void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const WebRtcArgs &args, const onCreateRtc &cb) {
|
||||||
Session &sender, const string &type, const string &offer, const WebRtcArgs &args, const onCreateRtc &cb) {
|
|
||||||
lock_guard<mutex> lck(_mtx_creator);
|
lock_guard<mutex> lck(_mtx_creator);
|
||||||
auto it = _map_creator.find(type);
|
auto it = _map_creator.find(type);
|
||||||
if (it == _map_creator.end()) {
|
if (it == _map_creator.end()) {
|
||||||
cb(WebRtcException(SockException(Err_other, "the type can not supported")));
|
cb(WebRtcException(SockException(Err_other, "the type can not supported")));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
it->second(sender, offer, args, cb);
|
it->second(sender, args, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void echo_plugin(
|
void echo_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
|
||||||
Session &sender, const string &offer, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
|
|
||||||
cb(*WebRtcEchoTest::create(EventPollerPool::Instance().getPoller()));
|
cb(*WebRtcEchoTest::create(EventPollerPool::Instance().getPoller()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_plugin(
|
void push_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
|
||||||
Session &sender, const string &offer_sdp, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
|
|
||||||
MediaInfo info(args["url"]);
|
MediaInfo info(args["url"]);
|
||||||
Broadcast::PublishAuthInvoker invoker = [cb, offer_sdp,
|
Broadcast::PublishAuthInvoker invoker = [cb, info](const string &err, const ProtocolOption &option) mutable {
|
||||||
info](const string &err, const ProtocolOption &option) mutable {
|
|
||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
cb(WebRtcException(SockException(Err_other, err)));
|
cb(WebRtcException(SockException(Err_other, err)));
|
||||||
return;
|
return;
|
||||||
@ -1173,26 +1169,23 @@ void push_plugin(
|
|||||||
push_src_ownership = push_src->getOwnership();
|
push_src_ownership = push_src->getOwnership();
|
||||||
push_src->setProtocolOption(option);
|
push_src->setProtocolOption(option);
|
||||||
}
|
}
|
||||||
auto rtc
|
auto rtc = WebRtcPusher::create(EventPollerPool::Instance().getPoller(), push_src, push_src_ownership, info, option);
|
||||||
= WebRtcPusher::create(EventPollerPool::Instance().getPoller(), push_src, push_src_ownership, info, option);
|
|
||||||
push_src->setListener(rtc);
|
push_src->setListener(rtc);
|
||||||
cb(*rtc);
|
cb(*rtc);
|
||||||
};
|
};
|
||||||
|
|
||||||
// rtsp推流需要鉴权
|
// rtsp推流需要鉴权
|
||||||
auto flag = NoticeCenter::Instance().emitEvent(
|
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, MediaOriginType::rtc_push, info, invoker, static_cast<SockInfo &>(sender));
|
||||||
Broadcast::kBroadcastMediaPublish, MediaOriginType::rtc_push, info, invoker, static_cast<SockInfo &>(sender));
|
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
// 该事件无人监听,默认不鉴权
|
// 该事件无人监听,默认不鉴权
|
||||||
invoker("", ProtocolOption());
|
invoker("", ProtocolOption());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_plugin(
|
void play_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
|
||||||
Session &sender, const string &offer_sdp, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
|
|
||||||
MediaInfo info(args["url"]);
|
MediaInfo info(args["url"]);
|
||||||
auto session_ptr = sender.shared_from_this();
|
auto session_ptr = sender.shared_from_this();
|
||||||
Broadcast::AuthInvoker invoker = [cb, offer_sdp, info, session_ptr](const string &err) mutable {
|
Broadcast::AuthInvoker invoker = [cb, info, session_ptr](const string &err) mutable {
|
||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
cb(WebRtcException(SockException(Err_other, err)));
|
cb(WebRtcException(SockException(Err_other, err)));
|
||||||
return;
|
return;
|
||||||
@ -1214,8 +1207,7 @@ void play_plugin(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 广播通用播放url鉴权事件
|
// 广播通用播放url鉴权事件
|
||||||
auto flag = NoticeCenter::Instance().emitEvent(
|
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, info, invoker, static_cast<SockInfo &>(sender));
|
||||||
Broadcast::kBroadcastMediaPlayed, info, invoker, static_cast<SockInfo &>(sender));
|
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
// 该事件无人监听,默认不鉴权
|
// 该事件无人监听,默认不鉴权
|
||||||
invoker("");
|
invoker("");
|
||||||
|
@ -332,12 +332,12 @@ public:
|
|||||||
class WebRtcPluginManager {
|
class WebRtcPluginManager {
|
||||||
public:
|
public:
|
||||||
using onCreateRtc = std::function<void(const WebRtcInterface &rtc)>;
|
using onCreateRtc = std::function<void(const WebRtcInterface &rtc)>;
|
||||||
using Plugin = std::function<void(Session &sender, const std::string &offer, const WebRtcArgs &args, const onCreateRtc &cb)>;
|
using Plugin = std::function<void(Session &sender, const WebRtcArgs &args, const onCreateRtc &cb)>;
|
||||||
|
|
||||||
static WebRtcPluginManager &Instance();
|
static WebRtcPluginManager &Instance();
|
||||||
|
|
||||||
void registerPlugin(const std::string &type, Plugin cb);
|
void registerPlugin(const std::string &type, Plugin cb);
|
||||||
void getAnswerSdp(Session &sender, const std::string &type, const std::string &offer, const WebRtcArgs &args, const onCreateRtc &cb);
|
void getAnswerSdp(Session &sender, const std::string &type, const WebRtcArgs &args, const onCreateRtc &cb);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WebRtcPluginManager() = default;
|
WebRtcPluginManager() = default;
|
||||||
|
Loading…
Reference in New Issue
Block a user