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
4 years ago
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
部分恢复录制相关接口
parent
c040f472
隐藏空白字符变更
内嵌
并排
正在显示
15 个修改的文件
包含
599 行增加
和
152 行删除
+599
-152
api/include/mk_recorder.h
+33
-0
api/source/mk_media.cpp
+1
-1
api/source/mk_recorder.cpp
+17
-2
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
...
...
This diff is collapsed.
Click to expand it.
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
(){
...
...
This diff is collapsed.
Click to expand it.
api/source/mk_recorder.cpp
查看文件 @
e5d5cabf
...
...
@@ -33,4 +33,20 @@ API_EXPORT int API_CALL mk_flv_recorder_start(mk_flv_recorder ctx, const char *v
WarnL
<<
ex
.
what
();
return
-
1
;
}
}
\ No newline at end of file
}
///////////////////////////////////////////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
);
}
This diff is collapsed.
Click to expand it.
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
){
...
...
This diff is collapsed.
Click to expand it.
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
)
{
...
...
This diff is collapsed.
Click to expand it.
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
)
;
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
);
/**
* 添加音视频媒体
* @param track 媒体描述
* 获取所有Track
* @param trackReady 是否筛选过滤未就绪的track
* @return 所有Track
*/
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
);
}
}
vector
<
Track
::
Ptr
>
getTracks
(
bool
trackReady
=
true
)
const
override
;
/**
* 写入帧数据然后打包rtmp
* @param frame 帧数据
* 通知拖动进度条
* @param sender 事件发送者
* @param ui32Stamp 目标时间戳
* @return 是否成功
*/
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
);
}
}
bool
seekTo
(
MediaSource
&
sender
,
uint32_t
ui32Stamp
)
override
;
/**
* 所有Track都准备就绪,触发媒体注册事件
* 通知停止流生成
* @param sender 事件发送者
* @param force 是否强制关闭
* @return 成功与否
*/
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
;
}
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 type 录制类型
* @return 录制状态
*/
bool
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
)
override
;
/**
* 添加track,内部会调用Track的clone方法
* 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系
* @param track
*/
void
addTrack
(
const
Track
::
Ptr
&
track
)
override
;
/**
* 添加track完毕
* @param track
*/
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
This diff is collapsed.
Click to expand it.
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
){
...
...
This diff is collapsed.
Click to expand it.
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
);
...
...
This diff is collapsed.
Click to expand it.
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 */
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
);
...
...
This diff is collapsed.
Click to expand it.
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
);
}
...
...
This diff is collapsed.
Click to expand it.
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
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论