基本完成hls相关的主要事件

This commit is contained in:
xiongziliang 2019-12-29 10:49:04 +08:00
parent 1afacdcff8
commit 54736859d4
13 changed files with 142 additions and 74 deletions

View File

@ -81,8 +81,6 @@ API_EXPORT const char* API_CALL mk_parser_get_content(const mk_parser ctx, int *
typedef void* mk_media_info; typedef void* 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["key"]
API_EXPORT const char* API_CALL mk_media_info_get_param(const mk_media_info ctx,const char *key);
//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

View File

@ -147,11 +147,7 @@ API_EXPORT const char* API_CALL mk_media_info_get_params(const mk_media_info 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_param(const mk_media_info ctx,const char *key){
assert(ctx && key);
MediaInfo *info = (MediaInfo *)ctx;
return info->_params[key].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;

View File

@ -156,9 +156,8 @@ static ApiArgsType getAllArgs(const Parser &parser) {
WarnL << "invalid Content-Type:" << parser["Content-Type"]; WarnL << "invalid Content-Type:" << parser["Content-Type"];
} }
auto &urlArgs = parser.getUrlArgs(); for (auto &pr : parser.getUrlArgs()) {
for (auto &pr : urlArgs) { allArgs[pr.first] = pr.second;
allArgs[pr.first] = HttpSession::urlDecode(pr.second);
} }
return std::move(allArgs); return std::move(allArgs);
} }

View File

@ -362,9 +362,9 @@ void MediaInfo::parse(const string &url){
if(pos != string::npos){ if(pos != string::npos){
_streamid = steamid.substr(0,pos); _streamid = steamid.substr(0,pos);
_param_strs = steamid.substr(pos + 1); _param_strs = steamid.substr(pos + 1);
_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];
} }
} else{ } else{
_streamid = steamid; _streamid = steamid;

View File

@ -72,19 +72,15 @@ public:
virtual int totalReaderCount(MediaSource &sender) = 0; virtual int totalReaderCount(MediaSource &sender) = 0;
}; };
/**
* url获取媒体相关信息
*/
class MediaInfo{ class MediaInfo{
public: public:
MediaInfo(){} MediaInfo(){}
MediaInfo(const string &url){
parse(url);
}
~MediaInfo(){} ~MediaInfo(){}
MediaInfo(const string &url){ parse(url); }
void parse(const string &url); void parse(const string &url);
string &operator[](const string &key){
return _params[key];
}
public: public:
string _schema; string _schema;
string _host; string _host;
@ -92,7 +88,6 @@ public:
string _vhost; string _vhost;
string _app; string _app;
string _streamid; string _streamid;
StrCaseMap _params;
string _param_strs; string _param_strs;
}; };
@ -118,21 +113,27 @@ public:
const string& getApp() const; const string& getApp() const;
// 流id // 流id
const string& getId() const; const string& getId() const;
// 获取所有Track
vector<Track::Ptr> getTracks(bool trackReady = true) const override;
// 获取监听者
const std::weak_ptr<MediaSourceEvent>& getListener() const;
// 设置TrackSource // 设置TrackSource
void setTrackSource(const std::weak_ptr<TrackSource> &track_src); void setTrackSource(const std::weak_ptr<TrackSource> &track_src);
// 获取所有Track
vector<Track::Ptr> getTracks(bool trackReady = true) const override;
// 设置监听者 // 设置监听者
virtual void setListener(const std::weak_ptr<MediaSourceEvent> &listener); virtual void setListener(const std::weak_ptr<MediaSourceEvent> &listener);
// 获取监听者
const std::weak_ptr<MediaSourceEvent>& getListener() const;
// 本协议获取观看者个数,可能返回本协议的观看人数,也可能返回总人数 // 本协议获取观看者个数,可能返回本协议的观看人数,也可能返回总人数
virtual int readerCount() = 0; virtual int readerCount() = 0;
// 观看者个数,包括(hls/rtsp/rtmp) // 观看者个数,包括(hls/rtsp/rtmp)
virtual int totalReaderCount(); virtual int totalReaderCount();
// 获取流当前时间戳 // 获取流当前时间戳
virtual uint32_t getTimeStamp(TrackType trackType) { return 0; }; virtual uint32_t getTimeStamp(TrackType trackType) { return 0; };
// 设置时间戳
virtual void setTimeStamp(uint32_t uiStamp) {};
// 拖动进度条 // 拖动进度条
bool seekTo(uint32_t ui32Stamp); bool seekTo(uint32_t ui32Stamp);
@ -147,12 +148,10 @@ public:
static void findAsync(const MediaInfo &info, const std::shared_ptr<TcpSession> &session, const function<void(const Ptr &src)> &cb); static void findAsync(const MediaInfo &info, const std::shared_ptr<TcpSession> &session, const function<void(const Ptr &src)> &cb);
// 遍历所有流 // 遍历所有流
static void for_each_media(const function<void(const Ptr &src)> &cb); static void for_each_media(const function<void(const Ptr &src)> &cb);
protected: protected:
void regist() ; void regist() ;
bool unregist() ; bool unregist() ;
void unregisted(); void unregisted();
private: private:
string _strSchema; string _strSchema;
string _strVhost; string _strVhost;

