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
e5d5cabf
Commit
e5d5cabf
authored
Apr 05, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
部分恢复录制相关接口
parent
c040f472
显示空白字符变更
内嵌
并排
正在显示
15 个修改的文件
包含
598 行增加
和
150 行删除
+598
-150
api/include/mk_recorder.h
+33
-0
api/source/mk_media.cpp
+1
-1
api/source/mk_recorder.cpp
+16
-0
server/WebApi.cpp
+31
-0
src/Common/MediaSource.cpp
+16
-2
src/Common/MediaSource.h
+9
-1
src/Common/MultiMediaSourceMuxer.cpp
+296
-0
src/Common/MultiMediaSourceMuxer.h
+126
-139
src/Player/PlayerProxy.cpp
+1
-1
src/Record/MP4Reader.cpp
+1
-1
src/Record/Recorder.cpp
+32
-0
src/Record/Recorder.h
+31
-0
src/Rtmp/RtmpMediaSourceImp.h
+2
-2
src/Rtp/RtpProcess.cpp
+1
-1
src/Rtsp/RtspMediaSourceImp.h
+2
-2
没有找到文件。
api/include/mk_recorder.h
查看文件 @
e5d5cabf
...
...
@@ -44,6 +44,39 @@ 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:正在录制
*/
API_EXPORT
int
API_CALL
mk_recorder_is_recording
(
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则自动生成
* @return 1代表成功,0代表失败
*/
API_EXPORT
int
API_CALL
mk_recorder_start
(
int
type
,
const
char
*
vhost
,
const
char
*
app
,
const
char
*
stream
,
const
char
*
customized_path
);
/**
* 停止录制
* @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
);
#ifdef __cplusplus
}
#endif
...
...
api/source/mk_media.cpp
查看文件 @
e5d5cabf
...
...
@@ -26,7 +26,7 @@ public:
~
MediaHelper
(){}
void
attachEvent
(){
_channel
->
setListener
(
shared_from_this
());
_channel
->
set
Media
Listener
(
shared_from_this
());
}
DevChannel
::
Ptr
&
getChannel
(){
...
...
api/source/mk_recorder.cpp
查看文件 @
e5d5cabf
...
...
@@ -34,3 +34,19 @@ API_EXPORT int API_CALL mk_flv_recorder_start(mk_flv_recorder ctx, const char *v
return
-
1
;
}
}
///////////////////////////////////////////hls/mp4录制/////////////////////////////////////////////
API_EXPORT
int
API_CALL
mk_recorder_is_recording
(
int
type
,
const
char
*
vhost
,
const
char
*
app
,
const
char
*
stream
){
assert
(
vhost
&&
app
&&
stream
);
return
Recorder
::
isRecording
((
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
){
assert
(
vhost
&&
app
&&
stream
);
return
Recorder
::
startRecord
((
Recorder
::
type
)
type
,
vhost
,
app
,
stream
,
customized_path
?
customized_path
:
""
);
}
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
);
}
server/WebApi.cpp
查看文件 @
e5d5cabf
...
...
@@ -721,6 +721,37 @@ void installWebApi() {
});
#endif//ENABLE_RTPPROXY
// 开始录制hls或MP4
api_regist1
(
"/index/api/startRecord"
,[](
API_ARGS1
){
CHECK_SECRET
();
CHECK_ARGS
(
"type"
,
"vhost"
,
"app"
,
"stream"
);
val
[
"result"
]
=
Recorder
::
startRecord
((
Recorder
::
type
)
allArgs
[
"type"
].
as
<
int
>
(),
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
],
allArgs
[
"customized_path"
]);
});
// 停止录制hls或MP4
api_regist1
(
"/index/api/stopRecord"
,[](
API_ARGS1
){
CHECK_SECRET
();
CHECK_ARGS
(
"type"
,
"vhost"
,
"app"
,
"stream"
);
val
[
"result"
]
=
Recorder
::
stopRecord
((
Recorder
::
type
)
allArgs
[
"type"
].
as
<
int
>
(),
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
});
// 获取hls或MP4录制状态
api_regist1
(
"/index/api/isRecording"
,[](
API_ARGS1
){
CHECK_SECRET
();
CHECK_ARGS
(
"type"
,
"vhost"
,
"app"
,
"stream"
);
val
[
"status"
]
=
Recorder
::
isRecording
((
Recorder
::
type
)
allArgs
[
"type"
].
as
<
int
>
(),
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
});
//获取录像文件夹列表或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
){
...
...
src/Common/MediaSource.cpp
查看文件 @
e5d5cabf
...
...
@@ -13,9 +13,7 @@
#include "Util/util.h"
#include "Network/sockutil.h"
#include "Network/TcpSession.h"
using
namespace
toolkit
;
namespace
mediakit
{
recursive_mutex
MediaSource
::
g_mtxMediaSrc
;
...
...
@@ -104,6 +102,22 @@ void MediaSource::onNoneReader(){
}
}
bool
MediaSource
::
setupRecord
(
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
){
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
setupRecord
(
*
this
,
type
,
start
,
custom_path
);
}
bool
MediaSource
::
isRecording
(
Recorder
::
type
type
){
auto
listener
=
_listener
.
lock
();
if
(
!
listener
){
return
false
;
}
return
listener
->
isRecording
(
*
this
,
type
);
}
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
)
{
...
...
src/Common/MediaSource.h
查看文件 @
e5d5cabf
...
...
@@ -22,6 +22,7 @@
#include "Util/TimeTicker.h"
#include "Util/NoticeCenter.h"
#include "Extension/Track.h"
#include "Record/Recorder.h"
using
namespace
std
;
using
namespace
toolkit
;
...
...
@@ -45,6 +46,10 @@ public:
virtual
bool
close
(
MediaSource
&
sender
,
bool
force
)
{
return
false
;}
// 观看总人数
virtual
int
totalReaderCount
(
MediaSource
&
sender
)
=
0
;
// 开启或关闭录制
virtual
bool
setupRecord
(
MediaSource
&
sender
,
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
)
{
return
false
;
};
// 获取录制状态
virtual
bool
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
)
{
return
false
;
};
private
:
// 通知无人观看
void
onNoneReader
(
MediaSource
&
sender
);
...
...
@@ -104,7 +109,6 @@ public:
// 获取监听者
const
std
::
weak_ptr
<
MediaSourceEvent
>&
getListener
()
const
;
// 本协议获取观看者个数,可能返回本协议的观看人数,也可能返回总人数
virtual
int
readerCount
()
=
0
;
// 观看者个数,包括(hls/rtsp/rtmp)
...
...
@@ -121,6 +125,10 @@ public:
bool
close
(
bool
force
);
// 该流无人观看
void
onNoneReader
();
// 开启或关闭录制
bool
setupRecord
(
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
);
// 获取录制状态
bool
isRecording
(
Recorder
::
type
type
);
// 同步查找流
static
Ptr
find
(
const
string
&
schema
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
id
,
bool
bMake
=
true
)
;
...
...
src/Common/MultiMediaSourceMuxer.cpp
0 → 100644
查看文件 @
e5d5cabf
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include "MultiMediaSourceMuxer.h"
namespace
mediakit
{
MultiMuxerPrivate
::~
MultiMuxerPrivate
()
{}
MultiMuxerPrivate
::
MultiMuxerPrivate
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
,
float
dur_sec
,
bool
enable_rtsp
,
bool
enable_rtmp
,
bool
enable_hls
,
bool
enable_mp4
)
{
if
(
enable_rtmp
)
{
_rtmp
=
std
::
make_shared
<
RtmpMediaSourceMuxer
>
(
vhost
,
app
,
stream
,
std
::
make_shared
<
TitleMeta
>
(
dur_sec
));
}
if
(
enable_rtsp
)
{
_rtsp
=
std
::
make_shared
<
RtspMediaSourceMuxer
>
(
vhost
,
app
,
stream
,
std
::
make_shared
<
TitleSdp
>
(
dur_sec
));
}
if
(
enable_hls
)
{
_hls
=
Recorder
::
createRecorder
(
Recorder
::
type_hls
,
vhost
,
app
,
stream
);
}
if
(
enable_mp4
)
{
_mp4
=
Recorder
::
createRecorder
(
Recorder
::
type_mp4
,
vhost
,
app
,
stream
);
}
}
void
MultiMuxerPrivate
::
resetTracks
()
{
if
(
_rtmp
)
{
_rtmp
->
resetTracks
();
}
if
(
_rtsp
)
{
_rtsp
->
resetTracks
();
}
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
auto
hls
=
_hls
;
if
(
hls
)
{
hls
->
resetTracks
();
}
auto
mp4
=
_mp4
;
if
(
mp4
)
{
mp4
->
resetTracks
();
}
}
void
MultiMuxerPrivate
::
setMediaListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
)
{
if
(
_rtmp
)
{
_rtmp
->
setListener
(
listener
);
}
if
(
_rtsp
)
{
_rtsp
->
setListener
(
listener
);
}
auto
hls_src
=
getHlsMediaSource
();
if
(
hls_src
)
{
hls_src
->
setListener
(
listener
);
}
_meida_listener
=
listener
;
}
int
MultiMuxerPrivate
::
totalReaderCount
()
const
{
auto
hls_src
=
getHlsMediaSource
();
return
(
_rtsp
?
_rtsp
->
readerCount
()
:
0
)
+
(
_rtmp
?
_rtmp
->
readerCount
()
:
0
)
+
(
hls_src
?
hls_src
->
readerCount
()
:
0
);
}
static
std
::
shared_ptr
<
MediaSinkInterface
>
makeRecorder
(
const
vector
<
Track
::
Ptr
>
&
tracks
,
Recorder
::
type
type
,
MediaSource
&
sender
){
auto
recorder
=
Recorder
::
createRecorder
(
type
,
sender
.
getVhost
(),
sender
.
getApp
(),
sender
.
getId
());
for
(
auto
&
track
:
tracks
)
{
recorder
->
addTrack
(
track
);
}
return
recorder
;
}
//此函数可能跨线程调用
bool
MultiMuxerPrivate
::
setupRecord
(
MediaSource
&
sender
,
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
){
switch
(
type
)
{
case
Recorder
:
:
type_hls
:
{
if
(
start
&&
!
_hls
)
{
//开始录制
_hls
=
makeRecorder
(
getTracks
(
true
),
type
,
sender
);
auto
hls_src
=
getHlsMediaSource
();
if
(
hls_src
)
{
//设置HlsMediaSource的事件监听器
hls_src
->
setListener
(
_meida_listener
);
}
}
else
if
(
!
start
&&
_hls
)
{
//停止录制
_hls
=
nullptr
;
}
return
true
;
}
case
Recorder
:
:
type_mp4
:
{
if
(
start
&&
!
_mp4
)
{
//开始录制
_mp4
=
makeRecorder
(
getTracks
(
true
),
type
,
sender
);;
}
else
if
(
!
start
&&
_mp4
)
{
//停止录制
_mp4
=
nullptr
;
}
return
true
;
}
default
:
return
false
;
}
}
//此函数可能跨线程调用
bool
MultiMuxerPrivate
::
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
){
switch
(
type
){
case
Recorder
:
:
type_hls
:
return
_hls
?
true
:
false
;
case
Recorder
:
:
type_mp4
:
return
_mp4
?
true
:
false
;
default
:
return
false
;
}
}
void
MultiMuxerPrivate
::
setTimeStamp
(
uint32_t
stamp
)
{
if
(
_rtmp
)
{
_rtmp
->
setTimeStamp
(
stamp
);
}
if
(
_rtsp
)
{
_rtsp
->
setTimeStamp
(
stamp
);
}
}
void
MultiMuxerPrivate
::
setTrackListener
(
Listener
*
listener
)
{
_listener
=
listener
;
}
void
MultiMuxerPrivate
::
onTrackReady
(
const
Track
::
Ptr
&
track
)
{
if
(
_rtmp
)
{
_rtmp
->
addTrack
(
track
);
}
if
(
_rtsp
)
{
_rtsp
->
addTrack
(
track
);
}
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
auto
hls
=
_hls
;
if
(
hls
)
{
hls
->
addTrack
(
track
);
}
auto
mp4
=
_mp4
;
if
(
mp4
)
{
mp4
->
addTrack
(
track
);
}
}
void
MultiMuxerPrivate
::
onTrackFrame
(
const
Frame
::
Ptr
&
frame
)
{
if
(
_rtmp
)
{
_rtmp
->
inputFrame
(
frame
);
}
if
(
_rtsp
)
{
_rtsp
->
inputFrame
(
frame
);
}
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
//此处使用智能指针拷贝来确保线程安全,比互斥锁性能更优
auto
hls
=
_hls
;
if
(
hls
)
{
hls
->
inputFrame
(
frame
);
}
auto
mp4
=
_mp4
;
if
(
mp4
)
{
mp4
->
inputFrame
(
frame
);
}
}
void
MultiMuxerPrivate
::
onAllTrackReady
()
{
if
(
_rtmp
)
{
_rtmp
->
setTrackSource
(
shared_from_this
());
_rtmp
->
onAllTrackReady
();
}
if
(
_rtsp
)
{
_rtsp
->
setTrackSource
(
shared_from_this
());
_rtsp
->
onAllTrackReady
();
}
auto
hls_src
=
getHlsMediaSource
();
if
(
hls_src
)
{
hls_src
->
setTrackSource
(
shared_from_this
());
}
if
(
_listener
)
{
_listener
->
onAllTrackReady
();
}
}
MediaSource
::
Ptr
MultiMuxerPrivate
::
getHlsMediaSource
()
const
{
auto
recorder
=
dynamic_pointer_cast
<
HlsRecorder
>
(
_hls
);
if
(
recorder
)
{
return
recorder
->
getMediaSource
();
}
return
nullptr
;
}
/////////////////////////////////////////////////////////////////
MultiMediaSourceMuxer
::~
MultiMediaSourceMuxer
()
{}
MultiMediaSourceMuxer
::
MultiMediaSourceMuxer
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
,
float
dur_sec
,
bool
enable_rtsp
,
bool
enable_rtmp
,
bool
enable_hls
,
bool
enable_mp4
)
{
_muxer
.
reset
(
new
MultiMuxerPrivate
(
vhost
,
app
,
stream
,
dur_sec
,
enable_rtsp
,
enable_rtmp
,
enable_hls
,
enable_mp4
));
}
void
MultiMediaSourceMuxer
::
setMediaListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
)
{
_muxer
->
setMediaListener
(
shared_from_this
());
_listener
=
listener
;
}
int
MultiMediaSourceMuxer
::
totalReaderCount
()
const
{
return
_muxer
->
totalReaderCount
();
}
void
MultiMediaSourceMuxer
::
setTimeStamp
(
uint32_t
stamp
)
{
_muxer
->
setTimeStamp
(
stamp
);
}
void
MultiMediaSourceMuxer
::
setTrackListener
(
Listener
*
listener
)
{
_muxer
->
setTrackListener
(
listener
);
}
vector
<
Track
::
Ptr
>
MultiMediaSourceMuxer
::
getTracks
(
bool
trackReady
)
const
{
return
_muxer
->
getTracks
(
trackReady
);
}
bool
MultiMediaSourceMuxer
::
seekTo
(
MediaSource
&
sender
,
uint32_t
ui32Stamp
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
seekTo
(
sender
,
ui32Stamp
);
}
bool
MultiMediaSourceMuxer
::
close
(
MediaSource
&
sender
,
bool
force
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
close
(
sender
,
force
);
}
int
MultiMediaSourceMuxer
::
totalReaderCount
(
MediaSource
&
sender
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
_muxer
->
totalReaderCount
();
}
return
listener
->
totalReaderCount
(
sender
);
}
bool
MultiMediaSourceMuxer
::
setupRecord
(
MediaSource
&
sender
,
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
)
{
return
_muxer
->
setupRecord
(
sender
,
type
,
start
,
custom_path
);
}
bool
MultiMediaSourceMuxer
::
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
)
{
return
_muxer
->
isRecording
(
sender
,
type
);
}
void
MultiMediaSourceMuxer
::
addTrack
(
const
Track
::
Ptr
&
track
)
{
_muxer
->
addTrack
(
track
);
}
void
MultiMediaSourceMuxer
::
addTrackCompleted
()
{
_muxer
->
addTrackCompleted
();
}
void
MultiMediaSourceMuxer
::
resetTracks
()
{
_muxer
->
resetTracks
();
}
void
MultiMediaSourceMuxer
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
_muxer
->
inputFrame
(
frame
);
}
}
//
namespace
mediakit
\ No newline at end of file
src/Common/MultiMediaSourceMuxer.h
查看文件 @
e5d5cabf
...
...
@@ -10,180 +10,167 @@
#ifndef ZLMEDIAKIT_MULTIMEDIASOURCEMUXER_H
#define ZLMEDIAKIT_MULTIMEDIASOURCEMUXER_H
#include "Rtsp/RtspMediaSourceMuxer.h"
#include "Rtmp/RtmpMediaSourceMuxer.h"
#include "Record/Recorder.h"
#include "Record/HlsMediaSource.h"
#include "Record/HlsRecorder.h"
namespace
mediakit
{
/**
* 使用该对象时,应该使用setListener方法来绑定MediaSource相关的事件
* 否则多种不同类型的MediaSource(rtsp/rtmp/hls)将无法产生关联
*/
class
MultiMediaSourceMuxer
:
public
MediaSink
,
public
std
::
enable_shared_from_this
<
MultiMediaSourceMuxer
>
{
class
MultiMuxerPrivate
:
public
MediaSink
,
public
std
::
enable_shared_from_this
<
MultiMuxerPrivate
>
{
public
:
friend
class
MultiMediaSourceMuxer
;
typedef
std
::
shared_ptr
<
MultiMuxerPrivate
>
Ptr
;
class
Listener
{
public
:
Listener
()
=
default
;
virtual
~
Listener
()
=
default
;
virtual
void
onAllTrackReady
()
=
0
;
};
~
MultiMuxerPrivate
()
override
;
private
:
MultiMuxerPrivate
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
,
float
dur_sec
,
bool
enable_rtsp
,
bool
enable_rtmp
,
bool
enable_hls
,
bool
enable_mp4
);
void
resetTracks
()
override
;
void
setMediaListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
);
int
totalReaderCount
()
const
;
void
setTimeStamp
(
uint32_t
stamp
);
void
setTrackListener
(
Listener
*
listener
);
bool
setupRecord
(
MediaSource
&
sender
,
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
);
bool
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
);
private
:
void
onTrackReady
(
const
Track
::
Ptr
&
track
)
override
;
void
onTrackFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
void
onAllTrackReady
()
override
;
MediaSource
::
Ptr
getHlsMediaSource
()
const
;
private
:
RtmpMediaSourceMuxer
::
Ptr
_rtmp
;
RtspMediaSourceMuxer
::
Ptr
_rtsp
;
MediaSinkInterface
::
Ptr
_hls
;
MediaSinkInterface
::
Ptr
_mp4
;
Listener
*
_listener
=
nullptr
;
std
::
weak_ptr
<
MediaSourceEvent
>
_meida_listener
;
};
class
MultiMediaSourceMuxer
:
public
MediaSourceEvent
,
public
MediaSinkInterface
,
public
TrackSource
,
public
std
::
enable_shared_from_this
<
MultiMediaSourceMuxer
>
{
public
:
typedef
MultiMuxerPrivate
::
Listener
Listener
;
typedef
std
::
shared_ptr
<
MultiMediaSourceMuxer
>
Ptr
;
MultiMediaSourceMuxer
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
,
float
dur_sec
=
0
.
0
,
bool
enable_rtsp
=
true
,
bool
enable_rtmp
=
true
,
bool
enable_hls
=
true
,
bool
enable_mp4
=
false
){
if
(
enable_rtmp
)
{
_rtmp
=
std
::
make_shared
<
RtmpMediaSourceMuxer
>
(
vhost
,
app
,
stream
,
std
::
make_shared
<
TitleMeta
>
(
dur_sec
));
}
if
(
enable_rtsp
)
{
_rtsp
=
std
::
make_shared
<
RtspMediaSourceMuxer
>
(
vhost
,
app
,
stream
,
std
::
make_shared
<
TitleSdp
>
(
dur_sec
));
}
if
(
enable_hls
){
_hls
=
Recorder
::
createRecorder
(
Recorder
::
type_hls
,
vhost
,
app
,
stream
);
}
if
(
enable_mp4
){
_mp4
=
Recorder
::
createRecorder
(
Recorder
::
type_mp4
,
vhost
,
app
,
stream
);
}
}
virtual
~
MultiMediaSourceMuxer
(){}
/**
* 重置音视频媒体
*/
void
resetTracks
()
override
{
if
(
_rtmp
){
_rtmp
->
resetTracks
();
}
if
(
_rtsp
){
_rtsp
->
resetTracks
();
}
if
(
_hls
){
_hls
->
resetTracks
();
}
if
(
_mp4
){
_mp4
->
resetTracks
();
}
}
~
MultiMediaSourceMuxer
()
override
;
MultiMediaSourceMuxer
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
,
float
dur_sec
=
0
.
0
,
bool
enable_rtsp
=
true
,
bool
enable_rtmp
=
true
,
bool
enable_hls
=
true
,
bool
enable_mp4
=
false
);
/**
* 设置事件监听器
* @param listener
*/
void
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
){
if
(
_rtmp
)
{
_rtmp
->
setListener
(
listener
);
}
if
(
_rtsp
)
{
_rtsp
->
setListener
(
listener
);
}
auto
hls_src
=
getHlsMediaSource
();
if
(
hls_src
){
hls_src
->
setListener
(
listener
);
}
}
void
setMediaListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
);
/**
* 返回总的消费者个数
* @return
*/
int
totalReaderCount
()
const
{
auto
hls_src
=
getHlsMediaSource
();
return
(
_rtsp
?
_rtsp
->
readerCount
()
:
0
)
+
(
_rtmp
?
_rtmp
->
readerCount
()
:
0
)
+
(
hls_src
?
hls_src
->
readerCount
()
:
0
);
}
void
setTimeStamp
(
uint32_t
stamp
){
if
(
_rtmp
){
_rtmp
->
setTimeStamp
(
stamp
);
}
if
(
_rtsp
){
_rtsp
->
setTimeStamp
(
stamp
);
}
}
void
setTrackListener
(
Listener
*
listener
){
_listener
=
listener
;
}
protected
:
int
totalReaderCount
()
const
;
/**
* 设置MediaSource时间戳
* @param stamp 时间戳
*/
void
setTimeStamp
(
uint32_t
stamp
);
/**
* 随着Track就绪事件监听器
* @param listener 事件监听器
*/
void
setTrackListener
(
Listener
*
listener
);
/**
* 获取所有Track
* @param trackReady 是否筛选过滤未就绪的track
* @return 所有Track
*/
vector
<
Track
::
Ptr
>
getTracks
(
bool
trackReady
=
true
)
const
override
;
/**
* 通知拖动进度条
* @param sender 事件发送者
* @param ui32Stamp 目标时间戳
* @return 是否成功
*/
bool
seekTo
(
MediaSource
&
sender
,
uint32_t
ui32Stamp
)
override
;
/**
* 通知停止流生成
* @param sender 事件发送者
* @param force 是否强制关闭
* @return 成功与否
*/
bool
close
(
MediaSource
&
sender
,
bool
force
)
override
;
/**
* 观看总人数
* @param sender 事件发送者
* @return 观看总人数
*/
int
totalReaderCount
(
MediaSource
&
sender
)
override
;
/**
* 设置录制状态
* @param type 录制类型
* @param start 开始或停止
* @param custom_path 开启录制时,指定自定义路径
* @return 是否设置成功
*/
bool
setupRecord
(
MediaSource
&
sender
,
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
)
override
;
/**
* 添加音视频媒体
* @param track 媒体描述
* 获取录制状态
* @param type 录制类型
* @return 录制状态
*/
void
onTrackReady
(
const
Track
::
Ptr
&
track
)
override
{
if
(
_rtmp
){
_rtmp
->
addTrack
(
track
);
}
if
(
_rtsp
){
_rtsp
->
addTrack
(
track
);
}
if
(
_hls
){
_hls
->
addTrack
(
track
);
}
if
(
_mp4
){
_mp4
->
addTrack
(
track
);
}
}
bool
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
)
override
;
/**
* 写入帧数据然后打包rtmp
* @param frame 帧数据
* 添加track,内部会调用Track的clone方法
* 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系
* @param track
*/
void
onTrackFrame
(
const
Frame
::
Ptr
&
frame
)
override
{
if
(
_rtmp
)
{
_rtmp
->
inputFrame
(
frame
);
}
if
(
_rtsp
)
{
_rtsp
->
inputFrame
(
frame
);
}
if
(
_hls
){
_hls
->
inputFrame
(
frame
);
}
if
(
_mp4
){
_mp4
->
inputFrame
(
frame
);
}
}
void
addTrack
(
const
Track
::
Ptr
&
track
)
override
;
/**
* 所有Track都准备就绪,触发媒体注册事件
* 添加track完毕
* @param track
*/
void
onAllTrackReady
()
override
{
if
(
_rtmp
)
{
_rtmp
->
setTrackSource
(
shared_from_this
());
_rtmp
->
onAllTrackReady
();
}
if
(
_rtsp
)
{
_rtsp
->
setTrackSource
(
shared_from_this
());
_rtsp
->
onAllTrackReady
();
}
auto
hls_src
=
getHlsMediaSource
();
if
(
hls_src
){
hls_src
->
setTrackSource
(
shared_from_this
());
}
if
(
_listener
){
_listener
->
onAllTrackReady
();
}
}
MediaSource
::
Ptr
getHlsMediaSource
()
const
{
auto
recorder
=
dynamic_pointer_cast
<
HlsRecorder
>
(
_hls
);
if
(
recorder
){
return
recorder
->
getMediaSource
();
}
return
nullptr
;
}
void
addTrackCompleted
();
/**
* 重置track
*/
void
resetTracks
()
override
;
/**
* 写入帧数据
* @param frame 帧
*/
void
inputFrame
(
const
Frame
::
Ptr
&
frame
)
override
;
private
:
RtmpMediaSourceMuxer
::
Ptr
_rtmp
;
RtspMediaSourceMuxer
::
Ptr
_rtsp
;
MediaSinkInterface
::
Ptr
_hls
;
MediaSinkInterface
::
Ptr
_mp4
;
Listener
*
_listener
=
nullptr
;
MultiMuxerPrivate
::
Ptr
_muxer
;
std
::
weak_ptr
<
MediaSourceEvent
>
_listener
;
};
}
//namespace mediakit
#endif //ZLMEDIAKIT_MULTIMEDIASOURCEMUXER_H
src/Player/PlayerProxy.cpp
查看文件 @
e5d5cabf
...
...
@@ -238,7 +238,7 @@ void PlayerProxy::onPlaySuccess() {
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
_strVhost
,
_strApp
,
_strSrc
,
getDuration
(),
_bEnableRtsp
,
_bEnableRtmp
,
_bEnableHls
,
_bEnableMp4
));
}
}
_mediaMuxer
->
setListener
(
shared_from_this
());
_mediaMuxer
->
set
Media
Listener
(
shared_from_this
());
auto
videoTrack
=
getTrack
(
TrackVideo
,
false
);
if
(
videoTrack
){
...
...
src/Record/MP4Reader.cpp
查看文件 @
e5d5cabf
...
...
@@ -73,7 +73,7 @@ bool MP4Reader::readSample() {
void
MP4Reader
::
startReadMP4
()
{
GET_CONFIG
(
uint32_t
,
sampleMS
,
Record
::
kSampleMS
);
auto
strongSelf
=
shared_from_this
();
_mediaMuxer
->
setListener
(
strongSelf
);
_mediaMuxer
->
set
Media
Listener
(
strongSelf
);
//先获取关键帧
seekTo
(
0
);
...
...
src/Record/Recorder.cpp
查看文件 @
e5d5cabf
...
...
@@ -79,4 +79,36 @@ std::shared_ptr<MediaSinkInterface> Recorder::createRecorder(type type, const st
}
}
static
MediaSource
::
Ptr
getMediaSource
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
){
auto
src
=
MediaSource
::
find
(
RTMP_SCHEMA
,
vhost
,
app
,
stream_id
,
false
);
if
(
src
){
return
src
;
}
return
MediaSource
::
find
(
RTSP_SCHEMA
,
vhost
,
app
,
stream_id
,
false
);
}
bool
Recorder
::
isRecording
(
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
){
auto
src
=
getMediaSource
(
vhost
,
app
,
stream_id
);
if
(
!
src
){
return
false
;
}
return
src
->
isRecording
(
type
);
}
bool
Recorder
::
startRecord
(
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
,
const
string
&
customized_path
){
auto
src
=
getMediaSource
(
vhost
,
app
,
stream_id
);
if
(
!
src
){
return
false
;
}
return
src
->
setupRecord
(
type
,
true
,
customized_path
);
}
bool
Recorder
::
stopRecord
(
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
){
auto
src
=
getMediaSource
(
vhost
,
app
,
stream_id
);
if
(
!
src
){
return
false
;
}
return
src
->
setupRecord
(
type
,
false
,
""
);
}
}
/* namespace mediakit */
src/Record/Recorder.h
查看文件 @
e5d5cabf
...
...
@@ -46,6 +46,37 @@ public:
* @return 对象指针,可能为nullptr
*/
static
std
::
shared_ptr
<
MediaSinkInterface
>
createRecorder
(
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
bool
isRecording
(
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 录像文件保存自定义目录,默认为空则自动生成
* @return 成功与否
*/
static
bool
startRecord
(
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
*/
static
bool
stopRecord
(
type
type
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream_id
);
private
:
Recorder
()
=
delete
;
~
Recorder
()
=
delete
;
...
...
src/Rtmp/RtmpMediaSourceImp.h
查看文件 @
e5d5cabf
...
...
@@ -68,7 +68,7 @@ public:
void
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
)
override
{
RtmpMediaSource
::
setListener
(
listener
);
if
(
_muxer
){
_muxer
->
setListener
(
listener
);
_muxer
->
set
Media
Listener
(
listener
);
}
}
...
...
@@ -88,7 +88,7 @@ public:
void
setProtocolTranslation
(
bool
enableRtsp
,
bool
enableHls
,
bool
enableMP4
)
{
//不重复生成rtmp
_muxer
=
std
::
make_shared
<
MultiMediaSourceMuxer
>
(
getVhost
(),
getApp
(),
getId
(),
_demuxer
->
getDuration
(),
enableRtsp
,
false
,
enableHls
,
enableMP4
);
_muxer
->
setListener
(
getListener
());
_muxer
->
set
Media
Listener
(
getListener
());
_muxer
->
setTrackListener
(
this
);
for
(
auto
&
track
:
_demuxer
->
getTracks
(
false
)){
_muxer
->
addTrack
(
track
);
...
...
src/Rtp/RtpProcess.cpp
查看文件 @
e5d5cabf
...
...
@@ -298,7 +298,7 @@ int RtpProcess::totalReaderCount(){
}
void
RtpProcess
::
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
){
_muxer
->
setListener
(
listener
);
_muxer
->
set
Media
Listener
(
listener
);
}
...
...
src/Rtsp/RtspMediaSourceImp.h
查看文件 @
e5d5cabf
...
...
@@ -59,7 +59,7 @@ public:
void
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
)
override
{
RtspMediaSource
::
setListener
(
listener
);
if
(
_muxer
){
_muxer
->
setListener
(
listener
);
_muxer
->
set
Media
Listener
(
listener
);
}
}
...
...
@@ -79,7 +79,7 @@ public:
void
setProtocolTranslation
(
bool
enableRtmp
,
bool
enableHls
,
bool
enableMP4
){
//不重复生成rtsp
_muxer
=
std
::
make_shared
<
MultiMediaSourceMuxer
>
(
getVhost
(),
getApp
(),
getId
(),
_demuxer
->
getDuration
(),
false
,
enableRtmp
,
enableHls
,
enableMP4
);
_muxer
->
setListener
(
getListener
());
_muxer
->
set
Media
Listener
(
getListener
());
_muxer
->
setTrackListener
(
this
);
for
(
auto
&
track
:
_demuxer
->
getTracks
(
false
)){
_muxer
->
addTrack
(
track
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论