mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-25 20:27:34 +08:00
基本完成hls相关的主要事件
This commit is contained in:
parent
1afacdcff8
commit
54736859d4
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -135,30 +135,29 @@ public:
|
|||||||
//获取HTTP请求中url参数、content参数
|
//获取HTTP请求中url参数、content参数
|
||||||
static ApiArgsType getAllArgs(const Parser &parser) {
|
static ApiArgsType getAllArgs(const Parser &parser) {
|
||||||
ApiArgsType allArgs;
|
ApiArgsType allArgs;
|
||||||
if(parser["Content-Type"].find("application/x-www-form-urlencoded") == 0){
|
if (parser["Content-Type"].find("application/x-www-form-urlencoded") == 0) {
|
||||||
auto contentArgs = parser.parseArgs(parser.Content());
|
auto contentArgs = parser.parseArgs(parser.Content());
|
||||||
for (auto &pr : contentArgs) {
|
for (auto &pr : contentArgs) {
|
||||||
allArgs[pr.first] = HttpSession::urlDecode(pr.second);
|
allArgs[pr.first] = HttpSession::urlDecode(pr.second);
|
||||||
}
|
}
|
||||||
}else if(parser["Content-Type"].find("application/json") == 0){
|
} else if (parser["Content-Type"].find("application/json") == 0) {
|
||||||
try {
|
try {
|
||||||
stringstream ss(parser.Content());
|
stringstream ss(parser.Content());
|
||||||
Value jsonArgs;
|
Value jsonArgs;
|
||||||
ss >> jsonArgs;
|
ss >> jsonArgs;
|
||||||
auto keys = jsonArgs.getMemberNames();
|
auto keys = jsonArgs.getMemberNames();
|
||||||
for (auto key = keys.begin(); key != keys.end(); ++key){
|
for (auto key = keys.begin(); key != keys.end(); ++key) {
|
||||||
allArgs[*key] = jsonArgs[*key].asString();
|
allArgs[*key] = jsonArgs[*key].asString();
|
||||||
}
|
}
|
||||||
}catch (std::exception &ex){
|
} catch (std::exception &ex) {
|
||||||
WarnL << ex.what();
|
WarnL << ex.what();
|
||||||
}
|
}
|
||||||
}else if(!parser["Content-Type"].empty()){
|
} else if (!parser["Content-Type"].empty()) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
@ -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;
|
||||||
|
@ -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 ¶ms){
|
HlsRecorder(const string &m3u8_file, const string ¶ms){
|
||||||
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 {
|
||||||
|
@ -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(tracks.size()){
|
if(src){
|
||||||
helper->attachTracks(std::move(tracks),schema);
|
auto tracks = src->getTracks(needTrackReady());
|
||||||
|
if(tracks.size()){
|
||||||
|
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:
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user