View File

@ -31,6 +31,7 @@
#include "Rtmp/RtmpMediaSourceMuxer.h" #include "Rtmp/RtmpMediaSourceMuxer.h"
#include "Record/Recorder.h" #include "Record/Recorder.h"
#include "Record/HlsMediaSource.h" #include "Record/HlsMediaSource.h"
#include "Record/HlsRecorder.h"
class MultiMediaSourceMuxer : public MediaSink , public std::enable_shared_from_this<MultiMediaSourceMuxer>{ class MultiMediaSourceMuxer : public MediaSink , public std::enable_shared_from_this<MultiMediaSourceMuxer>{
public: public:
@ -42,32 +43,29 @@ public:
}; };
typedef std::shared_ptr<MultiMediaSourceMuxer> Ptr; typedef std::shared_ptr<MultiMediaSourceMuxer> Ptr;
MultiMediaSourceMuxer(const string &vhost, MultiMediaSourceMuxer(const string &vhost, const string &app, const string &stream, float dur_sec = 0.0,
const string &strApp, bool enable_rtsp = true, bool enable_rtmp = true, bool enable_hls = true, bool enable_mp4 = false){
const string &strId, if (enable_rtmp) {
float dur_sec = 0.0, _rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, app, stream, std::make_shared<TitleMeta>(dur_sec));
bool bEanbleRtsp = true,
bool bEanbleRtmp = true,
bool bEanbleHls = true,
bool bEnableMp4 = false){
if (bEanbleRtmp) {
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, strApp, strId, std::make_shared<TitleMeta>(dur_sec));
} }
if (bEanbleRtsp) { if (enable_rtsp) {
_rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, strApp, strId, std::make_shared<TitleSdp>(dur_sec)); _rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, app, stream, std::make_shared<TitleSdp>(dur_sec));
} }
if(bEanbleHls){ if(enable_hls){
Recorder::startRecord(Recorder::type_hls,vhost, strApp, strId, true, false); Recorder::startRecord(Recorder::type_hls,vhost, app, stream, true, false);
} }
if(bEnableMp4){ if(enable_mp4){
Recorder::startRecord(Recorder::type_mp4,vhost, strApp, strId, true, false); Recorder::startRecord(Recorder::type_mp4,vhost, app, stream, true, false);
} }
_get_hls_player = [vhost,strApp,strId](){ _get_hls_media_source = [vhost,app,stream](){
auto src = MediaSource::find(HLS_SCHEMA,vhost,strApp,strId); auto recorder = dynamic_pointer_cast<HlsRecorder>(Recorder::getRecorder(Recorder::type_hls,vhost,app,stream));
return src ? src->readerCount() : 0; if(recorder){
return recorder->getMediaSource();
}
return MediaSource::Ptr();
}; };
} }
virtual ~MultiMediaSourceMuxer(){} virtual ~MultiMediaSourceMuxer(){}
@ -92,9 +90,15 @@ public:
if(_rtmp) { if(_rtmp) {
_rtmp->setListener(listener); _rtmp->setListener(listener);
} }
if(_rtsp) { if(_rtsp) {
_rtsp->setListener(listener); _rtsp->setListener(listener);
} }
auto hls_src = _get_hls_media_source();
if(hls_src){
hls_src->setListener(listener);
}
} }
/** /**
@ -102,10 +106,15 @@ public:
* @return * @return
*/ */
int totalReaderCount() const{ int totalReaderCount() const{
return (_rtsp ? _rtsp->readerCount() : 0) + (_rtmp ? _rtmp->readerCount() : 0) + _get_hls_player(); auto hls_src = _get_hls_media_source();
return (_rtsp ? _rtsp->readerCount() : 0) + (_rtmp ? _rtmp->readerCount() : 0) + (hls_src ? hls_src->readerCount() : 0);
} }
void setTimeStamp(uint32_t stamp){ void setTimeStamp(uint32_t stamp){
if(_rtmp){
_rtmp->setTimeStamp(stamp);
}
if(_rtsp){ if(_rtsp){
_rtsp->setTimeStamp(stamp); _rtsp->setTimeStamp(stamp);
} }
@ -154,6 +163,11 @@ protected:
_rtsp->onAllTrackReady(); _rtsp->onAllTrackReady();
} }
auto hls_src = _get_hls_media_source();
if(hls_src){
hls_src->setTrackSource(shared_from_this());
}
if(_listener){ if(_listener){
_listener->onAllTrackReady(); _listener->onAllTrackReady();
} }
@ -162,7 +176,7 @@ private:
RtmpMediaSourceMuxer::Ptr _rtmp; RtmpMediaSourceMuxer::Ptr _rtmp;
RtspMediaSourceMuxer::Ptr _rtsp; RtspMediaSourceMuxer::Ptr _rtsp;
Listener *_listener = nullptr; Listener *_listener = nullptr;
function<int()> _get_hls_player; function<MediaSource::Ptr ()> _get_hls_media_source;
}; };

