Commit cefb2a7c by xiongziliang

hls/mp4录制不再能随时开启或关闭

parent a581f78d
...@@ -60,47 +60,6 @@ API_EXPORT void API_CALL mk_flv_recorder_release(mk_flv_recorder ctx); ...@@ -60,47 +60,6 @@ API_EXPORT void API_CALL mk_flv_recorder_release(mk_flv_recorder ctx);
*/ */
API_EXPORT int API_CALL mk_flv_recorder_start(mk_flv_recorder ctx, const char *vhost, const char *app, const char *stream, const char *file_path); API_EXPORT int API_CALL mk_flv_recorder_start(mk_flv_recorder ctx, const char *vhost, const char *app, const char *stream, const char *file_path);
///////////////////////////////////////////hls/mp4录制/////////////////////////////////////////////
/**
* 获取录制状态
* @param type 0:hls,1:MP4
* @param vhost 虚拟主机
* @param app 应用名
* @param stream 流id
* @return 录制状态,0:未录制,1:等待MediaSource注册,注册成功后立即开始录制,2:MediaSource已注册,并且正在录制
*/
API_EXPORT int API_CALL mk_recorder_status(int type, const char *vhost, const char *app, const char *stream);
/**
* 开始录制
* @param type 0:hls,1:MP4
* @param vhost 虚拟主机
* @param app 应用名
* @param stream 流id
* @param customized_path 录像文件保存自定义目录,默认为空或null则自动生成
* @param wait_for_record 是否等待流注册后再录制,未注册时,置false将返回失败
* @param continue_record 流注销时是否继续等待录制还是立即停止录制
* @return 0代表成功,负数代表失败
*/
API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const char *app, const char *stream, const char *customized_path, int wait_for_record, int continue_record);
/**
* 停止录制
* @param type 0:hls,1:MP4
* @param vhost 虚拟主机
* @param app 应用名
* @param stream 流id
* @return 1:成功,0:失败
*/
API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char *app, const char *stream);
/**
* 停止所有录制,一般程序退出时调用
*/
API_EXPORT void API_CALL mk_recorder_stop_all();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -49,24 +49,4 @@ API_EXPORT int API_CALL mk_flv_recorder_start(mk_flv_recorder ctx, const char *v ...@@ -49,24 +49,4 @@ API_EXPORT int API_CALL mk_flv_recorder_start(mk_flv_recorder ctx, const char *v
WarnL << ex.what(); WarnL << ex.what();
return -1; return -1;
} }
}
///////////////////////////////////////////hls/mp4录制/////////////////////////////////////////////
API_EXPORT int API_CALL mk_recorder_status(int type, const char *vhost, const char *app, const char *stream){
assert(vhost && app && stream);
return Recorder::getRecordStatus((Recorder::type)type,vhost,app,stream);
}
API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const char *app, const char *stream,const char *customized_path,int wait_for_record, int continue_record){
assert(vhost && app && stream);
return Recorder::startRecord((Recorder::type)type,vhost,app,stream,customized_path ? customized_path : "",wait_for_record,continue_record);
}
API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char *app, const char *stream){
assert(vhost && app && stream);
return Recorder::stopRecord((Recorder::type)type,vhost,app,stream);
}
API_EXPORT void API_CALL mk_recorder_stop_all(){
Recorder::stopAll();
} }
\ No newline at end of file
...@@ -737,43 +737,6 @@ void installWebApi() { ...@@ -737,43 +737,6 @@ void installWebApi() {
}); });
#endif//ENABLE_RTPPROXY #endif//ENABLE_RTPPROXY
// 开始录制hls或MP4
api_regist1("/index/api/startRecord",[](API_ARGS1){
CHECK_SECRET();
CHECK_ARGS("type","vhost","app","stream","wait_for_record","continue_record");
int result = Recorder::startRecord((Recorder::type)allArgs["type"].as<int>(),
allArgs["vhost"],
allArgs["app"],
allArgs["stream"],
allArgs["customized_path"],
allArgs["wait_for_record"],
allArgs["continue_record"]);
val["result"] = result;
});
// 停止录制hls或MP4
api_regist1("/index/api/stopRecord",[](API_ARGS1){
CHECK_SECRET();
CHECK_ARGS("type","vhost","app","stream");
int result = Recorder::stopRecord((Recorder::type)allArgs["type"].as<int>(),
allArgs["vhost"],
allArgs["app"],
allArgs["stream"]);
val["result"] = result;
});
// 获取hls或MP4录制状态
api_regist1("/index/api/getRecordStatus",[](API_ARGS1){
CHECK_SECRET();
CHECK_ARGS("type","vhost","app","stream");
auto status = Recorder::getRecordStatus((Recorder::type)allArgs["type"].as<int>(),
allArgs["vhost"],
allArgs["app"],
allArgs["stream"]);
val["status"] = (int)status;
});
//获取录像文件夹列表或mp4文件列表 //获取录像文件夹列表或mp4文件列表
//http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01 //http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01
api_regist1("/index/api/getMp4RecordFile", [](API_ARGS1){ api_regist1("/index/api/getMp4RecordFile", [](API_ARGS1){
......
/* /*
* MIT License * MIT License
* *
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com> * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
...@@ -354,7 +354,6 @@ int start_main(int argc,char *argv[]) { ...@@ -354,7 +354,6 @@ int start_main(int argc,char *argv[]) {
} }
unInstallWebApi(); unInstallWebApi();
unInstallWebHook(); unInstallWebHook();
Recorder::stopAll();
//休眠1秒再退出,防止资源释放顺序错误 //休眠1秒再退出,防止资源释放顺序错误
InfoL << "程序退出中,请等待..."; InfoL << "程序退出中,请等待...";
sleep(1); sleep(1);
......
...@@ -78,7 +78,6 @@ vector<Track::Ptr> MediaSource::getTracks(bool trackReady) const { ...@@ -78,7 +78,6 @@ vector<Track::Ptr> MediaSource::getTracks(bool trackReady) const {
void MediaSource::setTrackSource(const std::weak_ptr<TrackSource> &track_src) { void MediaSource::setTrackSource(const std::weak_ptr<TrackSource> &track_src) {
_track_source = track_src; _track_source = track_src;
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaResetTracks, *this);
} }
void MediaSource::setListener(const std::weak_ptr<MediaSourceEvent> &listener){ void MediaSource::setListener(const std::weak_ptr<MediaSourceEvent> &listener){
......
...@@ -57,20 +57,12 @@ public: ...@@ -57,20 +57,12 @@ public:
} }
if(enable_hls){ if(enable_hls){
Recorder::startRecord(Recorder::type_hls,vhost, app, stream, "", true, false); _hls = Recorder::createRecorder(Recorder::type_hls,vhost, app, stream);
} }
if(enable_mp4){ if(enable_mp4){
Recorder::startRecord(Recorder::type_mp4,vhost, app, stream, "", true, false); _mp4 = Recorder::createRecorder(Recorder::type_mp4,vhost, app, stream);
} }
_get_hls_media_source = [vhost,app,stream](){
auto recorder = dynamic_pointer_cast<HlsRecorder>(Recorder::getRecorder(Recorder::type_hls,vhost,app,stream));
if(recorder){
return recorder->getMediaSource();
}
return MediaSource::Ptr();
};
} }
virtual ~MultiMediaSourceMuxer(){} virtual ~MultiMediaSourceMuxer(){}
...@@ -84,6 +76,12 @@ public: ...@@ -84,6 +76,12 @@ public:
if(_rtsp){ if(_rtsp){
_rtsp->resetTracks(); _rtsp->resetTracks();
} }
if(_hls){
_hls->resetTracks();
}
if(_mp4){
_mp4->resetTracks();
}
} }
/** /**
...@@ -99,7 +97,7 @@ public: ...@@ -99,7 +97,7 @@ public:
_rtsp->setListener(listener); _rtsp->setListener(listener);
} }
auto hls_src = _get_hls_media_source(); auto hls_src = getHlsMediaSource();
if(hls_src){ if(hls_src){
hls_src->setListener(listener); hls_src->setListener(listener);
} }
...@@ -110,7 +108,7 @@ public: ...@@ -110,7 +108,7 @@ public:
* @return * @return
*/ */
int totalReaderCount() const{ int totalReaderCount() const{
auto hls_src = _get_hls_media_source(); auto hls_src = getHlsMediaSource();
return (_rtsp ? _rtsp->readerCount() : 0) + (_rtmp ? _rtmp->readerCount() : 0) + (hls_src ? hls_src->readerCount() : 0); return (_rtsp ? _rtsp->readerCount() : 0) + (_rtmp ? _rtmp->readerCount() : 0) + (hls_src ? hls_src->readerCount() : 0);
} }
...@@ -118,7 +116,6 @@ public: ...@@ -118,7 +116,6 @@ public:
if(_rtmp){ if(_rtmp){
_rtmp->setTimeStamp(stamp); _rtmp->setTimeStamp(stamp);
} }
if(_rtsp){ if(_rtsp){
_rtsp->setTimeStamp(stamp); _rtsp->setTimeStamp(stamp);
} }
...@@ -139,6 +136,12 @@ protected: ...@@ -139,6 +136,12 @@ protected:
if(_rtsp){ if(_rtsp){
_rtsp->addTrack(track); _rtsp->addTrack(track);
} }
if(_hls){
_hls->addTrack(track);
}
if(_mp4){
_mp4->addTrack(track);
}
} }
/** /**
...@@ -152,6 +155,12 @@ protected: ...@@ -152,6 +155,12 @@ protected:
if(_rtsp) { if(_rtsp) {
_rtsp->inputFrame(frame); _rtsp->inputFrame(frame);
} }
if(_hls){
_hls->inputFrame(frame);
}
if(_mp4){
_mp4->inputFrame(frame);
}
} }
/** /**
...@@ -167,7 +176,7 @@ protected: ...@@ -167,7 +176,7 @@ protected:
_rtsp->onAllTrackReady(); _rtsp->onAllTrackReady();
} }
auto hls_src = _get_hls_media_source(); auto hls_src = getHlsMediaSource();
if(hls_src){ if(hls_src){
hls_src->setTrackSource(shared_from_this()); hls_src->setTrackSource(shared_from_this());
} }
...@@ -176,11 +185,20 @@ protected: ...@@ -176,11 +185,20 @@ protected:
_listener->onAllTrackReady(); _listener->onAllTrackReady();
} }
} }
MediaSource::Ptr getHlsMediaSource() const{
auto recorder = dynamic_pointer_cast<HlsRecorder>(_hls);
if(recorder){
return recorder->getMediaSource();
}
return nullptr;
}
private: private:
RtmpMediaSourceMuxer::Ptr _rtmp; RtmpMediaSourceMuxer::Ptr _rtmp;
RtspMediaSourceMuxer::Ptr _rtsp; RtspMediaSourceMuxer::Ptr _rtsp;
MediaSinkInterface::Ptr _hls;
MediaSinkInterface::Ptr _mp4;
Listener *_listener = nullptr; Listener *_listener = nullptr;
function<MediaSource::Ptr ()> _get_hls_media_source;
}; };
......
...@@ -55,7 +55,6 @@ bool loadIniConfig(const char *ini_path){ ...@@ -55,7 +55,6 @@ bool loadIniConfig(const char *ini_path){
////////////广播名称/////////// ////////////广播名称///////////
namespace Broadcast { namespace Broadcast {
const string kBroadcastMediaChanged = "kBroadcastMediaChanged"; const string kBroadcastMediaChanged = "kBroadcastMediaChanged";
const string kBroadcastMediaResetTracks = "kBroadcastMediaResetTracks";
const string kBroadcastRecordMP4 = "kBroadcastRecordMP4"; const string kBroadcastRecordMP4 = "kBroadcastRecordMP4";
const string kBroadcastHttpRequest = "kBroadcastHttpRequest"; const string kBroadcastHttpRequest = "kBroadcastHttpRequest";
const string kBroadcastHttpAccess = "kBroadcastHttpAccess"; const string kBroadcastHttpAccess = "kBroadcastHttpAccess";
......
...@@ -72,10 +72,6 @@ namespace Broadcast { ...@@ -72,10 +72,6 @@ namespace Broadcast {
extern const string kBroadcastMediaChanged; extern const string kBroadcastMediaChanged;
#define BroadcastMediaChangedArgs const bool &bRegist, MediaSource &sender #define BroadcastMediaChangedArgs const bool &bRegist, MediaSource &sender
//MediaSource重置Track事件
extern const string kBroadcastMediaResetTracks;
#define BroadcastMediaResetTracksArgs MediaSource &sender
//录制mp4文件成功后广播 //录制mp4文件成功后广播
extern const string kBroadcastRecordMP4; extern const string kBroadcastRecordMP4;
#define BroadcastRecordMP4Args const MP4Info &info #define BroadcastRecordMP4Args const MP4Info &info
......
...@@ -26,27 +26,15 @@ ...@@ -26,27 +26,15 @@
#ifndef SRC_MEDIAFILE_RECORDER_H_ #ifndef SRC_MEDIAFILE_RECORDER_H_
#define SRC_MEDIAFILE_RECORDER_H_ #define SRC_MEDIAFILE_RECORDER_H_
#include <memory> #include <memory>
#include <string> #include <string>
using namespace std; using namespace std;
namespace mediakit { namespace mediakit {
class MediaSinkInterface; class MediaSinkInterface;
class Recorder{ class Recorder{
public: public:
typedef enum { typedef enum {
// 未录制
status_not_record = 0,
// 等待MediaSource注册,注册成功后立即开始录制
status_wait_record = 1,
// MediaSource已注册,并且正在录制
status_recording = 2,
} status;
typedef enum {
// 录制hls // 录制hls
type_hls = 0, type_hls = 0,
// 录制MP4 // 录制MP4
...@@ -65,52 +53,6 @@ public: ...@@ -65,52 +53,6 @@ public:
static string getRecordPath(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path = ""); static string getRecordPath(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path = "");
/** /**
* 获取录制状态
* @param type hls还是MP4录制
* @param vhost 虚拟主机
* @param app 应用名
* @param stream_id 流id
* @return 录制状态
*/
static status getRecordStatus(type type, const string &vhost, const string &app, const string &stream_id);
/**
* 开始录制
* @param type hls还是MP4录制
* @param vhost 虚拟主机
* @param app 应用名
* @param stream_id 流id
* @param customized_path 录像文件保存自定义目录,默认为空则自动生成
* @param waitForRecord 是否等待流注册后再录制,未注册时,置false将返回失败
* @param continueRecord 流注销时是否继续等待录制还是立即停止录制
* @return 0代表成功,负数代表失败
*/
static int startRecord(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path,bool waitForRecord, bool continueRecord);
/**
* 停止录制
* @param type hls还是MP4录制
* @param vhost 虚拟主机
* @param app 应用名
* @param stream_id 流id
*/
static bool stopRecord(type type, const string &vhost, const string &app, const string &stream_id);
/**
* 停止所有录制,一般程序退出时调用
*/
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);
/**
* 创建录制器对象 * 创建录制器对象
* @param type hls还是MP4录制 * @param type hls还是MP4录制
* @param vhost 虚拟主机 * @param vhost 虚拟主机
...@@ -119,12 +61,11 @@ public: ...@@ -119,12 +61,11 @@ public:
* @param customized_path 录像文件保存自定义目录,默认为空则自动生成 * @param customized_path 录像文件保存自定义目录,默认为空则自动生成
* @return 对象指针,可能为nullptr * @return 对象指针,可能为nullptr
*/ */
static std::shared_ptr<MediaSinkInterface> createRecorder(type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path); static std::shared_ptr<MediaSinkInterface> createRecorder(type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path = "");
private: private:
Recorder() = delete; Recorder() = delete;
~Recorder() = delete; ~Recorder() = delete;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
#endif /* SRC_MEDIAFILE_RECORDER_H_ */ #endif /* SRC_MEDIAFILE_RECORDER_H_ */
...@@ -354,7 +354,6 @@ int main(int argc,char *argv[]) { ...@@ -354,7 +354,6 @@ int main(int argc,char *argv[]) {
signal(SIGHUP, [](int) { loadIniConfig(); }); signal(SIGHUP, [](int) { loadIniConfig(); });
sem.wait(); sem.wait();
Recorder::stopAll();
lock_guard<mutex> lck(s_mtxFlvRecorder); lock_guard<mutex> lck(s_mtxFlvRecorder);
s_mapFlvRecorder.clear(); s_mapFlvRecorder.clear();
return 0; return 0;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论