Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
cefb2a7c
Commit
cefb2a7c
authored
Apr 04, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hls/mp4录制不再能随时开启或关闭
parent
a581f78d
显示空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
35 行增加
和
489 行删除
+35
-489
api/include/mk_recorder.h
+0
-41
api/source/mk_recorder.cpp
+0
-21
server/WebApi.cpp
+0
-37
server/main.cpp
+1
-2
src/Common/MediaSource.cpp
+0
-1
src/Common/MultiMediaSourceMuxer.h
+33
-15
src/Common/config.cpp
+0
-1
src/Common/config.h
+0
-4
src/Record/Recorder.cpp
+0
-306
src/Record/Recorder.h
+1
-60
tests/test_server.cpp
+0
-1
没有找到文件。
api/include/mk_recorder.h
查看文件 @
cefb2a7c
...
...
@@ -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
);
///////////////////////////////////////////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
}
#endif
...
...
api/source/mk_recorder.cpp
查看文件 @
cefb2a7c
...
...
@@ -50,23 +50,3 @@ API_EXPORT int API_CALL mk_flv_recorder_start(mk_flv_recorder ctx, const char *v
return
-
1
;
}
}
\ No newline at end of file
///////////////////////////////////////////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
server/WebApi.cpp
查看文件 @
cefb2a7c
...
...
@@ -737,43 +737,6 @@ void installWebApi() {
});
#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文件列表
//http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01
api_regist1
(
"/index/api/getMp4RecordFile"
,
[](
API_ARGS1
){
...
...
server/main.cpp
查看文件 @
cefb2a7c
/*
/*
* MIT License
*
* Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
...
...
@@ -354,7 +354,6 @@ int start_main(int argc,char *argv[]) {
}
unInstallWebApi
();
unInstallWebHook
();
Recorder
::
stopAll
();
//休眠1秒再退出,防止资源释放顺序错误
InfoL
<<
"程序退出中,请等待..."
;
sleep
(
1
);
...
...
src/Common/MediaSource.cpp
查看文件 @
cefb2a7c
...
...
@@ -78,7 +78,6 @@ vector<Track::Ptr> MediaSource::getTracks(bool trackReady) const {
void
MediaSource
::
setTrackSource
(
const
std
::
weak_ptr
<
TrackSource
>
&
track_src
)
{
_track_source
=
track_src
;
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaResetTracks
,
*
this
);
}
void
MediaSource
::
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
){
...
...
src/Common/MultiMediaSourceMuxer.h
查看文件 @
cefb2a7c
...
...
@@ -57,20 +57,12 @@ public:
}
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
){
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
(){}
...
...
@@ -84,6 +76,12 @@ public:
if
(
_rtsp
){
_rtsp
->
resetTracks
();
}
if
(
_hls
){
_hls
->
resetTracks
();
}
if
(
_mp4
){
_mp4
->
resetTracks
();
}
}
/**
...
...
@@ -99,7 +97,7 @@ public:
_rtsp
->
setListener
(
listener
);
}
auto
hls_src
=
_get_hls_media_s
ource
();
auto
hls_src
=
getHlsMediaS
ource
();
if
(
hls_src
){
hls_src
->
setListener
(
listener
);
}
...
...
@@ -110,7 +108,7 @@ public:
* @return
*/
int
totalReaderCount
()
const
{
auto
hls_src
=
_get_hls_media_s
ource
();
auto
hls_src
=
getHlsMediaS
ource
();
return
(
_rtsp
?
_rtsp
->
readerCount
()
:
0
)
+
(
_rtmp
?
_rtmp
->
readerCount
()
:
0
)
+
(
hls_src
?
hls_src
->
readerCount
()
:
0
);
}
...
...
@@ -118,7 +116,6 @@ public:
if
(
_rtmp
){
_rtmp
->
setTimeStamp
(
stamp
);
}
if
(
_rtsp
){
_rtsp
->
setTimeStamp
(
stamp
);
}
...
...
@@ -139,6 +136,12 @@ protected:
if
(
_rtsp
){
_rtsp
->
addTrack
(
track
);
}
if
(
_hls
){
_hls
->
addTrack
(
track
);
}
if
(
_mp4
){
_mp4
->
addTrack
(
track
);
}
}
/**
...
...
@@ -152,6 +155,12 @@ protected:
if
(
_rtsp
)
{
_rtsp
->
inputFrame
(
frame
);
}
if
(
_hls
){
_hls
->
inputFrame
(
frame
);
}
if
(
_mp4
){
_mp4
->
inputFrame
(
frame
);
}
}
/**
...
...
@@ -167,7 +176,7 @@ protected:
_rtsp
->
onAllTrackReady
();
}
auto
hls_src
=
_get_hls_media_s
ource
();
auto
hls_src
=
getHlsMediaS
ource
();
if
(
hls_src
){
hls_src
->
setTrackSource
(
shared_from_this
());
}
...
...
@@ -176,11 +185,20 @@ protected:
_listener
->
onAllTrackReady
();
}
}
MediaSource
::
Ptr
getHlsMediaSource
()
const
{
auto
recorder
=
dynamic_pointer_cast
<
HlsRecorder
>
(
_hls
);
if
(
recorder
){
return
recorder
->
getMediaSource
();
}
return
nullptr
;
}
private
:
RtmpMediaSourceMuxer
::
Ptr
_rtmp
;
RtspMediaSourceMuxer
::
Ptr
_rtsp
;
MediaSinkInterface
::
Ptr
_hls
;
MediaSinkInterface
::
Ptr
_mp4
;
Listener
*
_listener
=
nullptr
;
function
<
MediaSource
::
Ptr
()
>
_get_hls_media_source
;
};
...
...
src/Common/config.cpp
查看文件 @
cefb2a7c
...
...
@@ -55,7 +55,6 @@ bool loadIniConfig(const char *ini_path){
////////////广播名称///////////
namespace
Broadcast
{
const
string
kBroadcastMediaChanged
=
"kBroadcastMediaChanged"
;
const
string
kBroadcastMediaResetTracks
=
"kBroadcastMediaResetTracks"
;
const
string
kBroadcastRecordMP4
=
"kBroadcastRecordMP4"
;
const
string
kBroadcastHttpRequest
=
"kBroadcastHttpRequest"
;
const
string
kBroadcastHttpAccess
=
"kBroadcastHttpAccess"
;
...
...
src/Common/config.h
查看文件 @
cefb2a7c
...
...
@@ -72,10 +72,6 @@ namespace Broadcast {
extern
const
string
kBroadcastMediaChanged
;
#define BroadcastMediaChangedArgs const bool &bRegist, MediaSource &sender
//MediaSource重置Track事件
extern
const
string
kBroadcastMediaResetTracks
;
#define BroadcastMediaResetTracksArgs MediaSource &sender
//录制mp4文件成功后广播
extern
const
string
kBroadcastRecordMP4
;
#define BroadcastRecordMP4Args const MP4Info &info
...
...
src/Record/Recorder.cpp
查看文件 @
cefb2a7c
...
...
@@ -70,286 +70,6 @@ string Recorder::getRecordPath(Recorder::type type, const string &vhost, const s
return
""
;
}
}
////////////////////////////////////////////////////////////////////////////////////////
class
RecorderHelper
{
public
:
typedef
std
::
shared_ptr
<
RecorderHelper
>
Ptr
;
/**
* 构建函数
* @param bContinueRecord false表明hls录制从头开始录制(意味着hls临时文件在媒体反注册时会被删除)
*/
RecorderHelper
(
const
MediaSinkInterface
::
Ptr
&
recorder
,
bool
bContinueRecord
)
{
_recorder
=
recorder
;
_continueRecord
=
bContinueRecord
;
}
~
RecorderHelper
()
{
resetTracks
();
}
// 附则于track上
void
attachTracks
(
vector
<
Track
::
Ptr
>
&&
tracks
,
const
string
&
schema
){
if
(
isTracksSame
(
tracks
)){
return
;
}
resetTracks
();
_tracks
=
std
::
move
(
tracks
);
_schema
=
schema
;
for
(
auto
&
track
:
_tracks
)
{
_recorder
->
addTrack
(
track
);
track
->
addDelegate
(
_recorder
);
}
}
// 判断新的tracks是否与之前的一致
bool
isTracksSame
(
const
vector
<
Track
::
Ptr
>
&
tracks
){
if
(
tracks
.
size
()
!=
_tracks
.
size
())
{
return
false
;
}
int
i
=
0
;
for
(
auto
&
track
:
tracks
){
if
(
track
!=
_tracks
[
i
++
]){
return
false
;
}
}
return
true
;
}
// 重置所有track
void
resetTracks
(){
if
(
_tracks
.
empty
()){
return
;
}
for
(
auto
&
track
:
_tracks
)
{
track
->
delDelegate
(
_recorder
.
get
());
}
_tracks
.
clear
();
_recorder
->
resetTracks
();
}
// 返回false表明hls录制从头开始录制(意味着hls临时文件在媒体反注册时会被删除)
bool
continueRecord
(){
return
_continueRecord
;
}
bool
isRecording
()
{
return
!
_tracks
.
empty
();
}
const
string
&
getSchema
()
const
{
return
_schema
;
}
const
MediaSinkInterface
::
Ptr
&
getRecorder
()
const
{
return
_recorder
;
}
private
:
MediaSinkInterface
::
Ptr
_recorder
;
vector
<
Track
::
Ptr
>
_tracks
;
bool
_continueRecord
;
string
_schema
;
};
template
<
Recorder
::
type
type
>
class
MediaSourceWatcher
{
public
:
static
MediaSourceWatcher
&
Instance
(){
static
MediaSourceWatcher
instance
;
return
instance
;
}
Recorder
::
status
getRecordStatus
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
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
,
const
string
&
customized_path
,
bool
waitForRecord
,
bool
continueRecord
)
{
auto
key
=
getRecorderKey
(
vhost
,
app
,
stream_id
);
lock_guard
<
decltype
(
_recorder_mtx
)
>
lck
(
_recorder_mtx
);
if
(
getRecordStatus_l
(
key
)
!=
Recorder
::
status_not_record
)
{
// 已经在录制了
return
0
;
}
auto
src
=
findMediaSource
(
vhost
,
app
,
stream_id
);
if
(
!
waitForRecord
&&
!
src
)
{
// 暂时无法开启录制
return
-
1
;
}
auto
recorder
=
Recorder
::
createRecorder
(
type
,
vhost
,
app
,
stream_id
,
customized_path
);
if
(
!
recorder
)
{
// 创建录制器失败
WarnL
<<
"不支持该录制类型:"
<<
type
;
return
-
2
;
}
auto
helper
=
std
::
make_shared
<
RecorderHelper
>
(
recorder
,
continueRecord
);
if
(
src
){
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
);
return
0
;
}
bool
stopRecord
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
)
{
lock_guard
<
decltype
(
_recorder_mtx
)
>
lck
(
_recorder_mtx
);
return
_recorder_map
.
erase
(
getRecorderKey
(
vhost
,
app
,
stream_id
));
}
void
stopAll
(){
lock_guard
<
decltype
(
_recorder_mtx
)
>
lck
(
_recorder_mtx
);
_recorder_map
.
clear
();
}
private
:
MediaSourceWatcher
(){
//保存NoticeCenter的强引用,防止在MediaSourceWatcher单例释放前释放NoticeCenter单例
_notice_center
=
NoticeCenter
::
Instance
().
shared_from_this
();
_notice_center
->
addListener
(
this
,
Broadcast
::
kBroadcastMediaChanged
,[
this
](
BroadcastMediaChangedArgs
){
if
(
!
bRegist
){
removeRecorder
(
sender
);
}
});
_notice_center
->
addListener
(
this
,
Broadcast
::
kBroadcastMediaResetTracks
,[
this
](
BroadcastMediaResetTracksArgs
){
addRecorder
(
sender
);
});
}
~
MediaSourceWatcher
(){
_notice_center
->
delListener
(
this
,
Broadcast
::
kBroadcastMediaChanged
);
_notice_center
->
delListener
(
this
,
Broadcast
::
kBroadcastMediaResetTracks
);
}
void
addRecorder
(
MediaSource
&
sender
){
auto
tracks
=
sender
.
getTracks
(
needTrackReady
());
auto
key
=
getRecorderKey
(
sender
.
getVhost
(),
sender
.
getApp
(),
sender
.
getId
());
lock_guard
<
decltype
(
_recorder_mtx
)
>
lck
(
_recorder_mtx
);
auto
it
=
_recorder_map
.
find
(
key
);
if
(
it
==
_recorder_map
.
end
()){
// 录像记录不存在
return
;
}
if
(
!
it
->
second
->
isRecording
()
||
it
->
second
->
getSchema
()
==
sender
.
getSchema
()){
// 绑定的协议一致或者并未正在录制则替换tracks
if
(
!
tracks
.
empty
())
{
it
->
second
->
attachTracks
(
std
::
move
(
tracks
),
sender
.
getSchema
());
}
}
}
void
removeRecorder
(
MediaSource
&
sender
){
auto
key
=
getRecorderKey
(
sender
.
getVhost
(),
sender
.
getApp
(),
sender
.
getId
());
lock_guard
<
decltype
(
_recorder_mtx
)
>
lck
(
_recorder_mtx
);
auto
it
=
_recorder_map
.
find
(
key
);
if
(
it
==
_recorder_map
.
end
()
||
it
->
second
->
getSchema
()
!=
sender
.
getSchema
()){
// 录像记录不存在或绑定的协议不一致
return
;
}
if
(
it
->
second
->
continueRecord
()){
// 如果可以继续录制,那么只重置tracks,不删除对象
it
->
second
->
resetTracks
();
}
else
{
// 删除对象(意味着可能删除hls临时文件)
_recorder_map
.
erase
(
it
);
}
}
Recorder
::
status
getRecordStatus_l
(
const
string
&
key
)
{
auto
it
=
_recorder_map
.
find
(
key
);
if
(
it
==
_recorder_map
.
end
())
{
return
Recorder
::
status_not_record
;
}
return
it
->
second
->
isRecording
()
?
Recorder
::
status_recording
:
Recorder
::
status_wait_record
;
}
// 查找MediaSource以便录制
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
);
if
(
src
)
{
auto
ret
=
src
->
getTracks
(
need_ready
);
if
(
!
ret
.
empty
())
{
return
std
::
move
(
src
);
}
}
src
=
MediaSource
::
find
(
RTSP_SCHEMA
,
vhost
,
app
,
stream_id
);
if
(
src
)
{
auto
ret
=
src
->
getTracks
(
need_ready
);
if
(
!
ret
.
empty
())
{
return
std
::
move
(
src
);
}
}
return
nullptr
;
}
string
getRecorderKey
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
)
const
{
return
vhost
+
"/"
+
app
+
"/"
+
stream_id
;
}
/**
* 有些录制类型不需要track就绪即可录制
*/
bool
needTrackReady
(){
switch
(
type
){
case
Recorder
:
:
type_hls
:
return
false
;
case
Recorder
:
:
type_mp4
:
return
true
;
default
:
return
true
;
}
}
private
:
mutable
recursive_mutex
_recorder_mtx
;
NoticeCenter
::
Ptr
_notice_center
;
unordered_map
<
string
,
RecorderHelper
::
Ptr
>
_recorder_map
;
};
Recorder
::
status
Recorder
::
getRecordStatus
(
Recorder
::
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
)
{
switch
(
type
){
case
type_mp4
:
return
MediaSourceWatcher
<
type_mp4
>::
Instance
().
getRecordStatus
(
vhost
,
app
,
stream_id
);
case
type_hls
:
return
MediaSourceWatcher
<
type_hls
>::
Instance
().
getRecordStatus
(
vhost
,
app
,
stream_id
);
}
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
;
}
std
::
shared_ptr
<
MediaSinkInterface
>
Recorder
::
createRecorder
(
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
,
const
string
&
customized_path
){
auto
path
=
Recorder
::
getRecordPath
(
type
,
vhost
,
app
,
stream_id
);
...
...
@@ -375,30 +95,4 @@ std::shared_ptr<MediaSinkInterface> Recorder::createRecorder(type type, const st
}
}
int
Recorder
::
startRecord
(
Recorder
::
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
,
const
string
&
customized_path
,
bool
waitForRecord
,
bool
continueRecord
)
{
switch
(
type
){
case
type_mp4
:
return
MediaSourceWatcher
<
type_mp4
>::
Instance
().
startRecord
(
vhost
,
app
,
stream_id
,
customized_path
,
waitForRecord
,
continueRecord
);
case
type_hls
:
return
MediaSourceWatcher
<
type_hls
>::
Instance
().
startRecord
(
vhost
,
app
,
stream_id
,
customized_path
,
waitForRecord
,
continueRecord
);
}
WarnL
<<
"unknown record type: "
<<
type
;
return
-
3
;
}
bool
Recorder
::
stopRecord
(
Recorder
::
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
)
{
switch
(
type
){
case
type_mp4
:
return
MediaSourceWatcher
<
type_mp4
>::
Instance
().
stopRecord
(
vhost
,
app
,
stream_id
);
case
type_hls
:
return
MediaSourceWatcher
<
type_hls
>::
Instance
().
stopRecord
(
vhost
,
app
,
stream_id
);
}
return
false
;
}
void
Recorder
::
stopAll
()
{
MediaSourceWatcher
<
type_hls
>::
Instance
().
stopAll
();
MediaSourceWatcher
<
type_mp4
>::
Instance
().
stopAll
();
}
}
/* namespace mediakit */
src/Record/Recorder.h
查看文件 @
cefb2a7c
...
...
@@ -26,27 +26,15 @@
#ifndef SRC_MEDIAFILE_RECORDER_H_
#define SRC_MEDIAFILE_RECORDER_H_
#include <memory>
#include <string>
using
namespace
std
;
namespace
mediakit
{
class
MediaSinkInterface
;
class
Recorder
{
public
:
typedef
enum
{
// 未录制
status_not_record
=
0
,
// 等待MediaSource注册,注册成功后立即开始录制
status_wait_record
=
1
,
// MediaSource已注册,并且正在录制
status_recording
=
2
,
}
status
;
typedef
enum
{
// 录制hls
type_hls
=
0
,
// 录制MP4
...
...
@@ -65,52 +53,6 @@ public:
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 vhost 虚拟主机
...
...
@@ -119,12 +61,11 @@ public:
* @param customized_path 录像文件保存自定义目录,默认为空则自动生成
* @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
:
Recorder
()
=
delete
;
~
Recorder
()
=
delete
;
};
}
/* namespace mediakit */
#endif
/* SRC_MEDIAFILE_RECORDER_H_ */
tests/test_server.cpp
查看文件 @
cefb2a7c
...
...
@@ -354,7 +354,6 @@ int main(int argc,char *argv[]) {
signal
(
SIGHUP
,
[](
int
)
{
loadIniConfig
();
});
sem
.
wait
();
Recorder
::
stopAll
();
lock_guard
<
mutex
>
lck
(
s_mtxFlvRecorder
);
s_mapFlvRecorder
.
clear
();
return
0
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论