View File

@ -118,8 +118,12 @@ std::shared_ptr<FILE> HlsMakerImp::makeFile(const string &file,bool setbuf) {
return ret; return ret;
} }
void HlsMakerImp::setMediaInfo(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); _media_src = std::make_shared<HlsMediaSource>(vhost, app, stream_id);
} }
MediaSource::Ptr HlsMakerImp::getMediaSource() const{
return _media_src;
}
}//namespace mediakit }//namespace mediakit

View File

@ -51,7 +51,13 @@ public:
* @param app * @param app
* @param stream_id id * @param stream_id id
*/ */
void setMediaInfo(const string &vhost, const string &app, const string &stream_id); void setMediaSource(const string &vhost, const string &app, const string &stream_id);
/**
* MediaSource
* @return
*/
MediaSource::Ptr getMediaSource() const;
protected: protected:
string onOpenSegment(int index) override ; string onOpenSegment(int index) override ;
void onDelSegment(int index) override; void onDelSegment(int index) override;

View File

@ -34,6 +34,7 @@ namespace mediakit {
class HlsRecorder : public TsMuxer { class HlsRecorder : public TsMuxer {
public: public:
typedef std::shared_ptr<HlsRecorder> Ptr;
HlsRecorder(const string &m3u8_file, const string &params){ HlsRecorder(const string &m3u8_file, const string &params){
GET_CONFIG(uint32_t,hlsNum,Hls::kSegmentNum); GET_CONFIG(uint32_t,hlsNum,Hls::kSegmentNum);
GET_CONFIG(uint32_t,hlsBufSize,Hls::kFileBufSize); GET_CONFIG(uint32_t,hlsBufSize,Hls::kFileBufSize);
@ -43,8 +44,12 @@ public:
~HlsRecorder(){ ~HlsRecorder(){
delete _hls; delete _hls;
} }
void setMediaInfo(const string &vhost, const string &app, const string &stream_id){ void setMediaSource(const string &vhost, const string &app, const string &stream_id){
_hls->setMediaInfo(vhost,app,stream_id); _hls->setMediaSource(vhost, app, stream_id);
}
MediaSource::Ptr getMediaSource() const{
return _hls->getMediaSource();
} }
protected: protected:
void onTs(const void *packet, int bytes,uint32_t timestamp,int flags) override { void onTs(const void *packet, int bytes,uint32_t timestamp,int flags) override {

View File

@ -55,7 +55,7 @@ MediaSinkInterface *createHlsRecorder(const string &strVhost_tmp, const string &
} }
m3u8FilePath = File::absolutePath(m3u8FilePath, hlsPath); m3u8FilePath = File::absolutePath(m3u8FilePath, hlsPath);
auto ret = new HlsRecorder(m3u8FilePath, params); auto ret = new HlsRecorder(m3u8FilePath, params);
ret->setMediaInfo(strVhost,strApp,strId); ret->setMediaSource(strVhost, strApp, strId);
return ret; return ret;
#else #else
return nullptr; return nullptr;
@ -159,6 +159,10 @@ public:
const string &getSchema() const{ const string &getSchema() const{
return _schema; return _schema;
} }
const MediaSinkInterface::Ptr& getRecorder() const{
return _recorder;
}
private: private:
MediaSinkInterface::Ptr _recorder; MediaSinkInterface::Ptr _recorder;
vector<Track::Ptr> _tracks; vector<Track::Ptr> _tracks;
@ -179,6 +183,16 @@ public:
return getRecordStatus_l(getRecorderKey(vhost, app, stream_id)); return getRecordStatus_l(getRecorderKey(vhost, app, stream_id));
} }
MediaSinkInterface::Ptr getRecorder(const string &vhost, const string &app, const string &stream_id) const{
auto key = getRecorderKey(vhost, app, stream_id);
lock_guard<decltype(_recorder_mtx)> lck(_recorder_mtx);
auto it = _recorder_map.find(key);
if (it == _recorder_map.end()) {
return nullptr;
}
return it->second->getRecorder();
}
int startRecord(const string &vhost, const string &app, const string &stream_id, bool waitForRecord, bool continueRecord) { int startRecord(const string &vhost, const string &app, const string &stream_id, bool waitForRecord, bool continueRecord) {
auto key = getRecorderKey(vhost, app, stream_id); auto key = getRecorderKey(vhost, app, stream_id);
lock_guard<decltype(_recorder_mtx)> lck(_recorder_mtx); lock_guard<decltype(_recorder_mtx)> lck(_recorder_mtx);
@ -187,9 +201,8 @@ public:
return 0; return 0;
} }
string schema; auto src = findMediaSource(vhost, app, stream_id);
auto tracks = findTracks(vhost, app, stream_id,schema); if (!waitForRecord && !src) {
if (!waitForRecord && tracks.empty()) {
// 暂时无法开启录制 // 暂时无法开启录制
return -1; return -1;
} }
@ -200,9 +213,17 @@ public:
return -2; return -2;
} }
auto helper = std::make_shared<RecorderHelper>(recorder, continueRecord); auto helper = std::make_shared<RecorderHelper>(recorder, continueRecord);
if(src){
auto tracks = src->getTracks(needTrackReady());
if(tracks.size()){ if(tracks.size()){
helper->attachTracks(std::move(tracks),schema); helper->attachTracks(std::move(tracks),src->getSchema());
} }
auto hls_recorder = dynamic_pointer_cast<HlsRecorder>(recorder);
if(hls_recorder){
hls_recorder->getMediaSource()->setListener(src->getListener());
}
}
_recorder_map[key] = std::move(helper); _recorder_map[key] = std::move(helper);
return 0; return 0;
} }
@ -281,25 +302,27 @@ private:
} }
// 查找MediaSource以便录制 // 查找MediaSource以便录制
vector<Track::Ptr> findTracks(const string &vhost, const string &app, const string &stream_id,string &schema) { MediaSource::Ptr findMediaSource(const string &vhost, const string &app, const string &stream_id) {
bool need_ready = needTrackReady();
auto src = MediaSource::find(RTMP_SCHEMA, vhost, app, stream_id); auto src = MediaSource::find(RTMP_SCHEMA, vhost, app, stream_id);
if (src) { if (src) {
auto ret = src->getTracks(needTrackReady()); auto ret = src->getTracks(need_ready);
if (!ret.empty()) { if (!ret.empty()) {
schema = RTMP_SCHEMA; return std::move(src);
return std::move(ret);
} }
} }
src = MediaSource::find(RTSP_SCHEMA, vhost, app, stream_id); src = MediaSource::find(RTSP_SCHEMA, vhost, app, stream_id);
if (src) { if (src) {
schema = RTSP_SCHEMA; auto ret = src->getTracks(need_ready);
return src->getTracks(needTrackReady()); if (!ret.empty()) {
return std::move(src);
} }
return vector<Track::Ptr>(); }
return nullptr;
} }
string getRecorderKey(const string &vhost, const string &app, const string &stream_id) { string getRecorderKey(const string &vhost, const string &app, const string &stream_id) const{
return vhost + "/" + app + "/" + stream_id; return vhost + "/" + app + "/" + stream_id;
} }
@ -335,7 +358,7 @@ private:
} }
} }
private: private:
recursive_mutex _recorder_mtx; mutable recursive_mutex _recorder_mtx;
NoticeCenter::Ptr _notice_center; NoticeCenter::Ptr _notice_center;
unordered_map<string, RecorderHelper::Ptr> _recorder_map; unordered_map<string, RecorderHelper::Ptr> _recorder_map;
}; };
@ -351,6 +374,17 @@ Recorder::status Recorder::getRecordStatus(Recorder::type type, const string &vh
return status_not_record; return status_not_record;
} }
std::shared_ptr<MediaSinkInterface> Recorder::getRecorder(type type, const string &vhost, const string &app, const string &stream_id){
switch (type){
case type_mp4:
return MediaSourceWatcher<type_mp4>::Instance().getRecorder(vhost,app,stream_id);
case type_hls:
return MediaSourceWatcher<type_hls>::Instance().getRecorder(vhost,app,stream_id);
}
return nullptr;
}
int Recorder::startRecord(Recorder::type type, const string &vhost, const string &app, const string &stream_id, bool waitForRecord, bool continueRecord) { int Recorder::startRecord(Recorder::type type, const string &vhost, const string &app, const string &stream_id, bool waitForRecord, bool continueRecord) {
switch (type){ switch (type){
case type_mp4: case type_mp4:

View File

@ -88,6 +88,15 @@ public:
* 退 * 退
*/ */
static void stopAll(); static void stopAll();
/**
*
* @param type hls还是MP4录制
* @param vhost
* @param app
* @param stream_id id
*/
static std::shared_ptr<MediaSinkInterface> getRecorder(type type, const string &vhost, const string &app, const string &stream_id);
private: private:
Recorder() = delete; Recorder() = delete;
~Recorder() = delete; ~Recorder() = delete;

View File

@ -49,6 +49,10 @@ public:
_mediaSouce->setListener(listener); _mediaSouce->setListener(listener);
} }
void setTimeStamp(uint32_t stamp){
_mediaSouce->setTimeStamp(stamp);
}
int readerCount() const{ int readerCount() const{
return _mediaSouce->readerCount(); return _mediaSouce->readerCount();
} }

View File

@ -140,7 +140,7 @@ public:
/** /**
* *
*/ */
virtual void setTimeStamp(uint32_t uiStamp) { void setTimeStamp(uint32_t uiStamp) override {
auto tracks = _sdp_parser.getAvailableTrack(); auto tracks = _sdp_parser.getAvailableTrack();
for (auto &track : tracks) { for (auto &track : tracks) {
track->_time_stamp = uiStamp; track->_time_stamp = uiStamp;