mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 10:40:05 +08:00
add MediaTuple
This commit is contained in:
parent
f4ee607feb
commit
0232caf068
@ -61,19 +61,19 @@ API_EXPORT const char* API_CALL mk_parser_get_content(const mk_parser ctx, size_
|
|||||||
///////////////////////////////////////////MediaInfo/////////////////////////////////////////////
|
///////////////////////////////////////////MediaInfo/////////////////////////////////////////////
|
||||||
//MediaInfo对象的C映射
|
//MediaInfo对象的C映射
|
||||||
typedef struct mk_media_info_t *mk_media_info;
|
typedef struct mk_media_info_t *mk_media_info;
|
||||||
//MediaInfo::_param_strs
|
//MediaInfo::param_strs
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_params(const mk_media_info ctx);
|
API_EXPORT const char* API_CALL mk_media_info_get_params(const mk_media_info ctx);
|
||||||
//MediaInfo::_schema
|
//MediaInfo::schema
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_schema(const mk_media_info ctx);
|
API_EXPORT const char* API_CALL mk_media_info_get_schema(const mk_media_info ctx);
|
||||||
//MediaInfo::_vhost
|
//MediaInfo::vhost
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_vhost(const mk_media_info ctx);
|
API_EXPORT const char* API_CALL mk_media_info_get_vhost(const mk_media_info ctx);
|
||||||
//MediaInfo::_app
|
//MediaInfo::app
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_app(const mk_media_info ctx);
|
API_EXPORT const char* API_CALL mk_media_info_get_app(const mk_media_info ctx);
|
||||||
//MediaInfo::_streamid
|
//MediaInfo::stream
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_stream(const mk_media_info ctx);
|
API_EXPORT const char* API_CALL mk_media_info_get_stream(const mk_media_info ctx);
|
||||||
//MediaInfo::_host
|
//MediaInfo::host
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_host(const mk_media_info ctx);
|
API_EXPORT const char* API_CALL mk_media_info_get_host(const mk_media_info ctx);
|
||||||
//MediaInfo::_port
|
//MediaInfo::port
|
||||||
API_EXPORT uint16_t API_CALL mk_media_info_get_port(const mk_media_info ctx);
|
API_EXPORT uint16_t API_CALL mk_media_info_get_port(const mk_media_info ctx);
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,43 +126,43 @@ API_EXPORT const char* API_CALL mk_parser_get_content(const mk_parser ctx, size_
|
|||||||
API_EXPORT const char* API_CALL mk_media_info_get_params(const mk_media_info ctx){
|
API_EXPORT const char* API_CALL mk_media_info_get_params(const mk_media_info ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaInfo *info = (MediaInfo *)ctx;
|
MediaInfo *info = (MediaInfo *)ctx;
|
||||||
return info->_param_strs.c_str();
|
return info->param_strs.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_schema(const mk_media_info ctx){
|
API_EXPORT const char* API_CALL mk_media_info_get_schema(const mk_media_info ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaInfo *info = (MediaInfo *)ctx;
|
MediaInfo *info = (MediaInfo *)ctx;
|
||||||
return info->_schema.c_str();
|
return info->schema.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_vhost(const mk_media_info ctx){
|
API_EXPORT const char* API_CALL mk_media_info_get_vhost(const mk_media_info ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaInfo *info = (MediaInfo *)ctx;
|
MediaInfo *info = (MediaInfo *)ctx;
|
||||||
return info->_vhost.c_str();
|
return info->vhost.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_host(const mk_media_info ctx){
|
API_EXPORT const char* API_CALL mk_media_info_get_host(const mk_media_info ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaInfo *info = (MediaInfo *)ctx;
|
MediaInfo *info = (MediaInfo *)ctx;
|
||||||
return info->_host.c_str();
|
return info->host.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT uint16_t API_CALL mk_media_info_get_port(const mk_media_info ctx){
|
API_EXPORT uint16_t API_CALL mk_media_info_get_port(const mk_media_info ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaInfo *info = (MediaInfo *)ctx;
|
MediaInfo *info = (MediaInfo *)ctx;
|
||||||
return info->_port;
|
return info->port;
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_app(const mk_media_info ctx){
|
API_EXPORT const char* API_CALL mk_media_info_get_app(const mk_media_info ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaInfo *info = (MediaInfo *)ctx;
|
MediaInfo *info = (MediaInfo *)ctx;
|
||||||
return info->_app.c_str();
|
return info->app.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT const char* API_CALL mk_media_info_get_stream(const mk_media_info ctx){
|
API_EXPORT const char* API_CALL mk_media_info_get_stream(const mk_media_info ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaInfo *info = (MediaInfo *)ctx;
|
MediaInfo *info = (MediaInfo *)ctx;
|
||||||
return info->_streamid.c_str();
|
return info->stream.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////MediaSource/////////////////////////////////////////////
|
///////////////////////////////////////////MediaSource/////////////////////////////////////////////
|
||||||
|
@ -22,7 +22,8 @@ public:
|
|||||||
MediaHelper(const char *vhost, const char *app, const char *stream, float duration, const ProtocolOption &option) {
|
MediaHelper(const char *vhost, const char *app, const char *stream, float duration, const ProtocolOption &option) {
|
||||||
_poller = EventPollerPool::Instance().getPoller();
|
_poller = EventPollerPool::Instance().getPoller();
|
||||||
// 在poller线程中创建DevChannel(MultiMediaSourceMuxer)对象,确保严格的线程安全限制
|
// 在poller线程中创建DevChannel(MultiMediaSourceMuxer)对象,确保严格的线程安全限制
|
||||||
_poller->sync([&]() { _channel = std::make_shared<DevChannel>(vhost, app, stream, duration, option); });
|
auto tuple = MediaTuple{vhost, app, stream};
|
||||||
|
_poller->sync([&]() { _channel = std::make_shared<DevChannel>(tuple, duration, option); });
|
||||||
}
|
}
|
||||||
|
|
||||||
~MediaHelper() = default;
|
~MediaHelper() = default;
|
||||||
|
@ -102,9 +102,9 @@ void FFmpegSource::play(const string &ffmpeg_cmd_key, const string &src_url,cons
|
|||||||
_process.run(cmd, log_file);
|
_process.run(cmd, log_file);
|
||||||
InfoL << cmd;
|
InfoL << cmd;
|
||||||
|
|
||||||
if (is_local_ip(_media_info._host)) {
|
if (is_local_ip(_media_info.host)) {
|
||||||
//推流给自己的,通过判断流是否注册上来判断是否正常
|
//推流给自己的,通过判断流是否注册上来判断是否正常
|
||||||
if(_media_info._schema != RTSP_SCHEMA && _media_info._schema != RTMP_SCHEMA){
|
if (_media_info.schema != RTSP_SCHEMA && _media_info.schema != RTMP_SCHEMA) {
|
||||||
cb(SockException(Err_other,"本服务只支持rtmp/rtsp推流"));
|
cb(SockException(Err_other,"本服务只支持rtmp/rtsp推流"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,10 +154,10 @@ void FFmpegSource::play(const string &ffmpeg_cmd_key, const string &src_url,cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FFmpegSource::findAsync(int maxWaitMS, const function<void(const MediaSource::Ptr &src)> &cb) {
|
void FFmpegSource::findAsync(int maxWaitMS, const function<void(const MediaSource::Ptr &src)> &cb) {
|
||||||
auto src = MediaSource::find(_media_info._schema,
|
auto src = MediaSource::find(_media_info.schema,
|
||||||
_media_info._vhost,
|
_media_info.vhost,
|
||||||
_media_info._app,
|
_media_info.app,
|
||||||
_media_info._streamid);
|
_media_info.stream);
|
||||||
if(src || !maxWaitMS){
|
if(src || !maxWaitMS){
|
||||||
cb(src);
|
cb(src);
|
||||||
return;
|
return;
|
||||||
@ -183,10 +183,10 @@ void FFmpegSource::findAsync(int maxWaitMS, const function<void(const MediaSourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!bRegist ||
|
if (!bRegist ||
|
||||||
sender.getSchema() != strongSelf->_media_info._schema ||
|
sender.getSchema() != strongSelf->_media_info.schema ||
|
||||||
sender.getVhost() != strongSelf->_media_info._vhost ||
|
sender.getVhost() != strongSelf->_media_info.vhost ||
|
||||||
sender.getApp() != strongSelf->_media_info._app ||
|
sender.getApp() != strongSelf->_media_info.app ||
|
||||||
sender.getId() != strongSelf->_media_info._streamid) {
|
sender.getId() != strongSelf->_media_info.stream) {
|
||||||
//不是自己感兴趣的事件,忽略之
|
//不是自己感兴趣的事件,忽略之
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ void FFmpegSource::startTimer(int timeout_ms) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool needRestart = ffmpeg_restart_sec > 0 && strongSelf->_replay_ticker.elapsedTime() > ffmpeg_restart_sec * 1000;
|
bool needRestart = ffmpeg_restart_sec > 0 && strongSelf->_replay_ticker.elapsedTime() > ffmpeg_restart_sec * 1000;
|
||||||
if (is_local_ip(strongSelf->_media_info._host)) {
|
if (is_local_ip(strongSelf->_media_info.host)) {
|
||||||
//推流给自己的,我们通过检查是否已经注册来判断FFmpeg是否工作正常
|
//推流给自己的,我们通过检查是否已经注册来判断FFmpeg是否工作正常
|
||||||
strongSelf->findAsync(0, [&](const MediaSource::Ptr &src) {
|
strongSelf->findAsync(0, [&](const MediaSource::Ptr &src) {
|
||||||
//同步查找流
|
//同步查找流
|
||||||
|
@ -1467,7 +1467,8 @@ void installWebApi() {
|
|||||||
api_regist("/index/api/deleteRecordDirectory", [](API_ARGS_MAP) {
|
api_regist("/index/api/deleteRecordDirectory", [](API_ARGS_MAP) {
|
||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
CHECK_ARGS("vhost", "app", "stream");
|
CHECK_ARGS("vhost", "app", "stream");
|
||||||
auto record_path = Recorder::getRecordPath(Recorder::type_mp4, allArgs["vhost"], allArgs["app"], allArgs["stream"], allArgs["customized_path"]);
|
auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"]};
|
||||||
|
auto record_path = Recorder::getRecordPath(Recorder::type_mp4, tuple, allArgs["customized_path"]);
|
||||||
auto period = allArgs["period"];
|
auto period = allArgs["period"];
|
||||||
record_path = record_path + period + "/";
|
record_path = record_path + period + "/";
|
||||||
int result = File::delete_file(record_path.data());
|
int result = File::delete_file(record_path.data());
|
||||||
@ -1484,7 +1485,8 @@ void installWebApi() {
|
|||||||
api_regist("/index/api/getMp4RecordFile", [](API_ARGS_MAP){
|
api_regist("/index/api/getMp4RecordFile", [](API_ARGS_MAP){
|
||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
CHECK_ARGS("vhost", "app", "stream");
|
CHECK_ARGS("vhost", "app", "stream");
|
||||||
auto record_path = Recorder::getRecordPath(Recorder::type_mp4, allArgs["vhost"], allArgs["app"], allArgs["stream"], allArgs["customized_path"]);
|
auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"]};
|
||||||
|
auto record_path = Recorder::getRecordPath(Recorder::type_mp4, tuple, allArgs["customized_path"]);
|
||||||
auto period = allArgs["period"];
|
auto period = allArgs["period"];
|
||||||
|
|
||||||
//判断是获取mp4文件列表还是获取文件夹列表
|
//判断是获取mp4文件列表还是获取文件夹列表
|
||||||
|
@ -215,11 +215,11 @@ void do_http_hook(const string &url, const ArgsType &body, const function<void(c
|
|||||||
|
|
||||||
static ArgsType make_json(const MediaInfo &args) {
|
static ArgsType make_json(const MediaInfo &args) {
|
||||||
ArgsType body;
|
ArgsType body;
|
||||||
body["schema"] = args._schema;
|
body["schema"] = args.schema;
|
||||||
body[VHOST_KEY] = args._vhost;
|
body[VHOST_KEY] = args.vhost;
|
||||||
body["app"] = args._app;
|
body["app"] = args.app;
|
||||||
body["stream"] = args._streamid;
|
body["stream"] = args.stream;
|
||||||
body["params"] = args._param_strs;
|
body["params"] = args.param_strs;
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,12 +263,12 @@ static const string kEdgeServerParam = "edge=1";
|
|||||||
|
|
||||||
static string getPullUrl(const string &origin_fmt, const MediaInfo &info) {
|
static string getPullUrl(const string &origin_fmt, const MediaInfo &info) {
|
||||||
char url[1024] = { 0 };
|
char url[1024] = { 0 };
|
||||||
if ((ssize_t)origin_fmt.size() > snprintf(url, sizeof(url), origin_fmt.data(), info._app.data(), info._streamid.data())) {
|
if ((ssize_t)origin_fmt.size() > snprintf(url, sizeof(url), origin_fmt.data(), info.app.data(), info.stream.data())) {
|
||||||
WarnL << "get origin url failed, origin_fmt:" << origin_fmt;
|
WarnL << "get origin url failed, origin_fmt:" << origin_fmt;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
// 告知源站这是来自边沿站的拉流请求,如果未找到流请立即返回拉流失败
|
// 告知源站这是来自边沿站的拉流请求,如果未找到流请立即返回拉流失败
|
||||||
return string(url) + '?' + kEdgeServerParam + '&' + VHOST_KEY + '=' + info._vhost + '&' + info._param_strs;
|
return string(url) + '?' + kEdgeServerParam + '&' + VHOST_KEY + '=' + info.vhost + '&' + info.param_strs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pullStreamFromOrigin(const vector<string> &urls, size_t index, size_t failed_cnt, const MediaInfo &args, const function<void()> &closePlayer) {
|
static void pullStreamFromOrigin(const vector<string> &urls, size_t index, size_t failed_cnt, const MediaInfo &args, const function<void()> &closePlayer) {
|
||||||
@ -280,10 +280,10 @@ static void pullStreamFromOrigin(const vector<string> &urls, size_t index, size_
|
|||||||
InfoL << "pull stream from origin, failed_cnt: " << failed_cnt << ", timeout_sec: " << timeout_sec << ", url: " << url;
|
InfoL << "pull stream from origin, failed_cnt: " << failed_cnt << ", timeout_sec: " << timeout_sec << ", url: " << url;
|
||||||
|
|
||||||
ProtocolOption option;
|
ProtocolOption option;
|
||||||
option.enable_hls = option.enable_hls || (args._schema == HLS_SCHEMA);
|
option.enable_hls = option.enable_hls || (args.schema == HLS_SCHEMA);
|
||||||
option.enable_mp4 = false;
|
option.enable_mp4 = false;
|
||||||
|
|
||||||
addStreamProxy(args._vhost, args._app, args._streamid, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, [=](const SockException &ex, const string &key) mutable {
|
addStreamProxy(args.vhost, args.app, args.stream, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, [=](const SockException &ex, const string &key) mutable {
|
||||||
if (!ex) {
|
if (!ex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -321,7 +321,7 @@ void installWebHook() {
|
|||||||
|
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastMediaPublish, [](BroadcastMediaPublishArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastMediaPublish, [](BroadcastMediaPublishArgs) {
|
||||||
GET_CONFIG(string, hook_publish, Hook::kOnPublish);
|
GET_CONFIG(string, hook_publish, Hook::kOnPublish);
|
||||||
if (!hook_enable || args._param_strs == hook_adminparams || hook_publish.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
if (!hook_enable || args.param_strs == hook_adminparams || hook_publish.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
||||||
invoker("", ProtocolOption());
|
invoker("", ProtocolOption());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ void installWebHook() {
|
|||||||
|
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastMediaPlayed, [](BroadcastMediaPlayedArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastMediaPlayed, [](BroadcastMediaPlayedArgs) {
|
||||||
GET_CONFIG(string, hook_play, Hook::kOnPlay);
|
GET_CONFIG(string, hook_play, Hook::kOnPlay);
|
||||||
if (!hook_enable || args._param_strs == hook_adminparams || hook_play.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
if (!hook_enable || args.param_strs == hook_adminparams || hook_play.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
||||||
invoker("");
|
invoker("");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -360,7 +360,7 @@ void installWebHook() {
|
|||||||
|
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastFlowReport, [](BroadcastFlowReportArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastFlowReport, [](BroadcastFlowReportArgs) {
|
||||||
GET_CONFIG(string, hook_flowreport, Hook::kOnFlowReport);
|
GET_CONFIG(string, hook_flowreport, Hook::kOnFlowReport);
|
||||||
if (!hook_enable || args._param_strs == hook_adminparams || hook_flowreport.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
if (!hook_enable || args.param_strs == hook_adminparams || hook_flowreport.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto body = make_json(args);
|
auto body = make_json(args);
|
||||||
@ -379,7 +379,7 @@ void installWebHook() {
|
|||||||
// 监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问
|
// 监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问
|
||||||
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastOnGetRtspRealm, [](BroadcastOnGetRtspRealmArgs) {
|
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastOnGetRtspRealm, [](BroadcastOnGetRtspRealmArgs) {
|
||||||
GET_CONFIG(string, hook_rtsp_realm, Hook::kOnRtspRealm);
|
GET_CONFIG(string, hook_rtsp_realm, Hook::kOnRtspRealm);
|
||||||
if (!hook_enable || args._param_strs == hook_adminparams || hook_rtsp_realm.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
if (!hook_enable || args.param_strs == hook_adminparams || hook_rtsp_realm.empty() || sender.get_peer_ip() == "127.0.0.1") {
|
||||||
// 无需认证
|
// 无需认证
|
||||||
invoker("");
|
invoker("");
|
||||||
return;
|
return;
|
||||||
@ -467,7 +467,7 @@ void installWebHook() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start_with(args._param_strs, kEdgeServerParam)) {
|
if (start_with(args.param_strs, kEdgeServerParam)) {
|
||||||
// 源站收到来自边沿站的溯源请求,流不存在时立即返回拉流失败
|
// 源站收到来自边沿站的溯源请求,流不存在时立即返回拉流失败
|
||||||
closePlayer();
|
closePlayer();
|
||||||
return;
|
return;
|
||||||
|
@ -47,10 +47,8 @@ public:
|
|||||||
using Ptr = std::shared_ptr<DevChannel>;
|
using Ptr = std::shared_ptr<DevChannel>;
|
||||||
|
|
||||||
//fDuration<=0为直播,否则为点播
|
//fDuration<=0为直播,否则为点播
|
||||||
DevChannel(
|
DevChannel(const MediaTuple& tuple, float duration = 0, const ProtocolOption &option = ProtocolOption())
|
||||||
const std::string &vhost, const std::string &app, const std::string &stream_id, float duration = 0,
|
: MultiMediaSourceMuxer(tuple, duration, option) {}
|
||||||
const ProtocolOption &option = ProtocolOption())
|
|
||||||
: MultiMediaSourceMuxer(vhost, app, stream_id, duration, option) {}
|
|
||||||
~DevChannel() override = default;
|
~DevChannel() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +105,7 @@ ProtocolOption::ProtocolOption() {
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct MediaSourceNull : public MediaSource {
|
struct MediaSourceNull : public MediaSource {
|
||||||
MediaSourceNull() : MediaSource("schema", "vhost", "app", "stream") {};
|
MediaSourceNull() : MediaSource("schema", MediaTuple{"vhost", "app", "stream"}) {};
|
||||||
int readerCount() override { return 0; }
|
int readerCount() override { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,16 +114,12 @@ MediaSource &MediaSource::NullMediaSource() {
|
|||||||
return *s_null;
|
return *s_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaSource::MediaSource(const string &schema, const string &vhost, const string &app, const string &stream_id){
|
MediaSource::MediaSource(const string &schema, const MediaTuple& tuple): _tuple(tuple) {
|
||||||
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
if (!enableVhost) {
|
if (!enableVhost || _tuple.vhost.empty()) {
|
||||||
_vhost = DEFAULT_VHOST;
|
_tuple.vhost = DEFAULT_VHOST;
|
||||||
} else {
|
|
||||||
_vhost = vhost.empty() ? DEFAULT_VHOST : vhost;
|
|
||||||
}
|
}
|
||||||
_schema = schema;
|
_schema = schema;
|
||||||
_app = app;
|
|
||||||
_stream_id = stream_id;
|
|
||||||
_create_stamp = time(NULL);
|
_create_stamp = time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,16 +132,16 @@ const string& MediaSource::getSchema() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const string& MediaSource::getVhost() const {
|
const string& MediaSource::getVhost() const {
|
||||||
return _vhost;
|
return _tuple.vhost;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string& MediaSource::getApp() const {
|
const string& MediaSource::getApp() const {
|
||||||
//获取该源的id
|
//获取该源的id
|
||||||
return _app;
|
return _tuple.app;
|
||||||
}
|
}
|
||||||
|
|
||||||
const string& MediaSource::getId() const {
|
const string& MediaSource::getId() const {
|
||||||
return _stream_id;
|
return _tuple.stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<void> MediaSource::getOwnership() {
|
std::shared_ptr<void> MediaSource::getOwnership() {
|
||||||
@ -424,7 +420,7 @@ static MediaSource::Ptr find_l(const string &schema, const string &vhost_in, con
|
|||||||
|
|
||||||
static void findAsync_l(const MediaInfo &info, const std::shared_ptr<Session> &session, bool retry,
|
static void findAsync_l(const MediaInfo &info, const std::shared_ptr<Session> &session, bool retry,
|
||||||
const function<void(const MediaSource::Ptr &src)> &cb){
|
const function<void(const MediaSource::Ptr &src)> &cb){
|
||||||
auto src = find_l(info._schema, info._vhost, info._app, info._streamid, true);
|
auto src = find_l(info.schema, info.vhost, info.app, info.stream, true);
|
||||||
if (src || !retry) {
|
if (src || !retry) {
|
||||||
cb(src);
|
cb(src);
|
||||||
return;
|
return;
|
||||||
@ -459,10 +455,10 @@ static void findAsync_l(const MediaInfo &info, const std::shared_ptr<Session> &s
|
|||||||
weak_ptr<Session> weak_session = session;
|
weak_ptr<Session> weak_session = session;
|
||||||
auto on_register = [weak_session, info, cb_once, cancel_all, poller](BroadcastMediaChangedArgs) {
|
auto on_register = [weak_session, info, cb_once, cancel_all, poller](BroadcastMediaChangedArgs) {
|
||||||
if (!bRegist ||
|
if (!bRegist ||
|
||||||
sender.getSchema() != info._schema ||
|
sender.getSchema() != info.schema ||
|
||||||
sender.getVhost() != info._vhost ||
|
sender.getVhost() != info.vhost ||
|
||||||
sender.getApp() != info._app ||
|
sender.getApp() != info.app ||
|
||||||
sender.getId() != info._streamid) {
|
sender.getId() != info.stream) {
|
||||||
//不是自己感兴趣的事件,忽略之
|
//不是自己感兴趣的事件,忽略之
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -527,7 +523,7 @@ void MediaSource::regist() {
|
|||||||
{
|
{
|
||||||
//减小互斥锁临界区
|
//减小互斥锁临界区
|
||||||
lock_guard<recursive_mutex> lock(s_media_source_mtx);
|
lock_guard<recursive_mutex> lock(s_media_source_mtx);
|
||||||
auto &ref = s_media_source_map[_schema][_vhost][_app][_stream_id];
|
auto &ref = s_media_source_map[_schema][_tuple.vhost][_tuple.app][_tuple.stream];
|
||||||
auto src = ref.lock();
|
auto src = ref.lock();
|
||||||
if (src) {
|
if (src) {
|
||||||
if (src.get() == this) {
|
if (src.get() == this) {
|
||||||
@ -570,7 +566,7 @@ bool MediaSource::unregist() {
|
|||||||
{
|
{
|
||||||
//减小互斥锁临界区
|
//减小互斥锁临界区
|
||||||
lock_guard<recursive_mutex> lock(s_media_source_mtx);
|
lock_guard<recursive_mutex> lock(s_media_source_mtx);
|
||||||
erase_media_source(ret, this, s_media_source_map, _schema, _vhost, _app, _stream_id);
|
erase_media_source(ret, this, s_media_source_map, _schema, _tuple.vhost, _tuple.app, _tuple.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -582,31 +578,31 @@ bool MediaSource::unregist() {
|
|||||||
/////////////////////////////////////MediaInfo//////////////////////////////////////
|
/////////////////////////////////////MediaInfo//////////////////////////////////////
|
||||||
|
|
||||||
void MediaInfo::parse(const std::string &url_in){
|
void MediaInfo::parse(const std::string &url_in){
|
||||||
_full_url = url_in;
|
full_url = url_in;
|
||||||
auto url = url_in;
|
auto url = url_in;
|
||||||
auto pos = url.find("?");
|
auto pos = url.find("?");
|
||||||
if (pos != string::npos) {
|
if (pos != string::npos) {
|
||||||
_param_strs = url.substr(pos + 1);
|
param_strs = url.substr(pos + 1);
|
||||||
url.erase(pos);
|
url.erase(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto schema_pos = url.find("://");
|
auto schema_pos = url.find("://");
|
||||||
if (schema_pos != string::npos) {
|
if (schema_pos != string::npos) {
|
||||||
_schema = url.substr(0, schema_pos);
|
schema = url.substr(0, schema_pos);
|
||||||
} else {
|
} else {
|
||||||
schema_pos = -3;
|
schema_pos = -3;
|
||||||
}
|
}
|
||||||
auto split_vec = split(url.substr(schema_pos + 3), "/");
|
auto split_vec = split(url.substr(schema_pos + 3), "/");
|
||||||
if (split_vec.size() > 0) {
|
if (split_vec.size() > 0) {
|
||||||
splitUrl(split_vec[0], _host, _port);
|
splitUrl(split_vec[0], host, port);
|
||||||
_vhost = _host;
|
vhost = host;
|
||||||
if (_vhost == "localhost" || isIP(_vhost.data())) {
|
if (vhost == "localhost" || isIP(vhost.data())) {
|
||||||
//如果访问的是localhost或ip,那么则为默认虚拟主机
|
//如果访问的是localhost或ip,那么则为默认虚拟主机
|
||||||
_vhost = DEFAULT_VHOST;
|
vhost = DEFAULT_VHOST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (split_vec.size() > 1) {
|
if (split_vec.size() > 1) {
|
||||||
_app = split_vec[1];
|
app = split_vec[1];
|
||||||
}
|
}
|
||||||
if (split_vec.size() > 2) {
|
if (split_vec.size() > 2) {
|
||||||
string stream_id;
|
string stream_id;
|
||||||
@ -616,18 +612,18 @@ void MediaInfo::parse(const std::string &url_in){
|
|||||||
if (stream_id.back() == '/') {
|
if (stream_id.back() == '/') {
|
||||||
stream_id.pop_back();
|
stream_id.pop_back();
|
||||||
}
|
}
|
||||||
_streamid = stream_id;
|
stream = stream_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto params = Parser::parseArgs(_param_strs);
|
auto params = Parser::parseArgs(param_strs);
|
||||||
if (params.find(VHOST_KEY) != params.end()) {
|
if (params.find(VHOST_KEY) != params.end()) {
|
||||||
_vhost = params[VHOST_KEY];
|
vhost = params[VHOST_KEY];
|
||||||
}
|
}
|
||||||
|
|
||||||
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
if (!enableVhost || _vhost.empty()) {
|
if (!enableVhost || vhost.empty()) {
|
||||||
//如果关闭虚拟主机或者虚拟主机为空,则设置虚拟主机为默认
|
//如果关闭虚拟主机或者虚拟主机为空,则设置虚拟主机为默认
|
||||||
_vhost = DEFAULT_VHOST;
|
vhost = DEFAULT_VHOST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,24 +252,20 @@ private:
|
|||||||
/**
|
/**
|
||||||
* 解析url获取媒体相关信息
|
* 解析url获取媒体相关信息
|
||||||
*/
|
*/
|
||||||
class MediaInfo {
|
class MediaInfo: public MediaTuple {
|
||||||
public:
|
public:
|
||||||
~MediaInfo() = default;
|
~MediaInfo() = default;
|
||||||
MediaInfo() = default;
|
MediaInfo() = default;
|
||||||
MediaInfo(const std::string &url) { parse(url); }
|
MediaInfo(const std::string &url) { parse(url); }
|
||||||
void parse(const std::string &url);
|
void parse(const std::string &url);
|
||||||
std::string shortUrl() const { return _vhost + "/" + _app + "/" + _streamid; }
|
std::string getUrl() const { return schema + "://" + shortUrl(); }
|
||||||
std::string getUrl() const { return _schema + "://" + shortUrl(); }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint16_t _port = 0;
|
uint16_t port = 0;
|
||||||
std::string _full_url;
|
std::string full_url;
|
||||||
std::string _schema;
|
std::string schema;
|
||||||
std::string _host;
|
std::string host;
|
||||||
std::string _vhost;
|
std::string param_strs;
|
||||||
std::string _app;
|
|
||||||
std::string _streamid;
|
|
||||||
std::string _param_strs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -280,7 +276,7 @@ public:
|
|||||||
static MediaSource& NullMediaSource();
|
static MediaSource& NullMediaSource();
|
||||||
using Ptr = std::shared_ptr<MediaSource>;
|
using Ptr = std::shared_ptr<MediaSource>;
|
||||||
|
|
||||||
MediaSource(const std::string &schema, const std::string &vhost, const std::string &app, const std::string &stream_id);
|
MediaSource(const std::string &schema, const MediaTuple& tuple);
|
||||||
virtual ~MediaSource();
|
virtual ~MediaSource();
|
||||||
|
|
||||||
////////////////获取MediaSource相关信息////////////////
|
////////////////获取MediaSource相关信息////////////////
|
||||||
@ -294,7 +290,11 @@ public:
|
|||||||
// 流id
|
// 流id
|
||||||
const std::string& getId() const;
|
const std::string& getId() const;
|
||||||
|
|
||||||
std::string shortUrl() const { return _vhost + "/" + _app + "/" + _stream_id; }
|
const MediaTuple& getMediaTuple() const {
|
||||||
|
return _tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string shortUrl() const { return _tuple.shortUrl(); }
|
||||||
|
|
||||||
std::string getUrl() const { return _schema + "://" + shortUrl(); }
|
std::string getUrl() const { return _schema + "://" + shortUrl(); }
|
||||||
|
|
||||||
@ -369,7 +369,7 @@ public:
|
|||||||
// 同步查找流
|
// 同步查找流
|
||||||
static Ptr find(const std::string &schema, const std::string &vhost, const std::string &app, const std::string &id, bool from_mp4 = false);
|
static Ptr find(const std::string &schema, const std::string &vhost, const std::string &app, const std::string &id, bool from_mp4 = false);
|
||||||
static Ptr find(const MediaInfo &info, bool from_mp4 = false) {
|
static Ptr find(const MediaInfo &info, bool from_mp4 = false) {
|
||||||
return find(info._schema, info._vhost, info._app, info._streamid, from_mp4);
|
return find(info.schema, info.vhost, info.app, info.stream, from_mp4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 忽略schema,同步查找流,可能返回rtmp/rtsp/hls类型
|
// 忽略schema,同步查找流,可能返回rtmp/rtsp/hls类型
|
||||||
@ -394,15 +394,13 @@ private:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
toolkit::BytesSpeed _speed[TrackMax];
|
toolkit::BytesSpeed _speed[TrackMax];
|
||||||
|
MediaTuple _tuple;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic_flag _owned { false };
|
std::atomic_flag _owned { false };
|
||||||
time_t _create_stamp;
|
time_t _create_stamp;
|
||||||
toolkit::Ticker _ticker;
|
toolkit::Ticker _ticker;
|
||||||
std::string _schema;
|
std::string _schema;
|
||||||
std::string _vhost;
|
|
||||||
std::string _app;
|
|
||||||
std::string _stream_id;
|
|
||||||
std::weak_ptr<MediaSourceEvent> _listener;
|
std::weak_ptr<MediaSourceEvent> _listener;
|
||||||
// 对象个数统计
|
// 对象个数统计
|
||||||
toolkit::ObjectStatistic<MediaSource> _statistic;
|
toolkit::ObjectStatistic<MediaSource> _statistic;
|
||||||
|
@ -25,7 +25,7 @@ namespace {
|
|||||||
class MediaSourceForMuxer : public MediaSource {
|
class MediaSourceForMuxer : public MediaSource {
|
||||||
public:
|
public:
|
||||||
MediaSourceForMuxer(const MultiMediaSourceMuxer::Ptr &muxer)
|
MediaSourceForMuxer(const MultiMediaSourceMuxer::Ptr &muxer)
|
||||||
: MediaSource("muxer", muxer->getVhost(), muxer->getApp(), muxer->getStreamId()) {
|
: MediaSource("muxer", muxer->getMediaTuple()) {
|
||||||
MediaSource::setListener(muxer);
|
MediaSource::setListener(muxer);
|
||||||
}
|
}
|
||||||
int readerCount() override { return 0; }
|
int readerCount() override { return 0; }
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
static std::shared_ptr<MediaSinkInterface> makeRecorder(MediaSource &sender, const vector<Track::Ptr> &tracks, Recorder::type type, const ProtocolOption &option){
|
static std::shared_ptr<MediaSinkInterface> makeRecorder(MediaSource &sender, const vector<Track::Ptr> &tracks, Recorder::type type, const ProtocolOption &option){
|
||||||
auto recorder = Recorder::createRecorder(type, sender.getVhost(), sender.getApp(), sender.getId(), option);
|
auto recorder = Recorder::createRecorder(type, sender.getMediaTuple(), option);
|
||||||
for (auto &track : tracks) {
|
for (auto &track : tracks) {
|
||||||
recorder->addTrack(track);
|
recorder->addTrack(track);
|
||||||
}
|
}
|
||||||
@ -71,15 +71,15 @@ static string getTrackInfoStr(const TrackSource *track_src){
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::string &MultiMediaSourceMuxer::getVhost() const {
|
const std::string &MultiMediaSourceMuxer::getVhost() const {
|
||||||
return _vhost;
|
return _tuple.vhost;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &MultiMediaSourceMuxer::getApp() const {
|
const std::string &MultiMediaSourceMuxer::getApp() const {
|
||||||
return _app;
|
return _tuple.app;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &MultiMediaSourceMuxer::getStreamId() const {
|
const std::string &MultiMediaSourceMuxer::getStreamId() const {
|
||||||
return _stream_id;
|
return _tuple.stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MultiMediaSourceMuxer::shortUrl() const {
|
std::string MultiMediaSourceMuxer::shortUrl() const {
|
||||||
@ -87,35 +87,32 @@ std::string MultiMediaSourceMuxer::shortUrl() const {
|
|||||||
if (!ret.empty()) {
|
if (!ret.empty()) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return _vhost + "/" + _app + "/" + _stream_id;
|
return _tuple.shortUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiMediaSourceMuxer::MultiMediaSourceMuxer(const string &vhost, const string &app, const string &stream, float dur_sec, const ProtocolOption &option) {
|
MultiMediaSourceMuxer::MultiMediaSourceMuxer(const MediaTuple& tuple, float dur_sec, const ProtocolOption &option): _tuple(tuple) {
|
||||||
_poller = EventPollerPool::Instance().getPoller();
|
_poller = EventPollerPool::Instance().getPoller();
|
||||||
_create_in_poller = _poller->isCurrentThread();
|
_create_in_poller = _poller->isCurrentThread();
|
||||||
_vhost = vhost;
|
|
||||||
_app = app;
|
|
||||||
_stream_id = stream;
|
|
||||||
_option = option;
|
_option = option;
|
||||||
|
|
||||||
if (option.enable_rtmp) {
|
if (option.enable_rtmp) {
|
||||||
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, app, stream, option, std::make_shared<TitleMeta>(dur_sec));
|
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(_tuple, option, std::make_shared<TitleMeta>(dur_sec));
|
||||||
}
|
}
|
||||||
if (option.enable_rtsp) {
|
if (option.enable_rtsp) {
|
||||||
_rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, app, stream, option, std::make_shared<TitleSdp>(dur_sec));
|
_rtsp = std::make_shared<RtspMediaSourceMuxer>(_tuple, option, std::make_shared<TitleSdp>(dur_sec));
|
||||||
}
|
}
|
||||||
if (option.enable_hls) {
|
if (option.enable_hls) {
|
||||||
_hls = dynamic_pointer_cast<HlsRecorder>(Recorder::createRecorder(Recorder::type_hls, vhost, app, stream, option));
|
_hls = dynamic_pointer_cast<HlsRecorder>(Recorder::createRecorder(Recorder::type_hls, _tuple, option));
|
||||||
}
|
}
|
||||||
if (option.enable_mp4) {
|
if (option.enable_mp4) {
|
||||||
_mp4 = Recorder::createRecorder(Recorder::type_mp4, vhost, app, stream, option);
|
_mp4 = Recorder::createRecorder(Recorder::type_mp4, _tuple, option);
|
||||||
}
|
}
|
||||||
if (option.enable_ts) {
|
if (option.enable_ts) {
|
||||||
_ts = std::make_shared<TSMediaSourceMuxer>(vhost, app, stream, option);
|
_ts = std::make_shared<TSMediaSourceMuxer>(_tuple, option);
|
||||||
}
|
}
|
||||||
#if defined(ENABLE_MP4)
|
#if defined(ENABLE_MP4)
|
||||||
if (option.enable_fmp4) {
|
if (option.enable_fmp4) {
|
||||||
_fmp4 = std::make_shared<FMP4MediaSourceMuxer>(vhost, app, stream, option);
|
_fmp4 = std::make_shared<FMP4MediaSourceMuxer>(_tuple, option);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
virtual void onAllTrackReady() = 0;
|
virtual void onAllTrackReady() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
MultiMediaSourceMuxer(const std::string &vhost, const std::string &app, const std::string &stream, float dur_sec = 0.0,const ProtocolOption &option = ProtocolOption());
|
MultiMediaSourceMuxer(const MediaTuple& tuple, float dur_sec = 0.0,const ProtocolOption &option = ProtocolOption());
|
||||||
~MultiMediaSourceMuxer() override = default;
|
~MultiMediaSourceMuxer() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,6 +129,9 @@ public:
|
|||||||
const std::string& getVhost() const;
|
const std::string& getVhost() const;
|
||||||
const std::string& getApp() const;
|
const std::string& getApp() const;
|
||||||
const std::string& getStreamId() const;
|
const std::string& getStreamId() const;
|
||||||
|
const MediaTuple& getMediaTuple() const {
|
||||||
|
return _tuple;
|
||||||
|
}
|
||||||
std::string shortUrl() const;
|
std::string shortUrl() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -159,9 +162,7 @@ private:
|
|||||||
bool _is_enable = false;
|
bool _is_enable = false;
|
||||||
bool _create_in_poller = false;
|
bool _create_in_poller = false;
|
||||||
bool _video_key_pos = false;
|
bool _video_key_pos = false;
|
||||||
std::string _vhost;
|
MediaTuple _tuple;
|
||||||
std::string _app;
|
|
||||||
std::string _stream_id;
|
|
||||||
ProtocolOption _option;
|
ProtocolOption _option;
|
||||||
toolkit::Ticker _last_check;
|
toolkit::Ticker _last_check;
|
||||||
Stamp _stamp[2];
|
Stamp _stamp[2];
|
||||||
|
@ -39,10 +39,8 @@ public:
|
|||||||
using RingDataType = std::shared_ptr<toolkit::List<FMP4Packet::Ptr> >;
|
using RingDataType = std::shared_ptr<toolkit::List<FMP4Packet::Ptr> >;
|
||||||
using RingType = toolkit::RingBuffer<RingDataType>;
|
using RingType = toolkit::RingBuffer<RingDataType>;
|
||||||
|
|
||||||
FMP4MediaSource(const std::string &vhost,
|
FMP4MediaSource(const MediaTuple& tuple,
|
||||||
const std::string &app,
|
int ring_size = FMP4_GOP_SIZE) : MediaSource(FMP4_SCHEMA, tuple), _ring_size(ring_size) {}
|
||||||
const std::string &stream_id,
|
|
||||||
int ring_size = FMP4_GOP_SIZE) : MediaSource(FMP4_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {}
|
|
||||||
|
|
||||||
~FMP4MediaSource() override { flush(); }
|
~FMP4MediaSource() override { flush(); }
|
||||||
|
|
||||||
|
@ -23,12 +23,9 @@ class FMP4MediaSourceMuxer final : public MP4MuxerMemory, public MediaSourceEven
|
|||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<FMP4MediaSourceMuxer>;
|
using Ptr = std::shared_ptr<FMP4MediaSourceMuxer>;
|
||||||
|
|
||||||
FMP4MediaSourceMuxer(const std::string &vhost,
|
FMP4MediaSourceMuxer(const MediaTuple& tuple, const ProtocolOption &option) {
|
||||||
const std::string &app,
|
|
||||||
const std::string &stream_id,
|
|
||||||
const ProtocolOption &option) {
|
|
||||||
_option = option;
|
_option = option;
|
||||||
_media_src = std::make_shared<FMP4MediaSource>(vhost, app, stream_id);
|
_media_src = std::make_shared<FMP4MediaSource>(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
~FMP4MediaSourceMuxer() override { MP4MuxerMemory::flush(); };
|
~FMP4MediaSourceMuxer() override { MP4MuxerMemory::flush(); };
|
||||||
|
@ -278,7 +278,7 @@ static void canAccessPath(Session &sender, const Parser &parser, const MediaInfo
|
|||||||
HttpCookieManager::Instance().delCookie(cookie);
|
HttpCookieManager::Instance().delCookie(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_hls = media_info._schema == HLS_SCHEMA;
|
bool is_hls = media_info.schema == HLS_SCHEMA;
|
||||||
|
|
||||||
SockInfoImp::Ptr info = std::make_shared<SockInfoImp>();
|
SockInfoImp::Ptr info = std::make_shared<SockInfoImp>();
|
||||||
info->_identifier = sender.getIdentifier();
|
info->_identifier = sender.getIdentifier();
|
||||||
@ -363,8 +363,8 @@ static void accessFile(Session &sender, const Parser &parser, const MediaInfo &m
|
|||||||
}
|
}
|
||||||
if (is_hls) {
|
if (is_hls) {
|
||||||
// hls,那么移除掉后缀获取真实的stream_id并且修改协议为HLS
|
// hls,那么移除掉后缀获取真实的stream_id并且修改协议为HLS
|
||||||
const_cast<string &>(media_info._schema) = HLS_SCHEMA;
|
const_cast<string &>(media_info.schema) = HLS_SCHEMA;
|
||||||
replace(const_cast<string &>(media_info._streamid), kHlsSuffix, "");
|
replace(const_cast<string &>(media_info.stream), kHlsSuffix, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
weak_ptr<Session> weakSession = static_pointer_cast<Session>(sender.shared_from_this());
|
weak_ptr<Session> weakSession = static_pointer_cast<Session>(sender.shared_from_this());
|
||||||
@ -465,11 +465,11 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, Sess
|
|||||||
});
|
});
|
||||||
|
|
||||||
string url, path;
|
string url, path;
|
||||||
auto it = virtualPathMap.find(media_info._app);
|
auto it = virtualPathMap.find(media_info.app);
|
||||||
if (it != virtualPathMap.end()) {
|
if (it != virtualPathMap.end()) {
|
||||||
//访问的是virtualPath
|
//访问的是virtualPath
|
||||||
path = it->second;
|
path = it->second;
|
||||||
url = parser.Url().substr(1 + media_info._app.size());
|
url = parser.Url().substr(1 + media_info.app.size());
|
||||||
} else {
|
} else {
|
||||||
//访问的是rootPath
|
//访问的是rootPath
|
||||||
path = rootPath;
|
path = rootPath;
|
||||||
@ -481,7 +481,7 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, Sess
|
|||||||
ch = '/';
|
ch = '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto ret = File::absolutePath(enableVhost ? media_info._vhost + url : url, path);
|
auto ret = File::absolutePath(enableVhost ? media_info.vhost + url : url, path);
|
||||||
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpBeforeAccess, parser, ret, static_cast<SockInfo &>(sender));
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpBeforeAccess, parser, ret, static_cast<SockInfo &>(sender));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ bool HttpSession::checkLiveStream(const string &schema, const string &url_suffi
|
|||||||
//解析带上协议+参数完整的url
|
//解析带上协议+参数完整的url
|
||||||
_mediaInfo.parse(schema + "://" + _parser["Host"] + url);
|
_mediaInfo.parse(schema + "://" + _parser["Host"] + url);
|
||||||
|
|
||||||
if (_mediaInfo._app.empty() || _mediaInfo._streamid.empty()) {
|
if (_mediaInfo.app.empty() || _mediaInfo.stream.empty()) {
|
||||||
//url不合法
|
//url不合法
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,9 @@ PlayerProxy::PlayerProxy(
|
|||||||
const EventPoller::Ptr &poller, int reconnect_delay_min, int reconnect_delay_max, int reconnect_delay_step)
|
const EventPoller::Ptr &poller, int reconnect_delay_min, int reconnect_delay_max, int reconnect_delay_step)
|
||||||
: MediaPlayer(poller)
|
: MediaPlayer(poller)
|
||||||
, _option(option) {
|
, _option(option) {
|
||||||
_vhost = vhost;
|
_tuple.vhost = vhost;
|
||||||
_app = app;
|
_tuple.app = app;
|
||||||
_stream_id = stream_id;
|
_tuple.stream = stream_id;
|
||||||
_retry_count = retry_count;
|
_retry_count = retry_count;
|
||||||
|
|
||||||
setOnClose(nullptr);
|
setOnClose(nullptr);
|
||||||
@ -187,11 +187,11 @@ void PlayerProxy::setDirectProxy() {
|
|||||||
// rtsp拉流
|
// rtsp拉流
|
||||||
GET_CONFIG(bool, directProxy, Rtsp::kDirectProxy);
|
GET_CONFIG(bool, directProxy, Rtsp::kDirectProxy);
|
||||||
if (directProxy) {
|
if (directProxy) {
|
||||||
mediaSource = std::make_shared<RtspMediaSource>(_vhost, _app, _stream_id);
|
mediaSource = std::make_shared<RtspMediaSource>(_tuple);
|
||||||
}
|
}
|
||||||
} else if (dynamic_pointer_cast<RtmpPlayer>(_delegate)) {
|
} else if (dynamic_pointer_cast<RtmpPlayer>(_delegate)) {
|
||||||
// rtmp拉流,rtmp强制直接代理
|
// rtmp拉流,rtmp强制直接代理
|
||||||
mediaSource = std::make_shared<RtmpMediaSource>(_vhost, _app, _stream_id);
|
mediaSource = std::make_shared<RtmpMediaSource>(_tuple);
|
||||||
}
|
}
|
||||||
if (mediaSource) {
|
if (mediaSource) {
|
||||||
setMediaSource(mediaSource);
|
setMediaSource(mediaSource);
|
||||||
@ -277,18 +277,18 @@ void PlayerProxy::onPlaySuccess() {
|
|||||||
// rtsp拉流代理
|
// rtsp拉流代理
|
||||||
if (reset_when_replay || !_muxer) {
|
if (reset_when_replay || !_muxer) {
|
||||||
_option.enable_rtsp = false;
|
_option.enable_rtsp = false;
|
||||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), _option);
|
_muxer = std::make_shared<MultiMediaSourceMuxer>(_tuple, getDuration(), _option);
|
||||||
}
|
}
|
||||||
} else if (dynamic_pointer_cast<RtmpMediaSource>(_media_src)) {
|
} else if (dynamic_pointer_cast<RtmpMediaSource>(_media_src)) {
|
||||||
// rtmp拉流代理
|
// rtmp拉流代理
|
||||||
if (reset_when_replay || !_muxer) {
|
if (reset_when_replay || !_muxer) {
|
||||||
_option.enable_rtmp = false;
|
_option.enable_rtmp = false;
|
||||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), _option);
|
_muxer = std::make_shared<MultiMediaSourceMuxer>(_tuple, getDuration(), _option);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 其他拉流代理
|
// 其他拉流代理
|
||||||
if (reset_when_replay || !_muxer) {
|
if (reset_when_replay || !_muxer) {
|
||||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(_vhost, _app, _stream_id, getDuration(), _option);
|
_muxer = std::make_shared<MultiMediaSourceMuxer>(_tuple, getDuration(), _option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_muxer->setMediaListener(shared_from_this());
|
_muxer->setMediaListener(shared_from_this());
|
||||||
|
@ -134,9 +134,7 @@ private:
|
|||||||
int _reconnect_delay_min;
|
int _reconnect_delay_min;
|
||||||
int _reconnect_delay_max;
|
int _reconnect_delay_max;
|
||||||
int _reconnect_delay_step;
|
int _reconnect_delay_step;
|
||||||
std::string _vhost;
|
MediaTuple _tuple;
|
||||||
std::string _app;
|
|
||||||
std::string _stream_id;
|
|
||||||
std::string _pull_url;
|
std::string _pull_url;
|
||||||
toolkit::Timer::Ptr _timer;
|
toolkit::Timer::Ptr _timer;
|
||||||
std::function<void()> _on_disconnect;
|
std::function<void()> _on_disconnect;
|
||||||
|
@ -163,10 +163,10 @@ std::shared_ptr<FILE> HlsMakerImp::makeFile(const string &file, bool setbuf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HlsMakerImp::setMediaSource(const string &vhost, const string &app, const string &stream_id) {
|
void HlsMakerImp::setMediaSource(const string &vhost, const string &app, const string &stream_id) {
|
||||||
_media_src = std::make_shared<HlsMediaSource>(vhost, app, stream_id);
|
|
||||||
_info.app = app;
|
_info.app = app;
|
||||||
_info.stream = stream_id;
|
_info.stream = stream_id;
|
||||||
_info.vhost = vhost;
|
_info.vhost = vhost;
|
||||||
|
_media_src = std::make_shared<HlsMediaSource>(_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
HlsMediaSource::Ptr HlsMakerImp::getMediaSource() const {
|
HlsMediaSource::Ptr HlsMakerImp::getMediaSource() const {
|
||||||
|
@ -25,8 +25,7 @@ public:
|
|||||||
using RingType = toolkit::RingBuffer<std::string>;
|
using RingType = toolkit::RingBuffer<std::string>;
|
||||||
using Ptr = std::shared_ptr<HlsMediaSource>;
|
using Ptr = std::shared_ptr<HlsMediaSource>;
|
||||||
|
|
||||||
HlsMediaSource(const std::string &vhost, const std::string &app, const std::string &stream_id)
|
HlsMediaSource(const MediaTuple& tuple): MediaSource(HLS_SCHEMA, tuple) {}
|
||||||
: MediaSource(HLS_SCHEMA, vhost, app, stream_id) {}
|
|
||||||
~HlsMediaSource() override = default;
|
~HlsMediaSource() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,8 +35,8 @@ public:
|
|||||||
|
|
||||||
~HlsRecorder() { MpegMuxer::flush(); };
|
~HlsRecorder() { MpegMuxer::flush(); };
|
||||||
|
|
||||||
void setMediaSource(const std::string &vhost, const std::string &app, const std::string &stream_id) {
|
void setMediaSource(const MediaTuple& tuple) {
|
||||||
_hls->setMediaSource(vhost, app, stream_id);
|
_hls->setMediaSource(tuple.vhost, tuple.app, tuple.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setListener(const std::weak_ptr<MediaSourceEvent> &listener) {
|
void setListener(const std::weak_ptr<MediaSourceEvent> &listener) {
|
||||||
|
@ -20,17 +20,18 @@ using namespace toolkit;
|
|||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
MP4Reader::MP4Reader(const string &vhost, const string &app, const string &stream_id, const string &file_path) {
|
MP4Reader::MP4Reader(const std::string &vhost, const std::string &app, const std::string &stream_id, const string &file_path) {
|
||||||
//读写文件建议放在后台线程
|
//读写文件建议放在后台线程
|
||||||
|
auto tuple = MediaTuple{vhost, app, stream_id};
|
||||||
_poller = WorkThreadPool::Instance().getPoller();
|
_poller = WorkThreadPool::Instance().getPoller();
|
||||||
_file_path = file_path;
|
_file_path = file_path;
|
||||||
if (_file_path.empty()) {
|
if (_file_path.empty()) {
|
||||||
GET_CONFIG(string, recordPath, Protocol::kMP4SavePath);
|
GET_CONFIG(string, recordPath, Protocol::kMP4SavePath);
|
||||||
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
if (enableVhost) {
|
if (enableVhost) {
|
||||||
_file_path = vhost + "/" + app + "/" + stream_id;
|
_file_path = tuple.shortUrl();
|
||||||
} else {
|
} else {
|
||||||
_file_path = app + "/" + stream_id;
|
_file_path = tuple.app + "/" + tuple.stream;
|
||||||
}
|
}
|
||||||
_file_path = File::absolutePath(_file_path, recordPath);
|
_file_path = File::absolutePath(_file_path, recordPath);
|
||||||
}
|
}
|
||||||
@ -38,14 +39,14 @@ MP4Reader::MP4Reader(const string &vhost, const string &app, const string &strea
|
|||||||
_demuxer = std::make_shared<MP4Demuxer>();
|
_demuxer = std::make_shared<MP4Demuxer>();
|
||||||
_demuxer->openMP4(_file_path);
|
_demuxer->openMP4(_file_path);
|
||||||
|
|
||||||
if (stream_id.empty()) {
|
if (tuple.stream.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ProtocolOption option;
|
ProtocolOption option;
|
||||||
//读取mp4文件并流化时,不重复生成mp4/hls文件
|
//读取mp4文件并流化时,不重复生成mp4/hls文件
|
||||||
option.enable_mp4 = false;
|
option.enable_mp4 = false;
|
||||||
option.enable_hls = false;
|
option.enable_hls = false;
|
||||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(vhost, app, stream_id, _demuxer->getDurationMS() / 1000.0f, option);
|
_muxer = std::make_shared<MultiMediaSourceMuxer>(tuple, _demuxer->getDurationMS() / 1000.0f, option);
|
||||||
auto tracks = _demuxer->getTracks(false);
|
auto tracks = _demuxer->getTracks(false);
|
||||||
if (tracks.empty()) {
|
if (tracks.empty()) {
|
||||||
throw std::runtime_error(StrPrinter << "该mp4文件没有有效的track:" << _file_path);
|
throw std::runtime_error(StrPrinter << "该mp4文件没有有效的track:" << _file_path);
|
||||||
|
@ -21,16 +21,16 @@ using namespace toolkit;
|
|||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
string Recorder::getRecordPath(Recorder::type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path) {
|
string Recorder::getRecordPath(Recorder::type type, const MediaTuple& tuple, const string &customized_path) {
|
||||||
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Recorder::type_hls: {
|
case Recorder::type_hls: {
|
||||||
GET_CONFIG(string, hlsPath, Protocol::kHlsSavePath);
|
GET_CONFIG(string, hlsPath, Protocol::kHlsSavePath);
|
||||||
string m3u8FilePath;
|
string m3u8FilePath;
|
||||||
if (enableVhost) {
|
if (enableVhost) {
|
||||||
m3u8FilePath = vhost + "/" + app + "/" + stream_id + "/hls.m3u8";
|
m3u8FilePath = tuple.shortUrl() + "/hls.m3u8";
|
||||||
} else {
|
} else {
|
||||||
m3u8FilePath = app + "/" + stream_id + "/hls.m3u8";
|
m3u8FilePath = tuple.app + "/" + tuple.stream + "/hls.m3u8";
|
||||||
}
|
}
|
||||||
//Here we use the customized file path.
|
//Here we use the customized file path.
|
||||||
if (!customized_path.empty()) {
|
if (!customized_path.empty()) {
|
||||||
@ -43,9 +43,9 @@ string Recorder::getRecordPath(Recorder::type type, const string &vhost, const s
|
|||||||
GET_CONFIG(string, recordAppName, Record::kAppName);
|
GET_CONFIG(string, recordAppName, Record::kAppName);
|
||||||
string mp4FilePath;
|
string mp4FilePath;
|
||||||
if (enableVhost) {
|
if (enableVhost) {
|
||||||
mp4FilePath = vhost + "/" + recordAppName + "/" + app + "/" + stream_id + "/";
|
mp4FilePath = tuple.vhost + "/" + recordAppName + "/" + tuple.app + "/" + tuple.stream + "/";
|
||||||
} else {
|
} else {
|
||||||
mp4FilePath = recordAppName + "/" + app + "/" + stream_id + "/";
|
mp4FilePath = recordAppName + "/" + tuple.app + "/" + tuple.stream + "/";
|
||||||
}
|
}
|
||||||
//Here we use the customized file path.
|
//Here we use the customized file path.
|
||||||
if (!customized_path.empty()) {
|
if (!customized_path.empty()) {
|
||||||
@ -58,14 +58,14 @@ string Recorder::getRecordPath(Recorder::type type, const string &vhost, const s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MediaSinkInterface> Recorder::createRecorder(type type, const string &vhost, const string &app, const string &stream_id, const ProtocolOption &option){
|
std::shared_ptr<MediaSinkInterface> Recorder::createRecorder(type type, const MediaTuple& tuple, const ProtocolOption &option){
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Recorder::type_hls: {
|
case Recorder::type_hls: {
|
||||||
#if defined(ENABLE_HLS)
|
#if defined(ENABLE_HLS)
|
||||||
auto path = Recorder::getRecordPath(type, vhost, app, stream_id, option.hls_save_path);
|
auto path = Recorder::getRecordPath(type, tuple, option.hls_save_path);
|
||||||
GET_CONFIG(bool, enable_vhost, General::kEnableVhost);
|
GET_CONFIG(bool, enable_vhost, General::kEnableVhost);
|
||||||
auto ret = std::make_shared<HlsRecorder>(path, enable_vhost ? string(VHOST_KEY) + "=" + vhost : "", option);
|
auto ret = std::make_shared<HlsRecorder>(path, enable_vhost ? string(VHOST_KEY) + "=" + tuple.vhost : "", option);
|
||||||
ret->setMediaSource(vhost, app, stream_id);
|
ret->setMediaSource(tuple);
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#else
|
||||||
throw std::invalid_argument("hls相关功能未打开,请开启ENABLE_HLS宏后编译再测试");
|
throw std::invalid_argument("hls相关功能未打开,请开启ENABLE_HLS宏后编译再测试");
|
||||||
@ -75,8 +75,8 @@ std::shared_ptr<MediaSinkInterface> Recorder::createRecorder(type type, const st
|
|||||||
|
|
||||||
case Recorder::type_mp4: {
|
case Recorder::type_mp4: {
|
||||||
#if defined(ENABLE_MP4)
|
#if defined(ENABLE_MP4)
|
||||||
auto path = Recorder::getRecordPath(type, vhost, app, stream_id, option.mp4_save_path);
|
auto path = Recorder::getRecordPath(type, tuple, option.mp4_save_path);
|
||||||
return std::make_shared<MP4Recorder>(path, vhost, app, stream_id, option.mp4_max_second);
|
return std::make_shared<MP4Recorder>(path, tuple.vhost, tuple.app, tuple.stream, option.mp4_max_second);
|
||||||
#else
|
#else
|
||||||
throw std::invalid_argument("mp4相关功能未打开,请开启ENABLE_MP4宏后编译再测试");
|
throw std::invalid_argument("mp4相关功能未打开,请开启ENABLE_MP4宏后编译再测试");
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,7 +18,16 @@ namespace mediakit {
|
|||||||
class MediaSinkInterface;
|
class MediaSinkInterface;
|
||||||
class ProtocolOption;
|
class ProtocolOption;
|
||||||
|
|
||||||
class RecordInfo {
|
struct MediaTuple {
|
||||||
|
std::string vhost;
|
||||||
|
std::string app;
|
||||||
|
std::string stream;
|
||||||
|
std::string shortUrl() const {
|
||||||
|
return vhost + '/' + app + '/' + stream;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RecordInfo: public MediaTuple {
|
||||||
public:
|
public:
|
||||||
time_t start_time; // GMT 标准时间,单位秒
|
time_t start_time; // GMT 标准时间,单位秒
|
||||||
float time_len; // 录像长度,单位秒
|
float time_len; // 录像长度,单位秒
|
||||||
@ -27,9 +36,6 @@ public:
|
|||||||
std::string file_name; // 文件名称
|
std::string file_name; // 文件名称
|
||||||
std::string folder; // 文件夹路径
|
std::string folder; // 文件夹路径
|
||||||
std::string url; // 播放路径
|
std::string url; // 播放路径
|
||||||
std::string app; // 应用名称
|
|
||||||
std::string stream; // 流 ID
|
|
||||||
std::string vhost; // 虚拟主机
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Recorder{
|
class Recorder{
|
||||||
@ -50,7 +56,7 @@ public:
|
|||||||
* @param customized_path 录像文件保存自定义根目录,为空则采用配置文件设置
|
* @param customized_path 录像文件保存自定义根目录,为空则采用配置文件设置
|
||||||
* @return 录制文件绝对路径
|
* @return 录制文件绝对路径
|
||||||
*/
|
*/
|
||||||
static std::string getRecordPath(type type, const std::string &vhost, const std::string &app, const std::string &stream_id,const std::string &customized_path = "");
|
static std::string getRecordPath(type type, const MediaTuple& tuple, const std::string &customized_path = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建录制器对象
|
* 创建录制器对象
|
||||||
@ -62,7 +68,7 @@ public:
|
|||||||
* @param max_second mp4录制最大切片时间,单位秒,置0则采用配置文件配置
|
* @param max_second mp4录制最大切片时间,单位秒,置0则采用配置文件配置
|
||||||
* @return 对象指针,可能为nullptr
|
* @return 对象指针,可能为nullptr
|
||||||
*/
|
*/
|
||||||
static std::shared_ptr<MediaSinkInterface> createRecorder(type type, const std::string &vhost, const std::string &app, const std::string &stream_id, const ProtocolOption &option);
|
static std::shared_ptr<MediaSinkInterface> createRecorder(type type, const MediaTuple& tuple, const ProtocolOption &option);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Recorder() = delete;
|
Recorder() = delete;
|
||||||
|
@ -46,12 +46,7 @@ public:
|
|||||||
* @param stream_id 流id
|
* @param stream_id 流id
|
||||||
* @param ring_size 可以设置固定的环形缓冲大小,0则自适应
|
* @param ring_size 可以设置固定的环形缓冲大小,0则自适应
|
||||||
*/
|
*/
|
||||||
RtmpMediaSource(const std::string &vhost,
|
RtmpMediaSource(const MediaTuple& tuple, int ring_size = RTMP_GOP_SIZE): MediaSource(RTMP_SCHEMA, tuple), _ring_size(ring_size) {}
|
||||||
const std::string &app,
|
|
||||||
const std::string &stream_id,
|
|
||||||
int ring_size = RTMP_GOP_SIZE) :
|
|
||||||
MediaSource(RTMP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~RtmpMediaSource() override { flush(); }
|
~RtmpMediaSource() override { flush(); }
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ void RtmpMediaSource::onWrite(RtmpPacket::Ptr pkt, bool /*= true*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RtmpMediaSourceImp::RtmpMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize) : RtmpMediaSource(vhost, app, id, ringSize)
|
RtmpMediaSourceImp::RtmpMediaSourceImp(const MediaTuple& tuple, int ringSize) : RtmpMediaSource(tuple, ringSize)
|
||||||
{
|
{
|
||||||
_demuxer = std::make_shared<RtmpDemuxer>();
|
_demuxer = std::make_shared<RtmpDemuxer>();
|
||||||
_demuxer->setTrackListener(this);
|
_demuxer->setTrackListener(this);
|
||||||
@ -99,7 +99,7 @@ void RtmpMediaSourceImp::setProtocolOption(const ProtocolOption &option)
|
|||||||
_option = option;
|
_option = option;
|
||||||
//不重复生成rtmp协议
|
//不重复生成rtmp协议
|
||||||
_option.enable_rtmp = false;
|
_option.enable_rtmp = false;
|
||||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(getVhost(), getApp(), getId(), _demuxer->getDuration(), _option);
|
_muxer = std::make_shared<MultiMediaSourceMuxer>(_tuple, _demuxer->getDuration(), _option);
|
||||||
_muxer->setMediaListener(getListener());
|
_muxer->setMediaListener(getListener());
|
||||||
_muxer->setTrackListener(std::static_pointer_cast<RtmpMediaSourceImp>(shared_from_this()));
|
_muxer->setTrackListener(std::static_pointer_cast<RtmpMediaSourceImp>(shared_from_this()));
|
||||||
//让_muxer对象拦截一部分事件(比如说录像相关事件)
|
//让_muxer对象拦截一部分事件(比如说录像相关事件)
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
* @param id 流id
|
* @param id 流id
|
||||||
* @param ringSize 环形缓存大小
|
* @param ringSize 环形缓存大小
|
||||||
*/
|
*/
|
||||||
RtmpMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize = RTMP_GOP_SIZE);
|
RtmpMediaSourceImp(const MediaTuple& tuple, int ringSize = RTMP_GOP_SIZE);
|
||||||
|
|
||||||
~RtmpMediaSourceImp() override = default;
|
~RtmpMediaSourceImp() override = default;
|
||||||
|
|
||||||
|
@ -21,13 +21,11 @@ class RtmpMediaSourceMuxer final : public RtmpMuxer, public MediaSourceEventInte
|
|||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<RtmpMediaSourceMuxer>;
|
using Ptr = std::shared_ptr<RtmpMediaSourceMuxer>;
|
||||||
|
|
||||||
RtmpMediaSourceMuxer(const std::string &vhost,
|
RtmpMediaSourceMuxer(const MediaTuple& tuple,
|
||||||
const std::string &strApp,
|
|
||||||
const std::string &strId,
|
|
||||||
const ProtocolOption &option,
|
const ProtocolOption &option,
|
||||||
const TitleMeta::Ptr &title = nullptr) : RtmpMuxer(title) {
|
const TitleMeta::Ptr &title = nullptr) : RtmpMuxer(title) {
|
||||||
_option = option;
|
_option = option;
|
||||||
_media_src = std::make_shared<RtmpMediaSource>(vhost, strApp, strId);
|
_media_src = std::make_shared<RtmpMediaSource>(tuple);
|
||||||
getRtmpRing()->setDelegate(_media_src);
|
getRtmpRing()->setDelegate(_media_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
|
|||||||
auto tc_url = params["tcUrl"].as_string();
|
auto tc_url = params["tcUrl"].as_string();
|
||||||
if (tc_url.empty()) {
|
if (tc_url.empty()) {
|
||||||
// defaultVhost:默认vhost
|
// defaultVhost:默认vhost
|
||||||
tc_url = string(RTMP_SCHEMA) + "://" + DEFAULT_VHOST + "/" + _media_info._app;
|
tc_url = string(RTMP_SCHEMA) + "://" + DEFAULT_VHOST + "/" + _media_info.app;
|
||||||
} else {
|
} else {
|
||||||
auto pos = tc_url.rfind('?');
|
auto pos = tc_url.rfind('?');
|
||||||
if (pos != string::npos) {
|
if (pos != string::npos) {
|
||||||
@ -94,9 +94,9 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
|
|||||||
}
|
}
|
||||||
// 初步解析,只用于获取vhost信息
|
// 初步解析,只用于获取vhost信息
|
||||||
_media_info.parse(tc_url);
|
_media_info.parse(tc_url);
|
||||||
_media_info._schema = RTMP_SCHEMA;
|
_media_info.schema = RTMP_SCHEMA;
|
||||||
// 赋值rtmp app
|
// 赋值rtmp app
|
||||||
_media_info._app = params["app"].as_string();
|
_media_info.app = params["app"].as_string();
|
||||||
|
|
||||||
bool ok = true; //(app == APP_NAME);
|
bool ok = true; //(app == APP_NAME);
|
||||||
AMFValue version(AMF_OBJECT);
|
AMFValue version(AMF_OBJECT);
|
||||||
@ -109,7 +109,7 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
|
|||||||
status.set("objectEncoding", params["objectEncoding"]);
|
status.set("objectEncoding", params["objectEncoding"]);
|
||||||
sendReply(ok ? "_result" : "_error", version, status);
|
sendReply(ok ? "_result" : "_error", version, status);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw std::runtime_error("Unsupported application: " + _media_info._app);
|
throw std::runtime_error("Unsupported application: " + _media_info.app);
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFEncoder invoke;
|
AMFEncoder invoke;
|
||||||
@ -132,9 +132,9 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
|
|||||||
}));
|
}));
|
||||||
dec.load<AMFValue>();/* NULL */
|
dec.load<AMFValue>();/* NULL */
|
||||||
// 赋值为rtmp stream id 信息
|
// 赋值为rtmp stream id 信息
|
||||||
_media_info._streamid = getStreamId(dec.load<std::string>());
|
_media_info.stream = getStreamId(dec.load<std::string>());
|
||||||
// 再解析url,切割url为app/stream_id (不一定符合rtmp url切割规范)
|
// 再解析url,切割url为app/stream_id (不一定符合rtmp url切割规范)
|
||||||
_media_info.parse(_media_info._schema + "://" + _media_info._vhost + '/' + _media_info._app + '/' + _media_info._streamid);
|
_media_info.parse(_media_info.getUrl());
|
||||||
|
|
||||||
auto now_stream_index = _now_stream_index;
|
auto now_stream_index = _now_stream_index;
|
||||||
auto on_res = [this, token, now_stream_index](const string &err, const ProtocolOption &option) {
|
auto on_res = [this, token, now_stream_index](const string &err, const ProtocolOption &option) {
|
||||||
@ -149,7 +149,7 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(!_push_src);
|
assert(!_push_src);
|
||||||
auto src = MediaSource::find(RTMP_SCHEMA, _media_info._vhost, _media_info._app, _media_info._streamid);
|
auto src = MediaSource::find(RTMP_SCHEMA, _media_info.vhost, _media_info.app, _media_info.stream);
|
||||||
auto push_failed = (bool)src;
|
auto push_failed = (bool)src;
|
||||||
|
|
||||||
while (src) {
|
while (src) {
|
||||||
@ -180,7 +180,7 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!_push_src) {
|
if (!_push_src) {
|
||||||
_push_src = std::make_shared<RtmpMediaSourceImp>(_media_info._vhost, _media_info._app, _media_info._streamid);
|
_push_src = std::make_shared<RtmpMediaSourceImp>(_media_info);
|
||||||
//获取所有权
|
//获取所有权
|
||||||
_push_src_ownership = _push_src->getOwnership();
|
_push_src_ownership = _push_src->getOwnership();
|
||||||
_push_src->setProtocolOption(option);
|
_push_src->setProtocolOption(option);
|
||||||
@ -196,7 +196,7 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
|
|||||||
setSocketFlags();
|
setSocketFlags();
|
||||||
};
|
};
|
||||||
|
|
||||||
if(_media_info._app.empty() || _media_info._streamid.empty()){
|
if(_media_info.app.empty() || _media_info.stream.empty()){
|
||||||
//不允许莫名其妙的推流url
|
//不允许莫名其妙的推流url
|
||||||
on_res("rtmp推流url非法", ProtocolOption());
|
on_res("rtmp推流url非法", ProtocolOption());
|
||||||
return;
|
return;
|
||||||
@ -256,7 +256,7 @@ void RtmpSession::sendPlayResponse(const string &err, const RtmpMediaSource::Ptr
|
|||||||
sendStatus({ "level", (ok ? "status" : "error"),
|
sendStatus({ "level", (ok ? "status" : "error"),
|
||||||
"code", (ok ? "NetStream.Play.Reset" : (auth_success ? "NetStream.Play.StreamNotFound" : "NetStream.Play.BadAuth")),
|
"code", (ok ? "NetStream.Play.Reset" : (auth_success ? "NetStream.Play.StreamNotFound" : "NetStream.Play.BadAuth")),
|
||||||
"description", (ok ? "Resetting and playing." : (auth_success ? "No such stream." : err.data())),
|
"description", (ok ? "Resetting and playing." : (auth_success ? "No such stream." : err.data())),
|
||||||
"details", _media_info._streamid,
|
"details", _media_info.stream,
|
||||||
"clientid", "0" });
|
"clientid", "0" });
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@ -270,7 +270,7 @@ void RtmpSession::sendPlayResponse(const string &err, const RtmpMediaSource::Ptr
|
|||||||
sendStatus({ "level", "status",
|
sendStatus({ "level", "status",
|
||||||
"code", "NetStream.Play.Start",
|
"code", "NetStream.Play.Start",
|
||||||
"description", "Started playing." ,
|
"description", "Started playing." ,
|
||||||
"details", _media_info._streamid,
|
"details", _media_info.stream,
|
||||||
"clientid", "0"});
|
"clientid", "0"});
|
||||||
|
|
||||||
// |RtmpSampleAccess(true, true)
|
// |RtmpSampleAccess(true, true)
|
||||||
@ -289,7 +289,7 @@ void RtmpSession::sendPlayResponse(const string &err, const RtmpMediaSource::Ptr
|
|||||||
sendStatus({ "level", "status",
|
sendStatus({ "level", "status",
|
||||||
"code", "NetStream.Play.PublishNotify",
|
"code", "NetStream.Play.PublishNotify",
|
||||||
"description", "Now published." ,
|
"description", "Now published." ,
|
||||||
"details", _media_info._streamid,
|
"details", _media_info.stream,
|
||||||
"clientid", "0"});
|
"clientid", "0"});
|
||||||
|
|
||||||
auto &metadata = src->getMetaData();
|
auto &metadata = src->getMetaData();
|
||||||
@ -433,9 +433,9 @@ string RtmpSession::getStreamId(const string &str){
|
|||||||
void RtmpSession::onCmd_play(AMFDecoder &dec) {
|
void RtmpSession::onCmd_play(AMFDecoder &dec) {
|
||||||
dec.load<AMFValue>(); /* NULL */
|
dec.load<AMFValue>(); /* NULL */
|
||||||
// 赋值为rtmp stream id 信息
|
// 赋值为rtmp stream id 信息
|
||||||
_media_info._streamid = getStreamId(dec.load<std::string>());
|
_media_info.stream = getStreamId(dec.load<std::string>());
|
||||||
// 再解析url,切割url为app/stream_id (不一定符合rtmp url切割规范)
|
// 再解析url,切割url为app/stream_id (不一定符合rtmp url切割规范)
|
||||||
_media_info.parse(_media_info._schema + "://" + _media_info._vhost + '/' + _media_info._app + '/' + _media_info._streamid);
|
_media_info.parse(_media_info.getUrl());
|
||||||
doPlay(dec);
|
doPlay(dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,7 +589,7 @@ MediaOriginType RtmpSession::getOriginType(MediaSource &sender) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
string RtmpSession::getOriginUrl(MediaSource &sender) const {
|
string RtmpSession::getOriginUrl(MediaSource &sender) const {
|
||||||
return _media_info._full_url;
|
return _media_info.full_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SockInfo> RtmpSession::getOriginSock(MediaSource &sender) const {
|
std::shared_ptr<SockInfo> RtmpSession::getOriginSock(MediaSource &sender) const {
|
||||||
|
@ -134,7 +134,7 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
|
|||||||
// 设置dump目录
|
// 设置dump目录
|
||||||
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
|
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
|
||||||
if (!dump_dir.empty()) {
|
if (!dump_dir.empty()) {
|
||||||
auto save_path = File::absolutePath(_media_info._streamid + ".mpeg", dump_dir);
|
auto save_path = File::absolutePath(_media_info.stream + ".mpeg", dump_dir);
|
||||||
_save_file_ps.reset(File::create_file(save_path.data(), "wb"), [](FILE *fp) {
|
_save_file_ps.reset(File::create_file(save_path.data(), "wb"), [](FILE *fp) {
|
||||||
if (fp) {
|
if (fp) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -171,11 +171,11 @@ void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
|
|||||||
// 创建解码器
|
// 创建解码器
|
||||||
if (checkTS((uint8_t *)frame->data(), frame->size())) {
|
if (checkTS((uint8_t *)frame->data(), frame->size())) {
|
||||||
// 猜测是ts负载
|
// 猜测是ts负载
|
||||||
InfoL << _media_info._streamid << " judged to be TS";
|
InfoL << _media_info.stream << " judged to be TS";
|
||||||
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
|
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
|
||||||
} else {
|
} else {
|
||||||
// 猜测是ps负载
|
// 猜测是ps负载
|
||||||
InfoL << _media_info._streamid << " judged to be PS";
|
InfoL << _media_info.stream << " judged to be PS";
|
||||||
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
|
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,14 @@ static constexpr size_t kMaxCachedFrame = 200;
|
|||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
RtpProcess::RtpProcess(const string &stream_id) {
|
RtpProcess::RtpProcess(const string &stream_id) {
|
||||||
_media_info._schema = kRtpAppName;
|
_media_info.schema = kRtpAppName;
|
||||||
_media_info._vhost = DEFAULT_VHOST;
|
_media_info.vhost = DEFAULT_VHOST;
|
||||||
_media_info._app = kRtpAppName;
|
_media_info.app = kRtpAppName;
|
||||||
_media_info._streamid = stream_id;
|
_media_info.stream = stream_id;
|
||||||
|
|
||||||
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
|
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
|
||||||
{
|
{
|
||||||
FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info._streamid + ".rtp", dump_dir).data(), "wb") : nullptr;
|
FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info.stream + ".rtp", dump_dir).data(), "wb") : nullptr;
|
||||||
if (fp) {
|
if (fp) {
|
||||||
_save_file_rtp.reset(fp, [](FILE *fp) {
|
_save_file_rtp.reset(fp, [](FILE *fp) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -42,7 +42,7 @@ RtpProcess::RtpProcess(const string &stream_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info._streamid + ".video", dump_dir).data(), "wb") : nullptr;
|
FILE *fp = !dump_dir.empty() ? File::create_file(File::absolutePath(_media_info.stream + ".video", dump_dir).data(), "wb") : nullptr;
|
||||||
if (fp) {
|
if (fp) {
|
||||||
_save_file_video.reset(fp, [](FILE *fp) {
|
_save_file_video.reset(fp, [](FILE *fp) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -234,7 +234,7 @@ uint16_t RtpProcess::get_local_port() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string RtpProcess::getIdentifier() const {
|
string RtpProcess::getIdentifier() const {
|
||||||
return _media_info._streamid;
|
return _media_info.stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtpProcess::emitOnPublish() {
|
void RtpProcess::emitOnPublish() {
|
||||||
@ -251,9 +251,7 @@ void RtpProcess::emitOnPublish() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err.empty()) {
|
if (err.empty()) {
|
||||||
strong_self->_muxer = std::make_shared<MultiMediaSourceMuxer>(strong_self->_media_info._vhost,
|
strong_self->_muxer = std::make_shared<MultiMediaSourceMuxer>(strong_self->_media_info, 0.0f,
|
||||||
strong_self->_media_info._app,
|
|
||||||
strong_self->_media_info._streamid,0.0f,
|
|
||||||
option);
|
option);
|
||||||
if (strong_self->_only_audio) {
|
if (strong_self->_only_audio) {
|
||||||
strong_self->_muxer->setOnlyAudio();
|
strong_self->_muxer->setOnlyAudio();
|
||||||
@ -291,7 +289,7 @@ toolkit::EventPoller::Ptr RtpProcess::getOwnerPoller(MediaSource &sender) {
|
|||||||
if (_sock) {
|
if (_sock) {
|
||||||
return _sock->getPoller();
|
return _sock->getPoller();
|
||||||
}
|
}
|
||||||
throw std::runtime_error("RtpProcess::getOwnerPoller failed:" + _media_info._streamid);
|
throw std::runtime_error("RtpProcess::getOwnerPoller failed:" + _media_info.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
float RtpProcess::getLossRate(MediaSource &sender, TrackType type) {
|
float RtpProcess::getLossRate(MediaSource &sender, TrackType type) {
|
||||||
|
@ -42,11 +42,7 @@ public:
|
|||||||
* @param stream_id 流id
|
* @param stream_id 流id
|
||||||
* @param ring_size 可以设置固定的环形缓冲大小,0则自适应
|
* @param ring_size 可以设置固定的环形缓冲大小,0则自适应
|
||||||
*/
|
*/
|
||||||
RtspMediaSource(const std::string &vhost,
|
RtspMediaSource(const MediaTuple& tuple, int ring_size = RTP_GOP_SIZE): MediaSource(RTSP_SCHEMA, tuple), _ring_size(ring_size) {}
|
||||||
const std::string &app,
|
|
||||||
const std::string &stream_id,
|
|
||||||
int ring_size = RTP_GOP_SIZE) :
|
|
||||||
MediaSource(RTSP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {}
|
|
||||||
|
|
||||||
~RtspMediaSource() override { flush(); }
|
~RtspMediaSource() override { flush(); }
|
||||||
|
|
||||||
@ -76,7 +72,7 @@ public:
|
|||||||
return _sdp;
|
return _sdp;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual RtspMediaSource::Ptr Clone(const std::string& stream) {
|
virtual RtspMediaSource::Ptr clone(const std::string& stream) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,8 +74,7 @@ void RtspMediaSource::onWrite(RtpPacket::Ptr rtp, bool keyPos) {
|
|||||||
PacketCache<RtpPacket>::inputPacket(stamp, is_video, std::move(rtp), keyPos);
|
PacketCache<RtpPacket>::inputPacket(stamp, is_video, std::move(rtp), keyPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
RtspMediaSourceImp::RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize)
|
RtspMediaSourceImp::RtspMediaSourceImp(const MediaTuple& tuple, int ringSize): RtspMediaSource(tuple, ringSize)
|
||||||
: RtspMediaSource(vhost, app, id, ringSize)
|
|
||||||
{
|
{
|
||||||
_demuxer = std::make_shared<RtspDemuxer>();
|
_demuxer = std::make_shared<RtspDemuxer>();
|
||||||
_demuxer->setTrackListener(this);
|
_demuxer->setTrackListener(this);
|
||||||
@ -114,7 +113,7 @@ void RtspMediaSourceImp::setProtocolOption(const ProtocolOption &option)
|
|||||||
//导致rtc无法播放,所以在rtsp推流rtc播放时,建议关闭直接代理模式
|
//导致rtc无法播放,所以在rtsp推流rtc播放时,建议关闭直接代理模式
|
||||||
_option = option;
|
_option = option;
|
||||||
_option.enable_rtsp = !direct_proxy;
|
_option.enable_rtsp = !direct_proxy;
|
||||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(getVhost(), getApp(), getId(), _demuxer->getDuration(), _option);
|
_muxer = std::make_shared<MultiMediaSourceMuxer>(_tuple, _demuxer->getDuration(), _option);
|
||||||
_muxer->setMediaListener(getListener());
|
_muxer->setMediaListener(getListener());
|
||||||
_muxer->setTrackListener(std::static_pointer_cast<RtspMediaSourceImp>(shared_from_this()));
|
_muxer->setTrackListener(std::static_pointer_cast<RtspMediaSourceImp>(shared_from_this()));
|
||||||
//让_muxer对象拦截一部分事件(比如说录像相关事件)
|
//让_muxer对象拦截一部分事件(比如说录像相关事件)
|
||||||
@ -126,8 +125,10 @@ void RtspMediaSourceImp::setProtocolOption(const ProtocolOption &option)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtspMediaSource::Ptr RtspMediaSourceImp::Clone(const std::string &stream) {
|
RtspMediaSource::Ptr RtspMediaSourceImp::clone(const std::string &stream) {
|
||||||
auto src_imp = std::make_shared<RtspMediaSourceImp>(getVhost(), getApp(), stream);
|
auto tuple = _tuple;
|
||||||
|
tuple.stream = stream;
|
||||||
|
auto src_imp = std::make_shared<RtspMediaSourceImp>(tuple);
|
||||||
src_imp->setSdp(getSdp());
|
src_imp->setSdp(getSdp());
|
||||||
src_imp->setProtocolOption(getProtocolOption());
|
src_imp->setProtocolOption(getProtocolOption());
|
||||||
return src_imp;
|
return src_imp;
|
||||||
|
@ -28,7 +28,7 @@ public:
|
|||||||
* @param id 流id
|
* @param id 流id
|
||||||
* @param ringSize 环形缓存大小
|
* @param ringSize 环形缓存大小
|
||||||
*/
|
*/
|
||||||
RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize = RTP_GOP_SIZE);
|
RtspMediaSourceImp(const MediaTuple& tuple, int ringSize = RTP_GOP_SIZE);
|
||||||
|
|
||||||
~RtspMediaSourceImp() override = default;
|
~RtspMediaSourceImp() override = default;
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtspMediaSource::Ptr Clone(const std::string& stream) override;
|
RtspMediaSource::Ptr clone(const std::string& stream) override;
|
||||||
private:
|
private:
|
||||||
bool _all_track_ready = false;
|
bool _all_track_ready = false;
|
||||||
ProtocolOption _option;
|
ProtocolOption _option;
|
||||||
|
@ -21,13 +21,11 @@ class RtspMediaSourceMuxer final : public RtspMuxer, public MediaSourceEventInte
|
|||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<RtspMediaSourceMuxer>;
|
using Ptr = std::shared_ptr<RtspMediaSourceMuxer>;
|
||||||
|
|
||||||
RtspMediaSourceMuxer(const std::string &vhost,
|
RtspMediaSourceMuxer(const MediaTuple& tuple,
|
||||||
const std::string &strApp,
|
|
||||||
const std::string &strId,
|
|
||||||
const ProtocolOption &option,
|
const ProtocolOption &option,
|
||||||
const TitleSdp::Ptr &title = nullptr) : RtspMuxer(title) {
|
const TitleSdp::Ptr &title = nullptr) : RtspMuxer(title) {
|
||||||
_option = option;
|
_option = option;
|
||||||
_media_src = std::make_shared<RtspMediaSource>(vhost,strApp,strId);
|
_media_src = std::make_shared<RtspMediaSource>(tuple);
|
||||||
getRtpRing()->setDelegate(_media_src);
|
getRtpRing()->setDelegate(_media_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ void RtspSession::onWholeRtspPacket(Parser &parser) {
|
|||||||
if (_content_base.empty() && method != "GET") {
|
if (_content_base.empty() && method != "GET") {
|
||||||
_content_base = parser.Url();
|
_content_base = parser.Url();
|
||||||
_media_info.parse(parser.FullUrl());
|
_media_info.parse(parser.FullUrl());
|
||||||
_media_info._schema = RTSP_SCHEMA;
|
_media_info.schema = RTSP_SCHEMA;
|
||||||
}
|
}
|
||||||
|
|
||||||
using rtsp_request_handler = void (RtspSession::*)(const Parser &parser);
|
using rtsp_request_handler = void (RtspSession::*)(const Parser &parser);
|
||||||
@ -208,7 +208,7 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) {
|
|||||||
_media_info.parse(full_url);
|
_media_info.parse(full_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_media_info._app.empty() || _media_info._streamid.empty()) {
|
if (_media_info.app.empty() || _media_info.stream.empty()) {
|
||||||
//推流rtsp url必须最少两级(rtsp://host/app/stream_id),不允许莫名其妙的推流url
|
//推流rtsp url必须最少两级(rtsp://host/app/stream_id),不允许莫名其妙的推流url
|
||||||
static constexpr auto err = "rtsp推流url非法,最少确保两级rtsp url";
|
static constexpr auto err = "rtsp推流url非法,最少确保两级rtsp url";
|
||||||
sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err);
|
sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err);
|
||||||
@ -223,7 +223,7 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(!_push_src);
|
assert(!_push_src);
|
||||||
auto src = MediaSource::find(RTSP_SCHEMA, _media_info._vhost, _media_info._app, _media_info._streamid);
|
auto src = MediaSource::find(RTSP_SCHEMA, _media_info.vhost, _media_info.app, _media_info.stream);
|
||||||
auto push_failed = (bool)src;
|
auto push_failed = (bool)src;
|
||||||
|
|
||||||
while (src) {
|
while (src) {
|
||||||
@ -266,7 +266,7 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!_push_src) {
|
if (!_push_src) {
|
||||||
_push_src = std::make_shared<RtspMediaSourceImp>(_media_info._vhost, _media_info._app, _media_info._streamid);
|
_push_src = std::make_shared<RtspMediaSourceImp>(_media_info);
|
||||||
//获取所有权
|
//获取所有权
|
||||||
_push_src_ownership = _push_src->getOwnership();
|
_push_src_ownership = _push_src->getOwnership();
|
||||||
_push_src->setProtocolOption(option);
|
_push_src->setProtocolOption(option);
|
||||||
@ -717,7 +717,7 @@ void RtspSession::handleReq_Setup(const Parser &parser) {
|
|||||||
break;
|
break;
|
||||||
case Rtsp::RTP_MULTICAST: {
|
case Rtsp::RTP_MULTICAST: {
|
||||||
if(!_multicaster){
|
if(!_multicaster){
|
||||||
_multicaster = RtpMultiCaster::get(*this, get_local_ip(), _media_info._vhost, _media_info._app, _media_info._streamid, _multicast_ip, _multicast_video_port, _multicast_audio_port);
|
_multicaster = RtpMultiCaster::get(*this, get_local_ip(), _media_info.vhost, _media_info.app, _media_info.stream, _multicast_ip, _multicast_video_port, _multicast_audio_port);
|
||||||
if (!_multicaster) {
|
if (!_multicaster) {
|
||||||
send_NotAcceptable();
|
send_NotAcceptable();
|
||||||
throw SockException(Err_shutdown, "can not get a available udp multicast socket");
|
throw SockException(Err_shutdown, "can not get a available udp multicast socket");
|
||||||
@ -1145,7 +1145,7 @@ MediaOriginType RtspSession::getOriginType(MediaSource &sender) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
string RtspSession::getOriginUrl(MediaSource &sender) const {
|
string RtspSession::getOriginUrl(MediaSource &sender) const {
|
||||||
return _media_info._full_url;
|
return _media_info.full_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SockInfo> RtspSession::getOriginSock(MediaSource &sender) const {
|
std::shared_ptr<SockInfo> RtspSession::getOriginSock(MediaSource &sender) const {
|
||||||
|
@ -39,10 +39,7 @@ public:
|
|||||||
using RingDataType = std::shared_ptr<toolkit::List<TSPacket::Ptr> >;
|
using RingDataType = std::shared_ptr<toolkit::List<TSPacket::Ptr> >;
|
||||||
using RingType = toolkit::RingBuffer<RingDataType>;
|
using RingType = toolkit::RingBuffer<RingDataType>;
|
||||||
|
|
||||||
TSMediaSource(const std::string &vhost,
|
TSMediaSource(const MediaTuple& tuple, int ring_size = TS_GOP_SIZE): MediaSource(TS_SCHEMA, tuple), _ring_size(ring_size) {}
|
||||||
const std::string &app,
|
|
||||||
const std::string &stream_id,
|
|
||||||
int ring_size = TS_GOP_SIZE) : MediaSource(TS_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {}
|
|
||||||
|
|
||||||
~TSMediaSource() override { flush(); }
|
~TSMediaSource() override { flush(); }
|
||||||
|
|
||||||
|
@ -21,12 +21,9 @@ class TSMediaSourceMuxer final : public MpegMuxer, public MediaSourceEventInterc
|
|||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<TSMediaSourceMuxer>;
|
using Ptr = std::shared_ptr<TSMediaSourceMuxer>;
|
||||||
|
|
||||||
TSMediaSourceMuxer(const std::string &vhost,
|
TSMediaSourceMuxer(const MediaTuple& tuple, const ProtocolOption &option) : MpegMuxer(false) {
|
||||||
const std::string &app,
|
|
||||||
const std::string &stream_id,
|
|
||||||
const ProtocolOption &option) : MpegMuxer(false) {
|
|
||||||
_option = option;
|
_option = option;
|
||||||
_media_src = std::make_shared<TSMediaSource>(vhost, app, stream_id);
|
_media_src = std::make_shared<TSMediaSource>(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
~TSMediaSourceMuxer() override { MpegMuxer::flush(); };
|
~TSMediaSourceMuxer() override { MpegMuxer::flush(); };
|
||||||
|
@ -35,7 +35,7 @@ void SrtTransportImp::onHandShakeFinished(std::string &streamid, struct sockaddr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto params = Parser::parseArgs(_media_info._param_strs);
|
auto params = Parser::parseArgs(_media_info.param_strs);
|
||||||
if (params["m"] == "publish") {
|
if (params["m"] == "publish") {
|
||||||
_is_pusher = true;
|
_is_pusher = true;
|
||||||
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this);
|
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this);
|
||||||
@ -52,7 +52,7 @@ bool SrtTransportImp::parseStreamid(std::string &streamid) {
|
|||||||
if (!toolkit::start_with(streamid, "#!::")) {
|
if (!toolkit::start_with(streamid, "#!::")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_media_info._schema = SRT_SCHEMA;
|
_media_info.schema = SRT_SCHEMA;
|
||||||
|
|
||||||
std::string real_streamid = streamid.substr(4);
|
std::string real_streamid = streamid.substr(4);
|
||||||
std::string vhost, app, stream_name;
|
std::string vhost, app, stream_name;
|
||||||
@ -70,10 +70,10 @@ bool SrtTransportImp::parseStreamid(std::string &streamid) {
|
|||||||
app = tmps[0];
|
app = tmps[0];
|
||||||
stream_name = tmps[1];
|
stream_name = tmps[1];
|
||||||
} else {
|
} else {
|
||||||
if (_media_info._param_strs.empty()) {
|
if (_media_info.param_strs.empty()) {
|
||||||
_media_info._param_strs = it.first + "=" + it.second;
|
_media_info.param_strs = it.first + "=" + it.second;
|
||||||
} else {
|
} else {
|
||||||
_media_info._param_strs += "&" + it.first + "=" + it.second;
|
_media_info.param_strs += "&" + it.first + "=" + it.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,15 +82,15 @@ bool SrtTransportImp::parseStreamid(std::string &streamid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vhost != "") {
|
if (vhost != "") {
|
||||||
_media_info._vhost = vhost;
|
_media_info.vhost = vhost;
|
||||||
} else {
|
} else {
|
||||||
_media_info._vhost = DEFAULT_VHOST;
|
_media_info.vhost = DEFAULT_VHOST;
|
||||||
}
|
}
|
||||||
|
|
||||||
_media_info._app = app;
|
_media_info.app = app;
|
||||||
_media_info._streamid = stream_name;
|
_media_info.stream = stream_name;
|
||||||
|
|
||||||
TraceL << " mediainfo=" << _media_info.shortUrl() << " params=" << _media_info._param_strs;
|
TraceL << " mediainfo=" << _media_info.shortUrl() << " params=" << _media_info.param_strs;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ mediakit::MediaOriginType SrtTransportImp::getOriginType(mediakit::MediaSource &
|
|||||||
|
|
||||||
// 获取媒体源url或者文件路径
|
// 获取媒体源url或者文件路径
|
||||||
std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const {
|
std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const {
|
||||||
return _media_info._full_url;
|
return _media_info.full_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取媒体源客户端相关信息
|
// 获取媒体源客户端相关信息
|
||||||
@ -157,9 +157,7 @@ void SrtTransportImp::emitOnPublish() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err.empty()) {
|
if (err.empty()) {
|
||||||
strong_self->_muxer = std::make_shared<MultiMediaSourceMuxer>(strong_self->_media_info._vhost,
|
strong_self->_muxer = std::make_shared<MultiMediaSourceMuxer>(strong_self->_media_info,0.0f,
|
||||||
strong_self->_media_info._app,
|
|
||||||
strong_self->_media_info._streamid,0.0f,
|
|
||||||
option);
|
option);
|
||||||
strong_self->_muxer->setMediaListener(strong_self);
|
strong_self->_muxer->setMediaListener(strong_self);
|
||||||
strong_self->doCachedFunc();
|
strong_self->doCachedFunc();
|
||||||
@ -207,7 +205,7 @@ void SrtTransportImp::emitOnPlay() {
|
|||||||
void SrtTransportImp::doPlay() {
|
void SrtTransportImp::doPlay() {
|
||||||
// 异步查找直播流
|
// 异步查找直播流
|
||||||
MediaInfo info = _media_info;
|
MediaInfo info = _media_info;
|
||||||
info._schema = TS_SCHEMA;
|
info.schema = TS_SCHEMA;
|
||||||
std::weak_ptr<SrtTransportImp> weak_self = static_pointer_cast<SrtTransportImp>(shared_from_this());
|
std::weak_ptr<SrtTransportImp> weak_self = static_pointer_cast<SrtTransportImp>(shared_from_this());
|
||||||
MediaSource::findAsync(info, getSession(), [weak_self](const MediaSource::Ptr &src) {
|
MediaSource::findAsync(info, getSession(), [weak_self](const MediaSource::Ptr &src) {
|
||||||
auto strong_self = weak_self.lock();
|
auto strong_self = weak_self.lock();
|
||||||
@ -281,7 +279,7 @@ uint16_t SrtTransportImp::get_local_port() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string SrtTransportImp::getIdentifier() const {
|
std::string SrtTransportImp::getIdentifier() const {
|
||||||
return _media_info._streamid;
|
return _media_info.stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) {
|
bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) {
|
||||||
@ -293,7 +291,7 @@ bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) {
|
|||||||
auto diff = _type_to_stamp[TrackType::TrackVideo].getRelativeStamp() - _type_to_stamp[TrackType::TrackAudio].getRelativeStamp();
|
auto diff = _type_to_stamp[TrackType::TrackVideo].getRelativeStamp() - _type_to_stamp[TrackType::TrackAudio].getRelativeStamp();
|
||||||
if(std::abs(diff) > 5000){
|
if(std::abs(diff) > 5000){
|
||||||
// 超过5s,应该同步 TODO
|
// 超过5s,应该同步 TODO
|
||||||
WarnL << _media_info._full_url<<" video or audio not sync : "<<diff;
|
WarnL << _media_info.full_url <<" video or audio not sync : "<<diff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TraceL<<"after type "<<frame_tmp->getCodecName()<<" dts "<<frame_tmp->dts()<<" pts "<<frame_tmp->pts();
|
//TraceL<<"after type "<<frame_tmp->getCodecName()<<" dts "<<frame_tmp->dts()<<" pts "<<frame_tmp->pts();
|
||||||
|
@ -90,8 +90,8 @@ void initEventListener() {
|
|||||||
static onceToken s_token([]() {
|
static onceToken s_token([]() {
|
||||||
//监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问
|
//监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问
|
||||||
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastOnGetRtspRealm, [](BroadcastOnGetRtspRealmArgs) {
|
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastOnGetRtspRealm, [](BroadcastOnGetRtspRealmArgs) {
|
||||||
DebugL << "RTSP是否需要鉴权事件:" << args.getUrl() << " " << args._param_strs;
|
DebugL << "RTSP是否需要鉴权事件:" << args.getUrl() << " " << args.param_strs;
|
||||||
if (string("1") == args._streamid) {
|
if (string("1") == args.stream) {
|
||||||
// live/1需要认证
|
// live/1需要认证
|
||||||
//该流需要认证,并且设置realm
|
//该流需要认证,并且设置realm
|
||||||
invoker(REALM);
|
invoker(REALM);
|
||||||
@ -104,7 +104,7 @@ void initEventListener() {
|
|||||||
|
|
||||||
//监听kBroadcastOnRtspAuth事件返回正确的rtsp鉴权用户密码
|
//监听kBroadcastOnRtspAuth事件返回正确的rtsp鉴权用户密码
|
||||||
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastOnRtspAuth, [](BroadcastOnRtspAuthArgs) {
|
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastOnRtspAuth, [](BroadcastOnRtspAuthArgs) {
|
||||||
DebugL << "RTSP播放鉴权:" << args.getUrl() << " " << args._param_strs;
|
DebugL << "RTSP播放鉴权:" << args.getUrl() << " " << args.param_strs;
|
||||||
DebugL << "RTSP用户:" << user_name << (must_no_encrypt ? " Base64" : " MD5") << " 方式登录";
|
DebugL << "RTSP用户:" << user_name << (must_no_encrypt ? " Base64" : " MD5") << " 方式登录";
|
||||||
string user = user_name;
|
string user = user_name;
|
||||||
//假设我们异步读取数据库
|
//假设我们异步读取数据库
|
||||||
@ -134,14 +134,14 @@ void initEventListener() {
|
|||||||
|
|
||||||
//监听rtsp/rtmp推流事件,返回结果告知是否有推流权限
|
//监听rtsp/rtmp推流事件,返回结果告知是否有推流权限
|
||||||
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaPublish, [](BroadcastMediaPublishArgs) {
|
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaPublish, [](BroadcastMediaPublishArgs) {
|
||||||
DebugL << "推流鉴权:" << args.getUrl() << " " << args._param_strs;
|
DebugL << "推流鉴权:" << args.getUrl() << " " << args.param_strs;
|
||||||
invoker("", ProtocolOption());//鉴权成功
|
invoker("", ProtocolOption());//鉴权成功
|
||||||
//invoker("this is auth failed message");//鉴权失败
|
//invoker("this is auth failed message");//鉴权失败
|
||||||
});
|
});
|
||||||
|
|
||||||
//监听rtsp/rtsps/rtmp/http-flv播放事件,返回结果告知是否有播放权限(rtsp通过kBroadcastOnRtspAuth或此事件都可以实现鉴权)
|
//监听rtsp/rtsps/rtmp/http-flv播放事件,返回结果告知是否有播放权限(rtsp通过kBroadcastOnRtspAuth或此事件都可以实现鉴权)
|
||||||
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaPlayed, [](BroadcastMediaPlayedArgs) {
|
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaPlayed, [](BroadcastMediaPlayedArgs) {
|
||||||
DebugL << "播放鉴权:" << args.getUrl() << " " << args._param_strs;
|
DebugL << "播放鉴权:" << args.getUrl() << " " << args.param_strs;
|
||||||
invoker("");//鉴权成功
|
invoker("");//鉴权成功
|
||||||
//invoker("this is auth failed message");//鉴权失败
|
//invoker("this is auth failed message");//鉴权失败
|
||||||
});
|
});
|
||||||
@ -182,14 +182,13 @@ void initEventListener() {
|
|||||||
* 你可以在这个事件触发时再去拉流,这样就可以实现按需拉流
|
* 你可以在这个事件触发时再去拉流,这样就可以实现按需拉流
|
||||||
* 拉流成功后,ZLMediaKit会把其立即转发给播放器(最大等待时间约为5秒,如果5秒都未拉流成功,播放器会播放失败)
|
* 拉流成功后,ZLMediaKit会把其立即转发给播放器(最大等待时间约为5秒,如果5秒都未拉流成功,播放器会播放失败)
|
||||||
*/
|
*/
|
||||||
DebugL << "未找到流事件:" << args.getUrl() << " " << args._param_strs;
|
DebugL << "未找到流事件:" << args.getUrl() << " " << args.param_strs;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//监听播放或推流结束时消耗流量事件
|
//监听播放或推流结束时消耗流量事件
|
||||||
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastFlowReport, [](BroadcastFlowReportArgs) {
|
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastFlowReport, [](BroadcastFlowReportArgs) {
|
||||||
DebugL << "播放器(推流器)断开连接事件:" << args.getUrl() << " " << args._param_strs
|
DebugL << "播放器(推流器)断开连接事件:" << args.getUrl() << " " << args.param_strs << "\r\n使用流量:" << totalBytes << " bytes,连接时长:" << totalDuration << "秒";
|
||||||
<< "\r\n使用流量:" << totalBytes << " bytes,连接时长:" << totalDuration << "秒";
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ MediaOriginType WebRtcPusher::getOriginType(MediaSource &sender) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string WebRtcPusher::getOriginUrl(MediaSource &sender) const {
|
string WebRtcPusher::getOriginUrl(MediaSource &sender) const {
|
||||||
return _media_info._full_url;
|
return _media_info.full_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SockInfo> WebRtcPusher::getOriginSock(MediaSource &sender) const {
|
std::shared_ptr<SockInfo> WebRtcPusher::getOriginSock(MediaSource &sender) const {
|
||||||
@ -99,7 +99,7 @@ void WebRtcPusher::onRecvRtp(MediaTrack &track, const string &rid, RtpPacket::Pt
|
|||||||
auto &src = _push_src_sim[rid];
|
auto &src = _push_src_sim[rid];
|
||||||
if (!src) {
|
if (!src) {
|
||||||
auto stream_id = rid.empty() ? _push_src->getId() : _push_src->getId() + "_" + rid;
|
auto stream_id = rid.empty() ? _push_src->getId() : _push_src->getId() + "_" + rid;
|
||||||
auto src_imp = _push_src->Clone(stream_id);
|
auto src_imp = _push_src->clone(stream_id);
|
||||||
_push_src_sim_ownership[rid] = src_imp->getOwnership();
|
_push_src_sim_ownership[rid] = src_imp->getOwnership();
|
||||||
src_imp->setListener(static_pointer_cast<WebRtcPusher>(shared_from_this()));
|
src_imp->setListener(static_pointer_cast<WebRtcPusher>(shared_from_this()));
|
||||||
src = src_imp;
|
src = src_imp;
|
||||||
|
@ -1179,7 +1179,7 @@ void push_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana
|
|||||||
|
|
||||||
RtspMediaSourceImp::Ptr push_src;
|
RtspMediaSourceImp::Ptr push_src;
|
||||||
std::shared_ptr<void> push_src_ownership;
|
std::shared_ptr<void> push_src_ownership;
|
||||||
auto src = MediaSource::find(RTSP_SCHEMA, info._vhost, info._app, info._streamid);
|
auto src = MediaSource::find(RTSP_SCHEMA, info.vhost, info.app, info.stream);
|
||||||
auto push_failed = (bool)src;
|
auto push_failed = (bool)src;
|
||||||
|
|
||||||
while (src) {
|
while (src) {
|
||||||
@ -1206,7 +1206,7 @@ void push_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!push_src) {
|
if (!push_src) {
|
||||||
push_src = std::make_shared<RtspMediaSourceImp>(info._vhost, info._app, info._streamid);
|
push_src = std::make_shared<RtspMediaSourceImp>(info);
|
||||||
push_src_ownership = push_src->getOwnership();
|
push_src_ownership = push_src->getOwnership();
|
||||||
push_src->setProtocolOption(option);
|
push_src->setProtocolOption(option);
|
||||||
}
|
}
|
||||||
@ -1235,7 +1235,7 @@ void play_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
// webrtc播放的是rtsp的源
|
// webrtc播放的是rtsp的源
|
||||||
info._schema = RTSP_SCHEMA;
|
info.schema = RTSP_SCHEMA;
|
||||||
MediaSource::findAsync(info, session_ptr, [=](const MediaSource::Ptr &src_in) mutable {
|
MediaSource::findAsync(info, session_ptr, [=](const MediaSource::Ptr &src_in) mutable {
|
||||||
auto src = dynamic_pointer_cast<RtspMediaSource>(src_in);
|
auto src = dynamic_pointer_cast<RtspMediaSource>(src_in);
|
||||||
if (!src) {
|
if (!src) {
|
||||||
@ -1243,7 +1243,7 @@ void play_plugin(Session &sender, const WebRtcArgs &args, const WebRtcPluginMana
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 还原成rtc,目的是为了hook时识别哪种播放协议
|
// 还原成rtc,目的是为了hook时识别哪种播放协议
|
||||||
info._schema = RTC_SCHEMA;
|
info.schema = RTC_SCHEMA;
|
||||||
auto rtc = WebRtcPlayer::create(EventPollerPool::Instance().getPoller(), src, info, preferred_tcp);
|
auto rtc = WebRtcPlayer::create(EventPollerPool::Instance().getPoller(), src, info, preferred_tcp);
|
||||||
cb(*rtc);
|
cb(*rtc);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user