mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
整理MediaSource代码
This commit is contained in:
parent
68718953d4
commit
5249c24430
@ -395,25 +395,21 @@ void installWebApi() {
|
|||||||
API_REGIST(api,getMediaList,{
|
API_REGIST(api,getMediaList,{
|
||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
//获取所有MediaSource列表
|
//获取所有MediaSource列表
|
||||||
MediaSource::for_each_media([&](const string &schema,
|
MediaSource::for_each_media([&](const MediaSource::Ptr &media){
|
||||||
const string &vhost,
|
if(!allArgs["schema"].empty() && allArgs["schema"] != media->getSchema()){
|
||||||
const string &app,
|
|
||||||
const string &stream,
|
|
||||||
const MediaSource::Ptr &media){
|
|
||||||
if(!allArgs["schema"].empty() && allArgs["schema"] != schema){
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!allArgs["vhost"].empty() && allArgs["vhost"] != vhost){
|
if(!allArgs["vhost"].empty() && allArgs["vhost"] != media->getVhost()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!allArgs["app"].empty() && allArgs["app"] != app){
|
if(!allArgs["app"].empty() && allArgs["app"] != media->getApp()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Value item;
|
Value item;
|
||||||
item["schema"] = schema;
|
item["schema"] = media->getSchema();
|
||||||
item["vhost"] = vhost;
|
item["vhost"] = media->getVhost();
|
||||||
item["app"] = app;
|
item["app"] = media->getApp();
|
||||||
item["stream"] = stream;
|
item["stream"] = media->getId();
|
||||||
val["data"].append(item);
|
val["data"].append(item);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -453,21 +449,17 @@ void installWebApi() {
|
|||||||
int count_hit = 0;
|
int count_hit = 0;
|
||||||
int count_closed = 0;
|
int count_closed = 0;
|
||||||
list<MediaSource::Ptr> media_list;
|
list<MediaSource::Ptr> media_list;
|
||||||
MediaSource::for_each_media([&](const string &schema,
|
MediaSource::for_each_media([&](const MediaSource::Ptr &media){
|
||||||
const string &vhost,
|
if(!allArgs["schema"].empty() && allArgs["schema"] != media->getSchema()){
|
||||||
const string &app,
|
|
||||||
const string &stream,
|
|
||||||
const MediaSource::Ptr &media){
|
|
||||||
if(!allArgs["schema"].empty() && allArgs["schema"] != schema){
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!allArgs["vhost"].empty() && allArgs["vhost"] != vhost){
|
if(!allArgs["vhost"].empty() && allArgs["vhost"] != media->getVhost()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!allArgs["app"].empty() && allArgs["app"] != app){
|
if(!allArgs["app"].empty() && allArgs["app"] != media->getApp()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!allArgs["stream"].empty() && allArgs["stream"] != stream){
|
if(!allArgs["stream"].empty() && allArgs["stream"] != media->getId()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
++count_hit;
|
++count_hit;
|
||||||
|
@ -38,8 +38,142 @@ namespace mediakit {
|
|||||||
recursive_mutex MediaSource::g_mtxMediaSrc;
|
recursive_mutex MediaSource::g_mtxMediaSrc;
|
||||||
MediaSource::SchemaVhostAppStreamMap MediaSource::g_mapMediaSrc;
|
MediaSource::SchemaVhostAppStreamMap MediaSource::g_mapMediaSrc;
|
||||||
|
|
||||||
|
MediaSource::MediaSource(const string &strSchema, const string &strVhost, const string &strApp, const string &strId) :
|
||||||
|
_strSchema(strSchema),
|
||||||
|
_strApp(strApp),
|
||||||
|
_strId(strId) {
|
||||||
|
if (strVhost.empty()) {
|
||||||
|
_strVhost = DEFAULT_VHOST;
|
||||||
|
} else {
|
||||||
|
_strVhost = strVhost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MediaSource::findAsync(const MediaInfo &info,
|
MediaSource::~MediaSource() {
|
||||||
|
unregist();
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& MediaSource::getSchema() const {
|
||||||
|
return _strSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& MediaSource::getVhost() const {
|
||||||
|
return _strVhost;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& MediaSource::getApp() const {
|
||||||
|
//获取该源的id
|
||||||
|
return _strApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string& MediaSource::getId() const {
|
||||||
|
return _strId;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<Track::Ptr> MediaSource::getTracks(bool trackReady) const {
|
||||||
|
auto strongPtr = _track_source.lock();
|
||||||
|
if(strongPtr){
|
||||||
|
return strongPtr->getTracks(trackReady);
|
||||||
|
}
|
||||||
|
return vector<Track::Ptr>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaSource::setTrackSource(const std::weak_ptr<TrackSource> &track_src) {
|
||||||
|
_track_source = track_src;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaSource::setListener(const std::weak_ptr<MediaSourceEvent> &listener){
|
||||||
|
_listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::weak_ptr<MediaSourceEvent>& MediaSource::getListener() const{
|
||||||
|
return _listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaSource::seekTo(uint32_t ui32Stamp) {
|
||||||
|
auto listener = _listener.lock();
|
||||||
|
if(!listener){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return listener->seekTo(*this,ui32Stamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaSource::close(bool force) {
|
||||||
|
auto listener = _listener.lock();
|
||||||
|
if(!listener){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return listener->close(*this,force);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaSource::onNoneReader(){
|
||||||
|
auto listener = _listener.lock();
|
||||||
|
if(!listener){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listener->onNoneReader(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaSource::for_each_media(const function<void(const MediaSource::Ptr &src)> &cb) {
|
||||||
|
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
||||||
|
for (auto &pr0 : g_mapMediaSrc) {
|
||||||
|
for (auto &pr1 : pr0.second) {
|
||||||
|
for (auto &pr2 : pr1.second) {
|
||||||
|
for (auto &pr3 : pr2.second) {
|
||||||
|
auto src = pr3.second.lock();
|
||||||
|
if(src){
|
||||||
|
cb(src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MAP, typename FUNC>
|
||||||
|
static bool searchMedia(MAP &map,
|
||||||
|
const string &schema,
|
||||||
|
const string &vhost,
|
||||||
|
const string &app,
|
||||||
|
const string &id,
|
||||||
|
FUNC &&func) {
|
||||||
|
auto it0 = map.find(schema);
|
||||||
|
if (it0 == map.end()) {
|
||||||
|
//未找到协议
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it1 = it0->second.find(vhost);
|
||||||
|
if (it1 == it0->second.end()) {
|
||||||
|
//未找到vhost
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it2 = it1->second.find(app);
|
||||||
|
if (it2 == it1->second.end()) {
|
||||||
|
//未找到app
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto it3 = it2->second.find(id);
|
||||||
|
if (it3 == it2->second.end()) {
|
||||||
|
//未找到streamId
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return func(it0, it1, it2, it3);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MAP, typename IT0, typename IT1, typename IT2>
|
||||||
|
static void eraseIfEmpty(MAP &map, IT0 it0, IT1 it1, IT2 it2) {
|
||||||
|
if (it2->second.empty()) {
|
||||||
|
it1->second.erase(it2);
|
||||||
|
if (it1->second.empty()) {
|
||||||
|
it0->second.erase(it1);
|
||||||
|
if (it0->second.empty()) {
|
||||||
|
map.erase(it0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void findAsync_l(const MediaInfo &info,
|
||||||
const std::shared_ptr<TcpSession> &session,
|
const std::shared_ptr<TcpSession> &session,
|
||||||
bool retry,
|
bool retry,
|
||||||
const function<void(const MediaSource::Ptr &src)> &cb){
|
const function<void(const MediaSource::Ptr &src)> &cb){
|
||||||
@ -99,12 +233,17 @@ void MediaSource::findAsync(const MediaInfo &info,
|
|||||||
}
|
}
|
||||||
DebugL << "收到媒体注册事件,回复播放器:" << info._schema << "/" << info._vhost << "/" << info._app << "/" << info._streamid;
|
DebugL << "收到媒体注册事件,回复播放器:" << info._schema << "/" << info._vhost << "/" << info._app << "/" << info._streamid;
|
||||||
//再找一遍媒体源,一般能找到
|
//再找一遍媒体源,一般能找到
|
||||||
findAsync(info,strongSession,false,cb);
|
findAsync_l(info,strongSession,false,cb);
|
||||||
}, false);
|
}, false);
|
||||||
};
|
};
|
||||||
//监听媒体注册事件
|
//监听媒体注册事件
|
||||||
NoticeCenter::Instance().addListener(listener_tag, Broadcast::kBroadcastMediaChanged, onRegist);
|
NoticeCenter::Instance().addListener(listener_tag, Broadcast::kBroadcastMediaChanged, onRegist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaSource::findAsync(const MediaInfo &info, const std::shared_ptr<TcpSession> &session,const function<void(const Ptr &src)> &cb){
|
||||||
|
return findAsync_l(info, session, true, cb);
|
||||||
|
}
|
||||||
|
|
||||||
MediaSource::Ptr MediaSource::find(
|
MediaSource::Ptr MediaSource::find(
|
||||||
const string &schema,
|
const string &schema,
|
||||||
const string &vhost_tmp,
|
const string &vhost_tmp,
|
||||||
@ -124,20 +263,19 @@ MediaSource::Ptr MediaSource::find(
|
|||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
||||||
MediaSource::Ptr ret;
|
MediaSource::Ptr ret;
|
||||||
//查找某一媒体源,找到后返回
|
//查找某一媒体源,找到后返回
|
||||||
searchMedia(schema, vhost, app, id,
|
searchMedia(g_mapMediaSrc, schema, vhost, app, id, [&](SchemaVhostAppStreamMap::iterator &it0,
|
||||||
[&](SchemaVhostAppStreamMap::iterator &it0 ,
|
VhostAppStreamMap::iterator &it1,
|
||||||
VhostAppStreamMap::iterator &it1,
|
AppStreamMap::iterator &it2,
|
||||||
AppStreamMap::iterator &it2,
|
StreamMap::iterator &it3) {
|
||||||
StreamMap::iterator &it3){
|
ret = it3->second.lock();
|
||||||
ret = it3->second.lock();
|
if (!ret) {
|
||||||
if(!ret){
|
//该对象已经销毁
|
||||||
//该对象已经销毁
|
it2->second.erase(it3);
|
||||||
it2->second.erase(it3);
|
eraseIfEmpty(g_mapMediaSrc,it0, it1, it2);
|
||||||
eraseIfEmpty(it0,it1,it2);
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
return true;
|
||||||
return true;
|
});
|
||||||
});
|
|
||||||
if(!ret && bMake){
|
if(!ret && bMake){
|
||||||
//未查找媒体源,则创建一个
|
//未查找媒体源,则创建一个
|
||||||
ret = MediaReader::onMakeMediaSource(schema, vhost,app,id);
|
ret = MediaReader::onMakeMediaSource(schema, vhost,app,id);
|
||||||
@ -166,17 +304,17 @@ void MediaSource::regist() {
|
|||||||
bool MediaSource::unregist() {
|
bool MediaSource::unregist() {
|
||||||
//反注册该源
|
//反注册该源
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
||||||
return searchMedia(_strSchema, _strVhost, _strApp, _strId, [&](SchemaVhostAppStreamMap::iterator &it0 ,
|
return searchMedia(g_mapMediaSrc, _strSchema, _strVhost, _strApp, _strId,[&](SchemaVhostAppStreamMap::iterator &it0,
|
||||||
VhostAppStreamMap::iterator &it1,
|
VhostAppStreamMap::iterator &it1,
|
||||||
AppStreamMap::iterator &it2,
|
AppStreamMap::iterator &it2,
|
||||||
StreamMap::iterator &it3){
|
StreamMap::iterator &it3) {
|
||||||
auto strongMedia = it3->second.lock();
|
auto strongMedia = it3->second.lock();
|
||||||
if(strongMedia && this != strongMedia.get()){
|
if (strongMedia && this != strongMedia.get()) {
|
||||||
//不是自己,不允许反注册
|
//不是自己,不允许反注册
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
it2->second.erase(it3);
|
it2->second.erase(it3);
|
||||||
eraseIfEmpty(it0,it1,it2);
|
eraseIfEmpty(g_mapMediaSrc, it0, it1, it2);
|
||||||
unregisted();
|
unregisted();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -192,6 +330,9 @@ void MediaSource::unregisted(){
|
|||||||
*this);
|
*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////MediaInfo//////////////////////////////////////
|
||||||
|
|
||||||
void MediaInfo::parse(const string &url){
|
void MediaInfo::parse(const string &url){
|
||||||
//string url = "rtsp://127.0.0.1:8554/live/id?key=val&a=1&&b=2&vhost=vhost.com";
|
//string url = "rtsp://127.0.0.1:8554/live/id?key=val&a=1&&b=2&vhost=vhost.com";
|
||||||
auto schema_pos = url.find("://");
|
auto schema_pos = url.find("://");
|
||||||
@ -241,6 +382,8 @@ void MediaInfo::parse(const string &url){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////MediaSourceEvent//////////////////////////////////////
|
||||||
|
|
||||||
void MediaSourceEvent::onNoneReader(MediaSource &sender){
|
void MediaSourceEvent::onNoneReader(MediaSource &sender){
|
||||||
//没有任何读取器消费该源,表明该源可以关闭了
|
//没有任何读取器消费该源,表明该源可以关闭了
|
||||||
WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId();
|
WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId();
|
||||||
|
@ -45,7 +45,7 @@ using namespace toolkit;
|
|||||||
|
|
||||||
namespace toolkit{
|
namespace toolkit{
|
||||||
class TcpSession;
|
class TcpSession;
|
||||||
}//namespace toolkit
|
}// namespace toolkit
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
@ -54,17 +54,18 @@ class MediaSourceEvent{
|
|||||||
public:
|
public:
|
||||||
MediaSourceEvent(){};
|
MediaSourceEvent(){};
|
||||||
virtual ~MediaSourceEvent(){};
|
virtual ~MediaSourceEvent(){};
|
||||||
public:
|
|
||||||
|
// 通知拖动进度条
|
||||||
virtual bool seekTo(MediaSource &sender,uint32_t ui32Stamp){
|
virtual bool seekTo(MediaSource &sender,uint32_t ui32Stamp){
|
||||||
//拖动进度条
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知其停止推流
|
||||||
virtual bool close(MediaSource &sender,bool force) {
|
virtual bool close(MediaSource &sender,bool force) {
|
||||||
//通知其停止推流
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知无人观看
|
||||||
virtual void onNoneReader(MediaSource &sender);
|
virtual void onNoneReader(MediaSource &sender);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,6 +93,9 @@ public:
|
|||||||
string _param_strs;
|
string _param_strs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 媒体源,任何rtsp/rtmp的直播流都源自该对象
|
||||||
|
*/
|
||||||
class MediaSource: public TrackSource, public enable_shared_from_this<MediaSource> {
|
class MediaSource: public TrackSource, public enable_shared_from_this<MediaSource> {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<MediaSource> Ptr;
|
typedef std::shared_ptr<MediaSource> Ptr;
|
||||||
@ -100,152 +104,59 @@ public:
|
|||||||
typedef unordered_map<string, AppStreamMap > VhostAppStreamMap;
|
typedef unordered_map<string, AppStreamMap > VhostAppStreamMap;
|
||||||
typedef unordered_map<string, VhostAppStreamMap > SchemaVhostAppStreamMap;
|
typedef unordered_map<string, VhostAppStreamMap > SchemaVhostAppStreamMap;
|
||||||
|
|
||||||
MediaSource(const string &strSchema,
|
MediaSource(const string &strSchema, const string &strVhost, const string &strApp, const string &strId) ;
|
||||||
const string &strVhost,
|
virtual ~MediaSource() ;
|
||||||
const string &strApp,
|
|
||||||
const string &strId) :
|
|
||||||
_strSchema(strSchema),
|
|
||||||
_strApp(strApp),
|
|
||||||
_strId(strId) {
|
|
||||||
if(strVhost.empty()){
|
|
||||||
_strVhost = DEFAULT_VHOST;
|
|
||||||
}else{
|
|
||||||
_strVhost = strVhost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual ~MediaSource() {
|
|
||||||
unregist();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Ptr find(const string &schema,
|
// 获取协议类型
|
||||||
const string &vhost,
|
const string& getSchema() const;
|
||||||
const string &app,
|
// 虚拟主机
|
||||||
const string &id,
|
const string& getVhost() const;
|
||||||
bool bMake = true) ;
|
// 应用名
|
||||||
|
const string& getApp() const;
|
||||||
static void findAsync(const MediaInfo &info,
|
// 流id
|
||||||
const std::shared_ptr<TcpSession> &session,
|
const string& getId() const;
|
||||||
bool retry,
|
// 获取所有Track
|
||||||
const function<void(const MediaSource::Ptr &src)> &cb);
|
vector<Track::Ptr> getTracks(bool trackReady = true) const override;
|
||||||
|
// 获取监听者
|
||||||
const string& getSchema() const {
|
const std::weak_ptr<MediaSourceEvent>& getListener() const;
|
||||||
return _strSchema;
|
|
||||||
}
|
|
||||||
const string& getVhost() const {
|
|
||||||
return _strVhost;
|
|
||||||
}
|
|
||||||
const string& getApp() const {
|
|
||||||
//获取该源的id
|
|
||||||
return _strApp;
|
|
||||||
}
|
|
||||||
const string& getId() const {
|
|
||||||
return _strId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool seekTo(uint32_t ui32Stamp) {
|
|
||||||
auto listener = _listener.lock();
|
|
||||||
if(!listener){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return listener->seekTo(*this,ui32Stamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 设置TrackSource
|
||||||
|
void setTrackSource(const std::weak_ptr<TrackSource> &track_src);
|
||||||
|
// 设置监听者
|
||||||
|
virtual void setListener(const std::weak_ptr<MediaSourceEvent> &listener);
|
||||||
|
// 获取观看者个数
|
||||||
|
virtual int readerCount() = 0;
|
||||||
|
// 获取流当前时间戳
|
||||||
virtual uint32_t getTimeStamp(TrackType trackType) = 0;
|
virtual uint32_t getTimeStamp(TrackType trackType) = 0;
|
||||||
|
|
||||||
bool close(bool force) {
|
// 拖动进度条
|
||||||
auto listener = _listener.lock();
|
bool seekTo(uint32_t ui32Stamp);
|
||||||
if(!listener){
|
// 关闭该流
|
||||||
return false;
|
bool close(bool force);
|
||||||
}
|
// 该流无人观看
|
||||||
return listener->close(*this,force);
|
void onNoneReader();
|
||||||
}
|
|
||||||
|
|
||||||
void onNoneReader(){
|
// 同步查找流
|
||||||
auto listener = _listener.lock();
|
static Ptr find(const string &schema, const string &vhost, const string &app, const string &id, bool bMake = true) ;
|
||||||
if(!listener){
|
// 异步查找流
|
||||||
return;
|
static void findAsync(const MediaInfo &info, const std::shared_ptr<TcpSession> &session, const function<void(const Ptr &src)> &cb);
|
||||||
}
|
// 遍历所有流
|
||||||
listener->onNoneReader(*this);
|
static void for_each_media(const function<void(const Ptr &src)> &cb);
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setListener(const std::weak_ptr<MediaSourceEvent> &listener){
|
|
||||||
_listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::weak_ptr<MediaSourceEvent> getListener(){
|
|
||||||
return _listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FUN>
|
|
||||||
static void for_each_media(FUN && fun){
|
|
||||||
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
|
|
||||||
for (auto &pr0 : g_mapMediaSrc){
|
|
||||||
for(auto &pr1 : pr0.second){
|
|
||||||
for(auto &pr2 : pr1.second){
|
|
||||||
for(auto &pr3 : pr2.second){
|
|
||||||
fun(pr0.first,pr1.first,pr2.first,pr3.first,pr3.second.lock());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int readerCount() = 0;
|
|
||||||
protected:
|
protected:
|
||||||
void regist() ;
|
void regist() ;
|
||||||
bool unregist() ;
|
bool unregist() ;
|
||||||
private:
|
|
||||||
template <typename FUN>
|
|
||||||
static bool searchMedia(const string &schema,
|
|
||||||
const string &vhost,
|
|
||||||
const string &app,
|
|
||||||
const string &id,
|
|
||||||
FUN &&fun){
|
|
||||||
auto it0 = g_mapMediaSrc.find(schema);
|
|
||||||
if (it0 == g_mapMediaSrc.end()) {
|
|
||||||
//未找到协议
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto it1 = it0->second.find(vhost);
|
|
||||||
if(it1 == it0->second.end()){
|
|
||||||
//未找到vhost
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto it2 = it1->second.find(app);
|
|
||||||
if(it2 == it1->second.end()){
|
|
||||||
//未找到app
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto it3 = it2->second.find(id);
|
|
||||||
if(it3 == it2->second.end()){
|
|
||||||
//未找到streamId
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return fun(it0,it1,it2,it3);
|
|
||||||
}
|
|
||||||
template <typename IT0,typename IT1,typename IT2>
|
|
||||||
static void eraseIfEmpty(IT0 it0,IT1 it1,IT2 it2){
|
|
||||||
if(it2->second.empty()){
|
|
||||||
it1->second.erase(it2);
|
|
||||||
if(it1->second.empty()){
|
|
||||||
it0->second.erase(it1);
|
|
||||||
if(it0->second.empty()){
|
|
||||||
g_mapMediaSrc.erase(it0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void unregisted();
|
void unregisted();
|
||||||
protected:
|
|
||||||
std::weak_ptr<MediaSourceEvent> _listener;
|
|
||||||
private:
|
private:
|
||||||
string _strSchema;//协议类型
|
string _strSchema;
|
||||||
string _strVhost; //vhost
|
string _strVhost;
|
||||||
string _strApp; //媒体app
|
string _strApp;
|
||||||
string _strId; //媒体id
|
string _strId;
|
||||||
static SchemaVhostAppStreamMap g_mapMediaSrc; //静态的媒体源表
|
std::weak_ptr<MediaSourceEvent> _listener;
|
||||||
static recursive_mutex g_mtxMediaSrc; //访问静态的媒体源表的互斥锁
|
weak_ptr<TrackSource> _track_source;
|
||||||
|
static SchemaVhostAppStreamMap g_mapMediaSrc;
|
||||||
|
static recursive_mutex g_mtxMediaSrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "Rtmp/RtmpMediaSourceMuxer.h"
|
#include "Rtmp/RtmpMediaSourceMuxer.h"
|
||||||
#include "MediaFile/MediaRecorder.h"
|
#include "MediaFile/MediaRecorder.h"
|
||||||
|
|
||||||
class MultiMediaSourceMuxer : public MediaSink{
|
class MultiMediaSourceMuxer : public MediaSink , public std::enable_shared_from_this<MultiMediaSourceMuxer>{
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<MultiMediaSourceMuxer> Ptr;
|
typedef std::shared_ptr<MultiMediaSourceMuxer> Ptr;
|
||||||
|
|
||||||
@ -128,9 +128,11 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void onAllTrackReady() override{
|
void onAllTrackReady() override{
|
||||||
if(_rtmp) {
|
if(_rtmp) {
|
||||||
|
_rtmp->setTrackSource(shared_from_this());
|
||||||
_rtmp->onAllTrackReady();
|
_rtmp->onAllTrackReady();
|
||||||
}
|
}
|
||||||
if(_rtsp) {
|
if(_rtsp) {
|
||||||
|
_rtmp->setTrackSource(shared_from_this());
|
||||||
_rtsp->onAllTrackReady();
|
_rtsp->onAllTrackReady();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,9 +141,7 @@ public:
|
|||||||
* @param trackReady 是否获取全部已经准备好的Track
|
* @param trackReady 是否获取全部已经准备好的Track
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual vector<Track::Ptr> getTracks(bool trackReady = true) const {
|
virtual vector<Track::Ptr> getTracks(bool trackReady = true) const = 0;
|
||||||
return vector<Track::Ptr>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取特定Track
|
* 获取特定Track
|
||||||
|
@ -197,7 +197,7 @@ bool HttpSession::checkLiveFlvStream(const function<void()> &cb){
|
|||||||
bool bClose = !strcasecmp(_parser["Connection"].data(),"close");
|
bool bClose = !strcasecmp(_parser["Connection"].data(),"close");
|
||||||
|
|
||||||
weak_ptr<HttpSession> weakSelf = dynamic_pointer_cast<HttpSession>(shared_from_this());
|
weak_ptr<HttpSession> weakSelf = dynamic_pointer_cast<HttpSession>(shared_from_this());
|
||||||
MediaSource::findAsync(_mediaInfo,weakSelf.lock(), true,[weakSelf,bClose,this,cb](const MediaSource::Ptr &src){
|
MediaSource::findAsync(_mediaInfo,weakSelf.lock(),[weakSelf,bClose,this,cb](const MediaSource::Ptr &src){
|
||||||
auto strongSelf = weakSelf.lock();
|
auto strongSelf = weakSelf.lock();
|
||||||
if(!strongSelf){
|
if(!strongSelf){
|
||||||
//本对象已经销毁
|
//本对象已经销毁
|
||||||
|
@ -42,13 +42,13 @@ MediaPlayer::MediaPlayer(const EventPoller::Ptr &poller) {
|
|||||||
MediaPlayer::~MediaPlayer() {
|
MediaPlayer::~MediaPlayer() {
|
||||||
}
|
}
|
||||||
void MediaPlayer::play(const string &strUrl) {
|
void MediaPlayer::play(const string &strUrl) {
|
||||||
_parser = PlayerBase::createPlayer(_poller,strUrl);
|
_delegate = PlayerBase::createPlayer(_poller,strUrl);
|
||||||
_parser->setOnShutdown(_shutdownCB);
|
_delegate->setOnShutdown(_shutdownCB);
|
||||||
_parser->setOnPlayResult(_playResultCB);
|
_delegate->setOnPlayResult(_playResultCB);
|
||||||
_parser->setOnResume(_resumeCB);
|
_delegate->setOnResume(_resumeCB);
|
||||||
_parser->setMediaSouce(_pMediaSrc);
|
_delegate->setMediaSouce(_pMediaSrc);
|
||||||
_parser->mINI::operator=(*this);
|
_delegate->mINI::operator=(*this);
|
||||||
_parser->play(strUrl);
|
_delegate->play(strUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventPoller::Ptr MediaPlayer::getPoller(){
|
EventPoller::Ptr MediaPlayer::getPoller(){
|
||||||
@ -56,14 +56,14 @@ EventPoller::Ptr MediaPlayer::getPoller(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MediaPlayer::pause(bool bPause) {
|
void MediaPlayer::pause(bool bPause) {
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
_parser->pause(bPause);
|
_delegate->pause(bPause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaPlayer::teardown() {
|
void MediaPlayer::teardown() {
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
_parser->teardown();
|
_delegate->teardown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,13 @@ public:
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual float getPacketLossRate(TrackType trackType) const {return 0; }
|
virtual float getPacketLossRate(TrackType trackType) const {return 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有track
|
||||||
|
*/
|
||||||
|
vector<Track::Ptr> getTracks(bool trackReady = true) const override{
|
||||||
|
return vector<Track::Ptr>();
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
virtual void onShutdown(const SockException &ex) {}
|
virtual void onShutdown(const SockException &ex) {}
|
||||||
virtual void onPlayResult(const SockException &ex) {}
|
virtual void onPlayResult(const SockException &ex) {}
|
||||||
@ -136,9 +143,8 @@ protected:
|
|||||||
virtual void onResume(){};
|
virtual void onResume(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Parent,typename Parser>
|
template<typename Parent,typename Delegate>
|
||||||
class PlayerImp : public Parent
|
class PlayerImp : public Parent {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<PlayerImp> Ptr;
|
typedef std::shared_ptr<PlayerImp> Ptr;
|
||||||
|
|
||||||
@ -147,62 +153,62 @@ public:
|
|||||||
|
|
||||||
virtual ~PlayerImp(){}
|
virtual ~PlayerImp(){}
|
||||||
void setOnShutdown(const function<void(const SockException &)> &cb) override {
|
void setOnShutdown(const function<void(const SockException &)> &cb) override {
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
_parser->setOnShutdown(cb);
|
_delegate->setOnShutdown(cb);
|
||||||
}
|
}
|
||||||
_shutdownCB = cb;
|
_shutdownCB = cb;
|
||||||
}
|
}
|
||||||
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
|
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
_parser->setOnPlayResult(cb);
|
_delegate->setOnPlayResult(cb);
|
||||||
}
|
}
|
||||||
_playResultCB = cb;
|
_playResultCB = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOnResume(const function<void()> &cb) override {
|
void setOnResume(const function<void()> &cb) override {
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
_parser->setOnResume(cb);
|
_delegate->setOnResume(cb);
|
||||||
}
|
}
|
||||||
_resumeCB = cb;
|
_resumeCB = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInited(int analysisMs) override{
|
bool isInited(int analysisMs) override{
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
return _parser->isInited(analysisMs);
|
return _delegate->isInited(analysisMs);
|
||||||
}
|
}
|
||||||
return PlayerBase::isInited(analysisMs);
|
return Parent::isInited(analysisMs);
|
||||||
}
|
}
|
||||||
float getDuration() const override {
|
float getDuration() const override {
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
return _parser->getDuration();
|
return _delegate->getDuration();
|
||||||
}
|
}
|
||||||
return PlayerBase::getDuration();
|
return Parent::getDuration();
|
||||||
}
|
}
|
||||||
float getProgress() const override{
|
float getProgress() const override{
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
return _parser->getProgress();
|
return _delegate->getProgress();
|
||||||
}
|
}
|
||||||
return PlayerBase::getProgress();
|
return Parent::getProgress();
|
||||||
}
|
}
|
||||||
void seekTo(float fProgress) override{
|
void seekTo(float fProgress) override{
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
return _parser->seekTo(fProgress);
|
return _delegate->seekTo(fProgress);
|
||||||
}
|
}
|
||||||
return PlayerBase::seekTo(fProgress);
|
return Parent::seekTo(fProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMediaSouce(const MediaSource::Ptr & src) override {
|
void setMediaSouce(const MediaSource::Ptr & src) override {
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
_parser->setMediaSouce(src);
|
_delegate->setMediaSouce(src);
|
||||||
}
|
}
|
||||||
_pMediaSrc = src;
|
_pMediaSrc = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Track::Ptr> getTracks(bool trackReady = true) const override{
|
vector<Track::Ptr> getTracks(bool trackReady = true) const override{
|
||||||
if (_parser) {
|
if (_delegate) {
|
||||||
return _parser->getTracks(trackReady);
|
return _delegate->getTracks(trackReady);
|
||||||
}
|
}
|
||||||
return PlayerBase::getTracks(trackReady);
|
return Parent::getTracks(trackReady);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void onShutdown(const SockException &ex) override {
|
void onShutdown(const SockException &ex) override {
|
||||||
@ -228,7 +234,7 @@ protected:
|
|||||||
function<void(const SockException &ex)> _shutdownCB;
|
function<void(const SockException &ex)> _shutdownCB;
|
||||||
function<void(const SockException &ex)> _playResultCB;
|
function<void(const SockException &ex)> _playResultCB;
|
||||||
function<void()> _resumeCB;
|
function<void()> _resumeCB;
|
||||||
std::shared_ptr<Parser> _parser;
|
std::shared_ptr<Delegate> _delegate;
|
||||||
MediaSource::Ptr _pMediaSrc;
|
MediaSource::Ptr _pMediaSrc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,13 +138,13 @@ void PlayerProxy::play(const string &strUrlTmp) {
|
|||||||
MediaPlayer::play(strUrlTmp);
|
MediaPlayer::play(strUrlTmp);
|
||||||
|
|
||||||
MediaSource::Ptr mediaSource;
|
MediaSource::Ptr mediaSource;
|
||||||
if(dynamic_pointer_cast<RtspPlayer>(_parser)){
|
if(dynamic_pointer_cast<RtspPlayer>(_delegate)){
|
||||||
//rtsp拉流
|
//rtsp拉流
|
||||||
GET_CONFIG(bool,directProxy,Rtsp::kDirectProxy);
|
GET_CONFIG(bool,directProxy,Rtsp::kDirectProxy);
|
||||||
if(directProxy && _bEnableRtsp){
|
if(directProxy && _bEnableRtsp){
|
||||||
mediaSource = std::make_shared<RtspMediaSource>(_strVhost,_strApp,_strSrc);
|
mediaSource = std::make_shared<RtspMediaSource>(_strVhost,_strApp,_strSrc);
|
||||||
}
|
}
|
||||||
} else if(dynamic_pointer_cast<RtmpPlayer>(_parser)){
|
} else if(dynamic_pointer_cast<RtmpPlayer>(_delegate)){
|
||||||
//rtmp拉流
|
//rtmp拉流
|
||||||
if(_bEnableRtmp){
|
if(_bEnableRtmp){
|
||||||
mediaSource = std::make_shared<RtmpMediaSource>(_strVhost,_strApp,_strSrc);
|
mediaSource = std::make_shared<RtmpMediaSource>(_strVhost,_strApp,_strSrc);
|
||||||
|
@ -56,6 +56,11 @@ public:
|
|||||||
void onAllTrackReady(){
|
void onAllTrackReady(){
|
||||||
_mediaSouce->onGetMetaData(getMetadata());
|
_mediaSouce->onGetMetaData(getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置TrackSource
|
||||||
|
void setTrackSource(const std::weak_ptr<TrackSource> &track_src){
|
||||||
|
_mediaSouce->setTrackSource(track_src);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
RtmpMediaSource::Ptr _mediaSouce;
|
RtmpMediaSource::Ptr _mediaSouce;
|
||||||
};
|
};
|
||||||
|
@ -67,18 +67,18 @@ private:
|
|||||||
if(_pRtmpMediaSrc){
|
if(_pRtmpMediaSrc){
|
||||||
_pRtmpMediaSrc->onGetMetaData(val);
|
_pRtmpMediaSrc->onGetMetaData(val);
|
||||||
}
|
}
|
||||||
_parser.reset(new RtmpDemuxer(val));
|
_delegate.reset(new RtmpDemuxer(val));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void onMediaData(const RtmpPacket::Ptr &chunkData) override {
|
void onMediaData(const RtmpPacket::Ptr &chunkData) override {
|
||||||
if(_pRtmpMediaSrc){
|
if(_pRtmpMediaSrc){
|
||||||
_pRtmpMediaSrc->onWrite(chunkData);
|
_pRtmpMediaSrc->onWrite(chunkData);
|
||||||
}
|
}
|
||||||
if(!_parser){
|
if(!_delegate){
|
||||||
//这个流没有metadata
|
//这个流没有metadata
|
||||||
_parser.reset(new RtmpDemuxer());
|
_delegate.reset(new RtmpDemuxer());
|
||||||
}
|
}
|
||||||
_parser->inputRtmp(chunkData);
|
_delegate->inputRtmp(chunkData);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
RtmpMediaSource::Ptr _pRtmpMediaSrc;
|
RtmpMediaSource::Ptr _pRtmpMediaSrc;
|
||||||
|
@ -319,7 +319,7 @@ void RtmpSession::doPlayResponse(const string &err,const std::function<void(bool
|
|||||||
|
|
||||||
//鉴权成功,查找媒体源并回复
|
//鉴权成功,查找媒体源并回复
|
||||||
weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this());
|
weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this());
|
||||||
MediaSource::findAsync(_mediaInfo,weakSelf.lock(), true,[weakSelf,cb](const MediaSource::Ptr &src){
|
MediaSource::findAsync(_mediaInfo,weakSelf.lock(),[weakSelf,cb](const MediaSource::Ptr &src){
|
||||||
auto rtmp_src = dynamic_pointer_cast<RtmpMediaSource>(src);
|
auto rtmp_src = dynamic_pointer_cast<RtmpMediaSource>(src);
|
||||||
auto strongSelf = weakSelf.lock();
|
auto strongSelf = weakSelf.lock();
|
||||||
if(strongSelf){
|
if(strongSelf){
|
||||||
|
@ -52,7 +52,8 @@ public:
|
|||||||
RtmpToRtspMediaSource(const string &vhost,
|
RtmpToRtspMediaSource(const string &vhost,
|
||||||
const string &app,
|
const string &app,
|
||||||
const string &id,
|
const string &id,
|
||||||
int ringSize = 0) : RtmpMediaSource(vhost, app, id,ringSize){
|
int ringSize = 0) :
|
||||||
|
RtmpMediaSource(vhost, app, id,ringSize){
|
||||||
}
|
}
|
||||||
virtual ~RtmpToRtspMediaSource(){}
|
virtual ~RtmpToRtspMediaSource(){}
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ public:
|
|||||||
_muxer->addTrack(track);
|
_muxer->addTrack(track);
|
||||||
track->addDelegate(_muxer);
|
track->addDelegate(_muxer);
|
||||||
}
|
}
|
||||||
_muxer->setListener(_listener);
|
_muxer->setListener(getListener());
|
||||||
}
|
}
|
||||||
RtmpMediaSource::onWrite(pkt,key_pos);
|
RtmpMediaSource::onWrite(pkt,key_pos);
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,11 @@ public:
|
|||||||
void onAllTrackReady(){
|
void onAllTrackReady(){
|
||||||
_mediaSouce->onGetSDP(getSdp());
|
_mediaSouce->onGetSDP(getSdp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置TrackSource
|
||||||
|
void setTrackSource(const std::weak_ptr<TrackSource> &track_src){
|
||||||
|
_mediaSouce->setTrackSource(track_src);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
RtspMediaSource::Ptr _mediaSouce;
|
RtspMediaSource::Ptr _mediaSouce;
|
||||||
};
|
};
|
||||||
|
@ -66,16 +66,16 @@ private:
|
|||||||
if(_pRtspMediaSrc){
|
if(_pRtspMediaSrc){
|
||||||
_pRtspMediaSrc->onGetSDP(sdp);
|
_pRtspMediaSrc->onGetSDP(sdp);
|
||||||
}
|
}
|
||||||
_parser.reset(new RtspDemuxer(sdp));
|
_delegate.reset(new RtspDemuxer(sdp));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void onRecvRTP(const RtpPacket::Ptr &rtp, const SdpTrack::Ptr &track) override {
|
void onRecvRTP(const RtpPacket::Ptr &rtp, const SdpTrack::Ptr &track) override {
|
||||||
if(_pRtspMediaSrc){
|
if(_pRtspMediaSrc){
|
||||||
_pRtspMediaSrc->onWrite(rtp,true);
|
_pRtspMediaSrc->onWrite(rtp,true);
|
||||||
}
|
}
|
||||||
_parser->inputRtp(rtp);
|
_delegate->inputRtp(rtp);
|
||||||
|
|
||||||
if(_maxAnalysisMS && _parser->isInited(_maxAnalysisMS)){
|
if(_maxAnalysisMS && _delegate->isInited(_maxAnalysisMS)){
|
||||||
PlayerImp<RtspPlayer,RtspDemuxer>::onPlayResult(SockException(Err_success,"play rtsp success"));
|
PlayerImp<RtspPlayer,RtspDemuxer>::onPlayResult(SockException(Err_success,"play rtsp success"));
|
||||||
_maxAnalysisMS = 0;
|
_maxAnalysisMS = 0;
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ private:
|
|||||||
//如果超过这个时间还未获取成功,那么会强制触发onPlayResult事件(虽然此时有些track还未初始化成功)
|
//如果超过这个时间还未获取成功,那么会强制触发onPlayResult事件(虽然此时有些track还未初始化成功)
|
||||||
void onPlayResult(const SockException &ex) override {
|
void onPlayResult(const SockException &ex) override {
|
||||||
//isInited判断条件:无超时
|
//isInited判断条件:无超时
|
||||||
if(ex || _parser->isInited(0)){
|
if(ex || _delegate->isInited(0)){
|
||||||
//已经初始化成功,说明sdp里面有完善的信息
|
//已经初始化成功,说明sdp里面有完善的信息
|
||||||
PlayerImp<RtspPlayer,RtspDemuxer>::onPlayResult(ex);
|
PlayerImp<RtspPlayer,RtspDemuxer>::onPlayResult(ex);
|
||||||
}else{
|
}else{
|
||||||
|
@ -371,7 +371,7 @@ void RtspSession::handleReq_Describe(const Parser &parser) {
|
|||||||
void RtspSession::onAuthSuccess() {
|
void RtspSession::onAuthSuccess() {
|
||||||
TraceP(this);
|
TraceP(this);
|
||||||
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
||||||
MediaSource::findAsync(_mediaInfo,weakSelf.lock(), true,[weakSelf](const MediaSource::Ptr &src){
|
MediaSource::findAsync(_mediaInfo,weakSelf.lock(),[weakSelf](const MediaSource::Ptr &src){
|
||||||
auto strongSelf = weakSelf.lock();
|
auto strongSelf = weakSelf.lock();
|
||||||
if(!strongSelf){
|
if(!strongSelf){
|
||||||
return;
|
return;
|
||||||
|
@ -43,7 +43,8 @@ public:
|
|||||||
RtspToRtmpMediaSource(const string &vhost,
|
RtspToRtmpMediaSource(const string &vhost,
|
||||||
const string &app,
|
const string &app,
|
||||||
const string &id,
|
const string &id,
|
||||||
int ringSize = 0) : RtspMediaSource(vhost, app, id,ringSize) {
|
int ringSize = 0)
|
||||||
|
: RtspMediaSource(vhost, app, id,ringSize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~RtspToRtmpMediaSource() {}
|
virtual ~RtspToRtmpMediaSource() {}
|
||||||
@ -69,7 +70,7 @@ public:
|
|||||||
_muxer->addTrack(track);
|
_muxer->addTrack(track);
|
||||||
track->addDelegate(_muxer);
|
track->addDelegate(_muxer);
|
||||||
}
|
}
|
||||||
_muxer->setListener(_listener);
|
_muxer->setListener(getListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RtspMediaSource::onWrite(rtp, bKeyPos);
|
RtspMediaSource::onWrite(rtp, bKeyPos);
|
||||||
|
@ -16,39 +16,35 @@ class CMD_media: public CMD {
|
|||||||
public:
|
public:
|
||||||
CMD_media(){
|
CMD_media(){
|
||||||
_parser.reset(new OptionParser([](const std::shared_ptr<ostream> &stream,mINI &ini){
|
_parser.reset(new OptionParser([](const std::shared_ptr<ostream> &stream,mINI &ini){
|
||||||
MediaSource::for_each_media([&](const string &schema,
|
MediaSource::for_each_media([&](const MediaSource::Ptr &media){
|
||||||
const string &vhost,
|
if(!ini["schema"].empty() && ini["schema"] != media->getSchema()){
|
||||||
const string &app,
|
|
||||||
const string &streamid,
|
|
||||||
const MediaSource::Ptr &media){
|
|
||||||
if(!ini["schema"].empty() && ini["schema"] != schema){
|
|
||||||
//筛选协议不匹配
|
//筛选协议不匹配
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!ini["vhost"].empty() && ini["vhost"] != vhost){
|
if(!ini["vhost"].empty() && ini["vhost"] != media->getVhost()){
|
||||||
//筛选虚拟主机不匹配
|
//筛选虚拟主机不匹配
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!ini["app"].empty() && ini["app"] != app){
|
if(!ini["app"].empty() && ini["app"] != media->getApp()){
|
||||||
//筛选应用名不匹配
|
//筛选应用名不匹配
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!ini["stream"].empty() && ini["stream"] != streamid){
|
if(!ini["stream"].empty() && ini["stream"] != media->getId()){
|
||||||
//流id不匹配
|
//流id不匹配
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(ini.find("list") != ini.end()){
|
if(ini.find("list") != ini.end()){
|
||||||
//列出源
|
//列出源
|
||||||
(*stream) << "\t"
|
(*stream) << "\t"
|
||||||
<< schema << "/"
|
<< media->getSchema() << "/"
|
||||||
<< vhost << "/"
|
<< media->getVhost() << "/"
|
||||||
<< app << "/"
|
<< media->getApp() << "/"
|
||||||
<< streamid
|
<< media->getId()
|
||||||
<< "\r\n";
|
<< "\r\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventPollerPool::Instance().getPoller()->async([ini,media,stream,schema,vhost,app,streamid](){
|
EventPollerPool::Instance().getPoller()->async([ini,media,stream](){
|
||||||
if(ini.find("kick") != ini.end()){
|
if(ini.find("kick") != ini.end()){
|
||||||
//踢出源
|
//踢出源
|
||||||
do{
|
do{
|
||||||
@ -59,18 +55,18 @@ public:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(*stream) << "\t踢出成功:"
|
(*stream) << "\t踢出成功:"
|
||||||
<< schema << "/"
|
<< media->getSchema() << "/"
|
||||||
<< vhost << "/"
|
<< media->getVhost() << "/"
|
||||||
<< app << "/"
|
<< media->getApp() << "/"
|
||||||
<< streamid
|
<< media->getId()
|
||||||
<< "\r\n";
|
<< "\r\n";
|
||||||
return;
|
return;
|
||||||
}while(0);
|
}while(0);
|
||||||
(*stream) << "\t踢出失败:"
|
(*stream) << "\t踢出失败:"
|
||||||
<< schema << "/"
|
<< media->getSchema() << "/"
|
||||||
<< vhost << "/"
|
<< media->getVhost() << "/"
|
||||||
<< app << "/"
|
<< media->getApp() << "/"
|
||||||
<< streamid
|
<< media->getId()
|
||||||
<< "\r\n";
|
<< "\r\n";
|
||||||
}
|
}
|
||||||
},false);
|
},false);
|
||||||
|
Loading…
Reference in New Issue
Block a user