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
0ed90250
Commit
0ed90250
authored
Aug 09, 2021
by
baiyfcu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
player增加speed,pause扩展,seek支持秒级定位,MP4按时间戳生成文件
parent
9e5d325e
隐藏空白字符变更
内嵌
并排
正在显示
25 个修改的文件
包含
455 行增加
和
52 行删除
+455
-52
.gitignore
+1
-0
CMakeLists.txt
+27
-6
api/include/mk_media.h
+29
-0
api/include/mk_player.h
+29
-1
api/source/mk_media.cpp
+46
-1
api/source/mk_player.cpp
+56
-0
server/WebApi.cpp
+60
-22
server/WebApi.h
+2
-1
src/Common/MediaSource.cpp
+36
-0
src/Common/MediaSource.h
+11
-0
src/Http/HttpDownloader.h
+4
-1
src/Player/MediaPlayer.cpp
+7
-0
src/Player/MediaPlayer.h
+1
-0
src/Player/PlayerBase.h
+31
-0
src/Record/MP4Recorder.cpp
+6
-1
src/Record/MP4Recorder.h
+2
-0
src/Rtmp/RtmpPlayer.cpp
+5
-0
src/Rtmp/RtmpPlayer.h
+1
-0
src/Rtmp/RtmpPlayerImp.h
+5
-0
src/Rtmp/RtmpSession.cpp
+31
-0
src/Rtmp/RtmpSession.h
+1
-0
src/Rtsp/RtspPlayer.cpp
+9
-3
src/Rtsp/RtspPlayer.h
+2
-1
src/Rtsp/RtspPlayerImp.h
+15
-2
src/Rtsp/RtspSession.cpp
+38
-13
没有找到文件。
.gitignore
查看文件 @
0ed90250
...
...
@@ -35,6 +35,7 @@
/cmake-build-release/
/linux/
/.vs/
/.vscode/
/.idea/
/c_wrapper/.idea/
/release/
...
...
CMakeLists.txt
查看文件 @
0ed90250
...
...
@@ -17,16 +17,21 @@ endif ()
#设置bin和lib库目录
set
(
RELEASE_DIR
${
CMAKE_CURRENT_SOURCE_DIR
}
/release
)
if
(
CMAKE_CL_64
)
set
(
CL_32_64 64
)
else
(
CMAKE_CL_64
)
set
(
CL_32_64 32
)
endif
(
CMAKE_CL_64
)
if
(
CMAKE_SYSTEM_NAME MATCHES
"Linux"
)
SET
(
LIBRARY_OUTPUT_PATH
${
RELEASE_DIR
}
/linux/
${
BuildType
}
)
SET
(
EXECUTABLE_OUTPUT_PATH
${
RELEASE_DIR
}
/linux/
${
BuildType
}
)
SET
(
LIBRARY_OUTPUT_PATH
${
RELEASE_DIR
}
/linux
${
CL_32_64
}
/
${
BuildType
}
)
SET
(
EXECUTABLE_OUTPUT_PATH
${
RELEASE_DIR
}
/linux
${
CL_32_64
}
/
${
BuildType
}
)
add_compile_options
(
-fPIC -Wall -Wno-unused-variable -Wno-unused-value
)
elseif
(
CMAKE_SYSTEM_NAME MATCHES
"Windows"
)
SET
(
LIBRARY_OUTPUT_PATH
${
RELEASE_DIR
}
/windows/
${
BuildType
}
)
SET
(
EXECUTABLE_OUTPUT_PATH
${
RELEASE_DIR
}
/windows/
${
BuildType
}
)
SET
(
LIBRARY_OUTPUT_PATH
${
RELEASE_DIR
}
/windows
${
CL_32_64
}
/
${
BuildType
}
)
SET
(
EXECUTABLE_OUTPUT_PATH
${
RELEASE_DIR
}
/windows
${
CL_32_64
}
/
${
BuildType
}
)
elseif
(
CMAKE_SYSTEM_NAME MATCHES
"Darwin"
)
SET
(
LIBRARY_OUTPUT_PATH
${
RELEASE_DIR
}
/mac/
${
BuildType
}
)
SET
(
EXECUTABLE_OUTPUT_PATH
${
RELEASE_DIR
}
/mac/
${
BuildType
}
)
SET
(
LIBRARY_OUTPUT_PATH
${
RELEASE_DIR
}
/mac
${
CL_32_64
}
/
${
BuildType
}
)
SET
(
EXECUTABLE_OUTPUT_PATH
${
RELEASE_DIR
}
/mac
${
CL_32_64
/
${
BuildType
}
)
add_compile_options(-Wall -Wno-unused-variable -Wno-unused-value)
endif ()
...
...
@@ -57,6 +62,22 @@ option(ENABLE_MEM_DEBUG "Enable Memory Debug" false)
option(ENABLE_ASAN "Enable Address Sanitize" false)
option(ENABLE_WEBRTC "Enable WebRTC" false)
option(ENABLE_PLAYER "Enable Player" true)
option(ENABLE_MsvcMT "Enable MSVC Mt/Mtd lib" true)
if (ENABLE_STATIC AND MSVC)
set(CompilerFlags
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE
CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
)
foreach(CompilerFlag
${
CompilerFlags
}
)
string(REPLACE "/MD" "/MT"
${
CompilerFlag
}
"
${${
CompilerFlag
}}
")
endforeach()
endif()
# 添加git版本信息
set(COMMIT_HASH "Git_NotFound_Unkown_commit")
...
...
api/include/mk_media.h
查看文件 @
0ed90250
...
...
@@ -143,6 +143,19 @@ API_EXPORT void API_CALL mk_media_set_on_close(mk_media ctx, on_mk_media_close c
typedef
int
(
API_CALL
*
on_mk_media_seek
)(
void
*
user_data
,
uint32_t
stamp_ms
);
/**
* 收到客户端的pause请求时触发该回调
* @param user_data 用户数据指针,通过mk_media_set_on_pause设置
*/
typedef
int
(
API_CALL
*
on_mk_media_pause
)(
void
*
user_data
);
/**
* 收到客户端的speed请求时触发该回调
* @param user_data 用户数据指针,通过mk_media_set_on_pause设置
* @param speed 0.5 1.0 2.0
*/
typedef
int
(
API_CALL
*
on_mk_media_speed
)(
void
*
user_data
,
float
speed
);
/**
* 监听播放器seek请求事件
* @param ctx 对象指针
* @param cb 回调指针
...
...
@@ -151,6 +164,22 @@ typedef int(API_CALL *on_mk_media_seek)(void *user_data,uint32_t stamp_ms);
API_EXPORT
void
API_CALL
mk_media_set_on_seek
(
mk_media
ctx
,
on_mk_media_seek
cb
,
void
*
user_data
);
/**
* 监听播放器pause请求事件
* @param ctx 对象指针
* @param cb 回调指针
* @param user_data 用户数据指针
*/
API_EXPORT
void
API_CALL
mk_media_set_on_pause
(
mk_media
ctx
,
on_mk_media_pause
cb
,
void
*
user_data
);
/**
* 监听播放器pause请求事件
* @param ctx 对象指针
* @param cb 回调指针
* @param user_data 用户数据指针
*/
API_EXPORT
void
API_CALL
mk_media_set_on_speed
(
mk_media
ctx
,
on_mk_media_speed
cb
,
void
*
user_data
);
/**
* 获取总的观看人数
* @param ctx 对象指针
* @return 观看人数
...
...
api/include/mk_player.h
查看文件 @
0ed90250
...
...
@@ -74,6 +74,13 @@ API_EXPORT void API_CALL mk_player_play(mk_player ctx, const char *url);
API_EXPORT
void
API_CALL
mk_player_pause
(
mk_player
ctx
,
int
pause
);
/**
* 倍数播放,仅对点播有用
* @param ctx 播放器指针
* @param speed 0.5 1.0 2.0
*/
API_EXPORT
void
API_CALL
mk_player_speed
(
mk_player
ctx
,
float
speed
);
/**
* 设置点播进度条
* @param ctx 对象指针
* @param progress 取值范围未 0.0~1.0
...
...
@@ -81,6 +88,13 @@ API_EXPORT void API_CALL mk_player_pause(mk_player ctx, int pause);
API_EXPORT
void
API_CALL
mk_player_seekto
(
mk_player
ctx
,
float
progress
);
/**
* 设置点播进度条
* @param ctx 对象指针
* @param seekPos 取值范围 相对于开始时间增量 单位秒
*/
API_EXPORT
void
API_CALL
mk_player_seektoByPos
(
mk_player
ctx
,
int
seekPos
);
/**
* 设置播放器开启播放结果回调函数
* @param ctx 播放器指针
* @param cb 回调函数指针,设置null立即取消回调
...
...
@@ -113,6 +127,15 @@ API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb
API_EXPORT
int
API_CALL
mk_player_video_codecId
(
mk_player
ctx
);
/**
* 获取视频codec_id, vendor类型, 私有头数据 codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
* @param ctx 播放器指针
* @param vendor 输出厂家类型 如果是私有流 应该是H264另外还有厂家类型
* @param head 厂家SDK头数据
* @param head 厂家SDK头数据长度
*/
API_EXPORT
int
API_CALL
mk_player_video_codecId_vendor_head
(
mk_player
ctx
,
char
*
vendor
,
char
*
head
,
int
*
headLen
);
/**
* 获取视频宽度
*/
API_EXPORT
int
API_CALL
mk_player_video_width
(
mk_player
ctx
);
...
...
@@ -154,11 +177,16 @@ API_EXPORT int API_CALL mk_player_audio_channel(mk_player ctx);
API_EXPORT
float
API_CALL
mk_player_duration
(
mk_player
ctx
);
/**
* 获取点播播放进度,取值范围
未
0.0~1.0
* 获取点播播放进度,取值范围 0.0~1.0
*/
API_EXPORT
float
API_CALL
mk_player_progress
(
mk_player
ctx
);
/**
* 获取点播播放进度位置,取值范围 相对于开始时间增量 单位秒
*/
API_EXPORT
int
API_CALL
mk_player_progress_pos
(
mk_player
ctx
);
/**
* 获取丢包率,rtsp时有效
* @param ctx 对象指针
* @param track_type 0:视频,1:音频
...
...
api/source/mk_media.cpp
查看文件 @
0ed90250
...
...
@@ -43,6 +43,16 @@ public:
_on_seek_data
=
user_data
;
}
void
setOnPause
(
on_mk_media_pause
cb
,
void
*
user_data
)
{
_on_pause
=
cb
;
_on_pause_data
=
user_data
;
}
void
setOnSpeed
(
on_mk_media_speed
cb
,
void
*
user_data
)
{
_on_speed
=
cb
;
_on_speed_data
=
user_data
;
}
void
setOnRegist
(
on_mk_media_source_regist
cb
,
void
*
user_data
){
_on_regist
=
cb
;
_on_regist_data
=
user_data
;
...
...
@@ -72,6 +82,23 @@ protected:
}
return
_on_seek
(
_on_seek_data
,
ui32Stamp
);
}
// 通知暂停
bool
pause
(
MediaSource
&
sender
)
override
{
if
(
!
_on_pause
)
{
return
false
;
}
return
_on_pause
(
_on_pause_data
);
}
//通知倍数播放
bool
speed
(
MediaSource
&
sender
,
float
speed
)
override
{
if
(
!
_on_speed
)
{
return
false
;
}
return
_on_speed
(
_on_pause_data
,
speed
);
}
// 观看总人数
int
totalReaderCount
(
MediaSource
&
sender
)
override
{
return
_channel
->
totalReaderCount
();
...
...
@@ -87,8 +114,12 @@ private:
DevChannel
::
Ptr
_channel
;
on_mk_media_close
_on_close
=
nullptr
;
on_mk_media_seek
_on_seek
=
nullptr
;
on_mk_media_pause
_on_pause
=
nullptr
;
on_mk_media_speed
_on_speed
=
nullptr
;
on_mk_media_source_regist
_on_regist
=
nullptr
;
void
*
_on_seek_data
;
void
*
_on_seek_data
;
void
*
_on_pause_data
;
void
*
_on_speed_data
;
void
*
_on_close_data
;
void
*
_on_regist_data
;
};
...
...
@@ -105,6 +136,20 @@ API_EXPORT void API_CALL mk_media_set_on_seek(mk_media ctx, on_mk_media_seek cb,
(
*
obj
)
->
setOnSeek
(
cb
,
user_data
);
}
API_EXPORT
void
API_CALL
mk_media_set_on_pause
(
mk_media
ctx
,
on_mk_media_pause
cb
,
void
*
user_data
)
{
assert
(
ctx
);
MediaHelper
::
Ptr
*
obj
=
(
MediaHelper
::
Ptr
*
)
ctx
;
(
*
obj
)
->
setOnPause
(
cb
,
user_data
);
}
API_EXPORT
void
API_CALL
mk_media_set_on_speed
(
mk_media
ctx
,
on_mk_media_speed
cb
,
void
*
user_data
)
{
assert
(
ctx
);
MediaHelper
::
Ptr
*
obj
=
(
MediaHelper
::
Ptr
*
)
ctx
;
(
*
obj
)
->
setOnSpeed
(
cb
,
user_data
);
}
API_EXPORT
void
API_CALL
mk_media_set_on_regist
(
mk_media
ctx
,
on_mk_media_source_regist
cb
,
void
*
user_data
){
assert
(
ctx
);
MediaHelper
::
Ptr
*
obj
=
(
MediaHelper
::
Ptr
*
)
ctx
;
...
...
api/source/mk_player.cpp
查看文件 @
0ed90250
...
...
@@ -11,6 +11,8 @@
#include "mk_player.h"
#include "Util/logger.h"
#include "Player/MediaPlayer.h"
#include "Extension/H264.h"
using
namespace
std
;
using
namespace
toolkit
;
using
namespace
mediakit
;
...
...
@@ -167,6 +169,16 @@ API_EXPORT void API_CALL mk_player_pause(mk_player ctx, int pause) {
});
}
API_EXPORT
void
API_CALL
mk_player_speed
(
mk_player
ctx
,
float
speed
)
{
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
auto
player
=
obj
.
getPlayer
();
player
->
getPoller
()
->
async
([
speed
,
player
]()
{
//切换线程后再操作
player
->
speed
(
speed
);
});
}
API_EXPORT
void
API_CALL
mk_player_seekto
(
mk_player
ctx
,
float
progress
)
{
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
...
...
@@ -177,6 +189,16 @@ API_EXPORT void API_CALL mk_player_seekto(mk_player ctx, float progress) {
});
}
API_EXPORT
void
API_CALL
mk_player_seektoByPos
(
mk_player
ctx
,
int
seekPos
){
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
auto
player
=
obj
.
getPlayer
();
player
->
getPoller
()
->
async
([
seekPos
,
player
]()
{
//切换线程后再操作
player
->
seekTo
((
uint32_t
)
seekPos
);
});
}
static
void
mk_player_set_on_event
(
mk_player
ctx
,
on_mk_play_event
cb
,
void
*
user_data
,
int
type
)
{
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
...
...
@@ -204,6 +226,32 @@ API_EXPORT int API_CALL mk_player_video_codecId(mk_player ctx){
return
track
?
track
->
getCodecId
()
:
CodecInvalid
;
}
API_EXPORT
int
API_CALL
mk_player_video_codecId_vendor_head
(
mk_player
ctx
,
char
*
vendor
,
char
*
head
,
int
*
head_len
)
{
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
auto
track
=
dynamic_pointer_cast
<
VideoTrack
>
(
obj
->
getTrack
(
TrackVideo
));
int
codecId
=
track
?
track
->
getCodecId
()
:
CodecInvalid
;
if
(
codecId
==
CodecH264
)
{
auto
h264Track
=
dynamic_pointer_cast
<
H264Track
>
(
obj
->
getTrack
(
TrackVideo
));
auto
pps
=
h264Track
->
getPps
();
auto
ppsLen
=
pps
.
size
();
if
(
ppsLen
>=
(
4
+
16
))
{
std
::
string
temVendor
=
std
::
string
(
pps
.
c_str
()
+
4
,
16
);
memcpy
(
vendor
,
temVendor
.
c_str
(),
temVendor
.
length
());
if
(
ppsLen
>
(
4
+
16
))
{
std
::
string
temHead
=
std
::
string
(
pps
.
c_str
()
+
20
,
ppsLen
-
20
);
memcpy
(
head
,
temHead
.
c_str
(),
temHead
.
length
());
*
head_len
=
temHead
.
length
();
}
}
}
return
codecId
;
}
API_EXPORT
int
API_CALL
mk_player_video_width
(
mk_player
ctx
)
{
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
...
...
@@ -265,6 +313,14 @@ API_EXPORT float API_CALL mk_player_progress(mk_player ctx) {
return
obj
->
getProgress
();
}
API_EXPORT
int
API_CALL
mk_player_progress_pos
(
mk_player
ctx
)
{
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
return
obj
->
getProgressPos
();
}
API_EXPORT
float
API_CALL
mk_player_loss_rate
(
mk_player
ctx
,
int
track_type
)
{
assert
(
ctx
);
MediaPlayerForC
&
obj
=
**
((
MediaPlayerForC
::
Ptr
*
)
ctx
);
...
...
server/WebApi.cpp
查看文件 @
0ed90250
...
...
@@ -118,13 +118,15 @@ static HttpApi toApi(const function<void(API_ARGS_JSON_ASYNC)> &cb) {
Json
::
Reader
reader
;
reader
.
parse
(
parser
.
Content
(),
in
);
cb
(
sender
,
parser
.
getHeader
(),
headerOut
,
in
,
out
,
invoker
);
//参数解析成map
auto
urlArgs
=
getAllArgs
(
parser
);
cb
(
sender
,
parser
.
getHeader
(),
headerOut
,
in
,
urlArgs
,
out
,
invoker
);
};
}
static
HttpApi
toApi
(
const
function
<
void
(
API_ARGS_JSON
)
>
&
cb
)
{
return
toApi
([
cb
](
API_ARGS_JSON_ASYNC
)
{
cb
(
API_ARGS_VALUE
);
cb
(
API_ARGS_
JSON_
VALUE
);
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
}
...
...
@@ -228,18 +230,19 @@ static inline void addHttpListener(){
size
=
body
->
remainSize
();
}
const
std
::
string
&
content
=
parser
.
Content
();
if
(
size
&&
size
<
4
*
1024
)
{
string
contentOut
=
body
->
readData
(
size
)
->
toString
();
DebugL
<<
"
\r\n
# request:
\r\n
"
<<
parser
.
Method
()
<<
" "
<<
parser
.
FullUrl
()
<<
"
\r\n
"
<<
"# content:
\r\n
"
<<
parser
.
Content
(
)
<<
"
\r\n
"
<<
"# response:
\r\n
"
<<
contentOut
<<
"
\r\n
"
;
<<
"# content:
\r\n
"
<<
(
content
.
size
()
>
4
*
1024
?
content
.
substr
(
0
,
4
*
1024
)
:
content
)
<<
"
\r\n
"
<<
"# response:
\r\n
"
<<
contentOut
<<
"
\r\n
"
;
invoker
(
code
,
headerOut
,
contentOut
);
}
else
{
DebugL
<<
"
\r\n
# request:
\r\n
"
<<
parser
.
Method
()
<<
" "
<<
parser
.
FullUrl
()
<<
"
\r\n
"
<<
"# content:
\r\n
"
<<
parser
.
Content
(
)
<<
"
\r\n
"
<<
"# response size:"
<<
size
<<
"
\r\n
"
;
<<
"# content:
\r\n
"
<<
(
content
.
size
()
>
4
*
1024
?
content
.
substr
(
0
,
4
*
1024
)
:
content
)
<<
"
\r\n
"
<<
"# response size:"
<<
size
<<
"
\r\n
"
;
invoker
(
code
,
headerOut
,
body
);
}
};
...
...
@@ -276,8 +279,8 @@ static recursive_mutex s_ffmpegMapMtx;
#if defined(ENABLE_RTPPROXY)
//rtp服务器列表
static
unordered_map
<
string
,
RtpServer
::
Ptr
>
s_rtpServerMap
;
static
recursive_mutex
s_rtpServerMapMtx
;
/*static*/
unordered_map
<
string
,
RtpServer
::
Ptr
>
s_rtpServerMap
;
/*static*/
recursive_mutex
s_rtpServerMapMtx
;
#endif
static
inline
string
getProxyKey
(
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
)
{
...
...
@@ -932,21 +935,56 @@ void installWebApi() {
api_regist
(
"/index/api/startSendRtp"
,[](
API_ARGS_MAP_ASYNC
){
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
,
"ssrc"
,
"dst_url"
,
"dst_port"
,
"is_udp"
);
bool
isAsync
=
false
;
if
(
checkArgs
(
allArgs
,
"is_async"
))
isAsync
=
allArgs
[
"is_async"
];
if
(
isAsync
)
{
MediaInfo
info
=
{};
info
.
_vhost
=
allArgs
[
"vhost"
];
info
.
_app
=
allArgs
[
"app"
];
info
.
_streamid
=
allArgs
[
"stream"
];
info
.
_schema
=
RTSP_SCHEMA
;
auto
session
=
static_cast
<
TcpSession
*>
(
&
sender
);
auto
session_ptr
=
session
->
shared_from_this
();
auto
src
=
MediaSource
::
find
(
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
if
(
!
src
)
{
throw
ApiRetException
(
"该媒体流不存在"
,
API
::
OtherFailed
);
MediaSource
::
findAsync
(
info
,
session_ptr
,
[
=
](
const
MediaSource
::
Ptr
&
src_in
)
mutable
{
if
(
!
src_in
)
{
val
[
"code"
]
=
API
::
OtherFailed
;
val
[
"msg"
]
=
"该媒体流不存在"
;
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
return
;
}
auto
src
=
dynamic_pointer_cast
<
RtspMediaSource
>
(
src_in
);
//src_port为空时,则随机本地端口
src
->
startSendRtp
(
allArgs
[
"dst_url"
],
allArgs
[
"dst_port"
],
allArgs
[
"ssrc"
],
allArgs
[
"is_udp"
],
allArgs
[
"src_port"
],
[
val
,
headerOut
,
invoker
](
uint16_t
local_port
,
const
SockException
&
ex
)
mutable
{
if
(
ex
)
{
val
[
"code"
]
=
API
::
OtherFailed
;
val
[
"msg"
]
=
ex
.
what
();
}
val
[
"local_port"
]
=
local_port
;
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
});
}
//src_port为空时,则随机本地端口
src
->
startSendRtp
(
allArgs
[
"dst_url"
],
allArgs
[
"dst_port"
],
allArgs
[
"ssrc"
],
allArgs
[
"is_udp"
],
allArgs
[
"src_port"
],
[
val
,
headerOut
,
invoker
](
uint16_t
local_port
,
const
SockException
&
ex
)
mutable
{
if
(
ex
)
{
val
[
"code"
]
=
API
::
OtherFailed
;
val
[
"msg"
]
=
ex
.
what
();
else
{
auto
src
=
MediaSource
::
find
(
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
if
(
!
src
)
{
throw
ApiRetException
(
"该媒体流不存在"
,
API
::
OtherFailed
);
}
val
[
"local_port"
]
=
local_port
;
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
//src_port为空时,则随机本地端口
src
->
startSendRtp
(
allArgs
[
"dst_url"
],
allArgs
[
"dst_port"
],
allArgs
[
"ssrc"
],
allArgs
[
"is_udp"
],
allArgs
[
"src_port"
],
[
val
,
headerOut
,
invoker
](
uint16_t
local_port
,
const
SockException
&
ex
)
mutable
{
if
(
ex
)
{
val
[
"code"
]
=
API
::
OtherFailed
;
val
[
"msg"
]
=
ex
.
what
();
}
val
[
"local_port"
]
=
local_port
;
invoker
(
200
,
headerOut
,
val
.
toStyledString
());
});
}
});
api_regist
(
"/index/api/stopSendRtp"
,[](
API_ARGS_MAP
){
...
...
server/WebApi.h
查看文件 @
0ed90250
...
...
@@ -83,11 +83,12 @@ using ApiArgsType = map<string, variant, StrCaseCompare>;
#define API_ARGS_MAP SockInfo &sender, HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, ApiArgsType &allArgs, Json::Value &val
#define API_ARGS_MAP_ASYNC API_ARGS_MAP, const HttpSession::HttpResponseInvoker &invoker
#define API_ARGS_JSON SockInfo &sender, HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, Json::Value &allArgs, Json::Value &val
#define API_ARGS_JSON SockInfo &sender, HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, Json::Value &
bodyArgs, ApiArgsType &
allArgs, Json::Value &val
#define API_ARGS_JSON_ASYNC API_ARGS_JSON, const HttpSession::HttpResponseInvoker &invoker
#define API_ARGS_STRING SockInfo &sender, HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, const Parser &allArgs, Json::Value &val
#define API_ARGS_STRING_ASYNC API_ARGS_STRING, const HttpSession::HttpResponseInvoker &invoker
#define API_ARGS_VALUE sender, headerIn, headerOut, allArgs, val
#define API_ARGS_JSON_VALUE sender, headerIn, headerOut, bodyArgs, allArgs, val
//注册http请求参数是map<string, variant, StrCaseCompare>类型的http api
void
api_regist
(
const
string
&
api_path
,
const
function
<
void
(
API_ARGS_MAP
)
>
&
func
);
...
...
src/Common/MediaSource.cpp
查看文件 @
0ed90250
...
...
@@ -157,6 +157,24 @@ bool MediaSource::seekTo(uint32_t stamp) {
return
listener
->
seekTo
(
*
this
,
stamp
);
}
bool
MediaSource
::
pause
()
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
pause
(
*
this
);
}
bool
MediaSource
::
speed
(
float
speed
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
speed
(
*
this
,
speed
);
}
bool
MediaSource
::
close
(
bool
force
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
){
...
...
@@ -588,6 +606,24 @@ bool MediaSourceEventInterceptor::seekTo(MediaSource &sender, uint32_t stamp) {
return
listener
->
seekTo
(
sender
,
stamp
);
}
bool
MediaSourceEventInterceptor
::
pause
(
MediaSource
&
sender
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
pause
(
sender
);
}
bool
MediaSourceEventInterceptor
::
speed
(
MediaSource
&
sender
,
float
speed
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
speed
(
sender
,
speed
);
}
bool
MediaSourceEventInterceptor
::
close
(
MediaSource
&
sender
,
bool
force
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
...
...
src/Common/MediaSource.h
查看文件 @
0ed90250
...
...
@@ -67,6 +67,10 @@ public:
// 通知拖动进度条
virtual
bool
seekTo
(
MediaSource
&
sender
,
uint32_t
stamp
)
{
return
false
;
}
// 通知暂停
virtual
bool
pause
(
MediaSource
&
sender
)
{
return
false
;
}
// 通知倍数
virtual
bool
speed
(
MediaSource
&
sender
,
float
speed
)
{
return
false
;
}
// 通知其停止产生流
virtual
bool
close
(
MediaSource
&
sender
,
bool
force
)
{
return
false
;
}
// 获取观看总人数
...
...
@@ -106,6 +110,8 @@ public:
std
::
shared_ptr
<
SockInfo
>
getOriginSock
(
MediaSource
&
sender
)
const
override
;
bool
seekTo
(
MediaSource
&
sender
,
uint32_t
stamp
)
override
;
bool
pause
(
MediaSource
&
sender
)
override
;
bool
speed
(
MediaSource
&
sender
,
float
speed
)
override
;
bool
close
(
MediaSource
&
sender
,
bool
force
)
override
;
int
totalReaderCount
(
MediaSource
&
sender
)
override
;
void
onReaderChanged
(
MediaSource
&
sender
,
int
size
)
override
;
...
...
@@ -249,6 +255,11 @@ public:
// 拖动进度条
bool
seekTo
(
uint32_t
stamp
);
//暂停
bool
pause
();
//倍数播放
bool
speed
(
float
speed
);
// 关闭该流
bool
close
(
bool
force
);
// 该流观看人数变化
...
...
src/Http/HttpDownloader.h
查看文件 @
0ed90250
...
...
@@ -30,9 +30,12 @@ public:
void
setOnResult
(
const
onDownloadResult
&
cb
){
_onResult
=
cb
;
}
protected
:
void
onResponseBody
(
const
char
*
buf
,
size_t
size
,
size_t
recvedSize
,
size_t
totalSize
)
override
;
private
:
ssize_t
onResponseHeader
(
const
string
&
status
,
const
HttpHeader
&
headers
)
override
;
void
onResponseBody
(
const
char
*
buf
,
size_t
size
,
size_t
recvedSize
,
size_t
totalSize
)
override
;
void
onResponseCompleted
()
override
;
void
onDisconnect
(
const
SockException
&
ex
)
override
;
void
closeFile
();
...
...
src/Player/MediaPlayer.cpp
查看文件 @
0ed90250
...
...
@@ -64,6 +64,13 @@ void MediaPlayer::pause(bool pause) {
}
}
void
MediaPlayer
::
speed
(
float
speed
)
{
if
(
_delegate
)
{
_delegate
->
speed
(
speed
);
}
}
void
MediaPlayer
::
teardown
()
{
if
(
_delegate
)
{
_delegate
->
teardown
();
...
...
src/Player/MediaPlayer.h
查看文件 @
0ed90250
...
...
@@ -29,6 +29,7 @@ public:
virtual
~
MediaPlayer
();
void
play
(
const
string
&
url
)
override
;
void
pause
(
bool
pause
)
override
;
void
speed
(
float
speed
)
override
;
void
teardown
()
override
;
EventPoller
::
Ptr
getPoller
();
void
setOnCreateSocket
(
Socket
::
onCreateSocket
cb
);
...
...
src/Player/PlayerBase.h
查看文件 @
0ed90250
...
...
@@ -66,6 +66,12 @@ public:
virtual
void
pause
(
bool
bPause
)
{}
/**
* 倍数播放
* @param speed 1.0 2.0 0.5
*/
virtual
void
speed
(
float
speed
)
{}
/**
* 中断播放
*/
virtual
void
teardown
()
{}
...
...
@@ -95,12 +101,24 @@ public:
virtual
float
getProgress
()
const
{
return
0
;}
/**
* 获取播放进度pos,取值 相对开始时间增量 单位秒
* @return
*/
virtual
uint32_t
getProgressPos
()
const
{
return
0
;
}
/**
* 拖动进度条
* @param fProgress 进度,取值 0.0 ~ 1.0
*/
virtual
void
seekTo
(
float
fProgress
)
{}
/**
* 拖动进度条
* @param seekPos 进度,取值 相对于开始时间的增量 单位秒
*/
virtual
void
seekTo
(
uint32_t
seekPos
)
{}
/**
* 设置一个MediaSource,直接生产rtsp/rtmp代理
* @param src
*/
...
...
@@ -175,6 +193,12 @@ public:
}
return
Parent
::
getProgress
();
}
uint32_t
getProgressPos
()
const
override
{
if
(
_delegate
)
{
return
_delegate
->
getProgressPos
();
}
return
Parent
::
getProgressPos
();
}
void
seekTo
(
float
fProgress
)
override
{
if
(
_delegate
)
{
return
_delegate
->
seekTo
(
fProgress
);
...
...
@@ -182,6 +206,13 @@ public:
return
Parent
::
seekTo
(
fProgress
);
}
void
seekTo
(
uint32_t
seekPos
)
override
{
if
(
_delegate
)
{
return
_delegate
->
seekTo
(
seekPos
);
}
return
Parent
::
seekTo
(
seekPos
);
}
void
setMediaSource
(
const
MediaSource
::
Ptr
&
src
)
override
{
if
(
_delegate
)
{
_delegate
->
setMediaSource
(
src
);
...
...
src/Record/MP4Recorder.cpp
查看文件 @
0ed90250
...
...
@@ -107,12 +107,17 @@ void MP4Recorder::closeFile() {
}
void
MP4Recorder
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
if
(
!
_muxer
||
((
_createFileTicker
.
elapsedTime
()
>
_max_second
*
1000
)
&&
if
(
_baseSec
==
0
)
_baseSec
=
frame
->
dts
();
auto
dis
=
frame
->
dts
()
-
_baseSec
;
if
(
!
_muxer
||
((
dis
>
_max_second
*
1000
)
&&
(
!
_haveVideo
||
(
_haveVideo
&&
frame
->
keyFrame
())))
){
//成立条件
//1、_muxer为空
//2、到了切片时间,并且只有音频
//3、到了切片时间,有视频并且遇到视频的关键帧
DebugL
<<
"create file dts:"
<<
frame
->
dts
()
<<
" baseSec:"
<<
_baseSec
;
_baseSec
=
0
;
createFile
();
}
...
...
src/Record/MP4Recorder.h
查看文件 @
0ed90250
...
...
@@ -65,6 +65,8 @@ private:
RecordInfo
_info
;
MP4Muxer
::
Ptr
_muxer
;
list
<
Track
::
Ptr
>
_tracks
;
uint64_t
_baseSec
=
0
;
};
#endif ///ENABLE_MP4
...
...
src/Rtmp/RtmpPlayer.cpp
查看文件 @
0ed90250
...
...
@@ -171,6 +171,11 @@ void RtmpPlayer::pause(bool bPause) {
send_pause
(
bPause
);
}
void
RtmpPlayer
::
speed
(
float
speed
)
{
//todo
}
inline
void
RtmpPlayer
::
send_connect
()
{
AMFValue
obj
(
AMF_OBJECT
);
obj
.
set
(
"app"
,
_app
);
...
...
src/Rtmp/RtmpPlayer.h
查看文件 @
0ed90250
...
...
@@ -38,6 +38,7 @@ public:
void
play
(
const
string
&
strUrl
)
override
;
void
pause
(
bool
bPause
)
override
;
void
speed
(
float
speed
)
override
;
void
teardown
()
override
;
protected
:
...
...
src/Rtmp/RtmpPlayerImp.h
查看文件 @
0ed90250
...
...
@@ -46,6 +46,11 @@ public:
seekToMilliSecond
((
uint32_t
)(
fProgress
*
getDuration
()
*
1000
));
}
void
seekTo
(
uint32_t
seekPos
)
override
{
uint32_t
pos
=
MAX
(
float
(
0
),
MIN
(
seekPos
,
getDuration
()))
*
1000
;
seekToMilliSecond
(
pos
);
}
void
play
(
const
string
&
strUrl
)
override
{
PlayerImp
<
RtmpPlayer
,
RtmpDemuxer
>::
play
(
strUrl
);
}
...
...
src/Rtmp/RtmpSession.cpp
查看文件 @
0ed90250
...
...
@@ -412,6 +412,36 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
//streamBegin
sendUserControl
(
paused
?
CONTROL_STREAM_EOF
:
CONTROL_STREAM_BEGIN
,
STREAM_MEDIA
);
_paused
=
paused
;
auto
stongSrc
=
_player_src
.
lock
();
if
(
stongSrc
)
{
if
(
_paused
)
stongSrc
->
pause
();
else
stongSrc
->
seekTo
(
-
1
);
}
}
void
RtmpSession
::
onCmd_playCtrl
(
AMFDecoder
&
dec
)
{
dec
.
load
<
AMFValue
>
();
auto
ctrlObj
=
dec
.
load
<
AMFValue
>
();
int
ctrlType
=
ctrlObj
[
"ctrlType"
].
as_integer
();
float
speed
=
ctrlObj
[
"speed"
].
as_number
();
AMFValue
status
(
AMF_OBJECT
);
status
.
set
(
"level"
,
"status"
);
status
.
set
(
"code"
,
"NetStream.Speed.Notify"
);
status
.
set
(
"description"
,
"Speeding"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
//streamBegin
sendUserControl
(
CONTROL_STREAM_EOF
,
STREAM_MEDIA
);
auto
stongSrc
=
_player_src
.
lock
();
if
(
stongSrc
)
{
stongSrc
->
speed
(
speed
);
}
}
void
RtmpSession
::
setMetaData
(
AMFDecoder
&
dec
)
{
...
...
@@ -434,6 +464,7 @@ void RtmpSession::onProcessCmd(AMFDecoder &dec) {
s_cmd_functions
.
emplace
(
"play2"
,
&
RtmpSession
::
onCmd_play2
);
s_cmd_functions
.
emplace
(
"seek"
,
&
RtmpSession
::
onCmd_seek
);
s_cmd_functions
.
emplace
(
"pause"
,
&
RtmpSession
::
onCmd_pause
);
s_cmd_functions
.
emplace
(
"onPlayCtrl"
,
&
RtmpSession
::
onCmd_playCtrl
);
});
std
::
string
method
=
dec
.
load
<
std
::
string
>
();
...
...
src/Rtmp/RtmpSession.h
查看文件 @
0ed90250
...
...
@@ -53,6 +53,7 @@ private:
void
onCmd_seek
(
AMFDecoder
&
dec
);
void
onCmd_pause
(
AMFDecoder
&
dec
);
void
onCmd_playCtrl
(
AMFDecoder
&
dec
);
void
setMetaData
(
AMFDecoder
&
dec
);
void
onSendMedia
(
const
RtmpPacket
::
Ptr
&
pkt
);
...
...
src/Rtsp/RtspPlayer.cpp
查看文件 @
0ed90250
...
...
@@ -25,7 +25,8 @@ namespace mediakit {
enum
PlayType
{
type_play
=
0
,
type_pause
,
type_seek
type_seek
,
type_speed
};
RtspPlayer
::
RtspPlayer
(
const
EventPoller
::
Ptr
&
poller
)
:
TcpClient
(
poller
){
...
...
@@ -414,8 +415,13 @@ void RtspPlayer::sendPause(int type , uint32_t seekMS){
}
}
void
RtspPlayer
::
pause
(
bool
pause_flag
)
{
sendPause
(
pause_flag
?
type_pause
:
type_seek
,
getProgressMilliSecond
());
void
RtspPlayer
::
pause
(
bool
bPause
)
{
sendPause
(
bPause
?
type_pause
:
type_seek
,
getProgressMilliSecond
());
}
void
RtspPlayer
::
speed
(
float
speed
)
{
sendRtspRequest
(
"PLAY"
,
_content_base
,
{
"Scale"
,
StrPrinter
<<
speed
});
}
void
RtspPlayer
::
handleResPAUSE
(
const
Parser
&
parser
,
int
type
)
{
...
...
src/Rtsp/RtspPlayer.h
查看文件 @
0ed90250
...
...
@@ -41,7 +41,8 @@ public:
~
RtspPlayer
()
override
;
void
play
(
const
string
&
strUrl
)
override
;
void
pause
(
bool
pause_flag
)
override
;
void
pause
(
bool
bPause
)
override
;
void
speed
(
float
speed
)
override
;
void
teardown
()
override
;
float
getPacketLossRate
(
TrackType
type
)
const
override
;
...
...
src/Rtsp/RtspPlayerImp.h
查看文件 @
0ed90250
...
...
@@ -42,11 +42,24 @@ public:
}
void
seekTo
(
float
fProgress
)
override
{
fProgress
=
MAX
(
float
(
0
),
MIN
(
fProgress
,
float
(
1
.
0
)));
uint32_t
getProgressPos
()
const
override
{
if
(
getDuration
()
>
0
)
{
return
getProgressMilliSecond
();
}
return
PlayerBase
::
getProgressPos
();
};
void
seekTo
(
float
fProgress
)
override
{
fProgress
=
MAX
(
float
(
0
),
MIN
(
fProgress
,
float
(
1
.
0
)));
seekToMilliSecond
((
uint32_t
)(
fProgress
*
getDuration
()
*
1000
));
}
void
seekTo
(
uint32_t
seekPos
)
override
{
uint32_t
pos
=
MAX
(
float
(
0
),
MIN
(
seekPos
,
getDuration
()))
*
1000
;
seekToMilliSecond
(
pos
);
}
private
:
//派生类回调函数
bool
onCheckSDP
(
const
string
&
sdp
)
override
{
...
...
src/Rtsp/RtspSession.cpp
查看文件 @
0ed90250
...
...
@@ -774,21 +774,36 @@ void RtspSession::handleReq_Play(const Parser &parser) {
}
bool
useGOP
=
true
;
_enable_send_rtp
=
false
;
//
_enable_send_rtp = false;
float
iStartTime
=
0
;
auto
strRange
=
parser
[
"Range"
];
if
(
strRange
.
size
())
{
//这个是seek操作
auto
strStart
=
FindField
(
strRange
.
data
(),
"npt="
,
"-"
);
if
(
strStart
==
"now"
)
{
strStart
=
"0"
;
auto
strScale
=
parser
[
"Scale"
];
if
(
strScale
.
size
()
==
0
)
{
if
(
strRange
.
size
())
{
//这个是seek操作
auto
strStart
=
FindField
(
strRange
.
data
(),
"npt="
,
"-"
);
if
(
strStart
==
"now"
)
{
strStart
=
"0"
;
}
iStartTime
=
1000
*
(
float
)
atof
(
strStart
.
data
());
InfoP
(
this
)
<<
"rtsp seekTo(ms):"
<<
iStartTime
;
useGOP
=
!
play_src
->
seekTo
((
uint32_t
)
iStartTime
);
}
else
if
(
play_src
->
totalReaderCount
()
==
0
)
{
//第一个消费者
play_src
->
seekTo
(
0
);
}
else
if
(
play_src
->
totalReaderCount
()
>
0
)
{
_enable_send_rtp
=
true
;
play_src
->
seekTo
(
-
1
);
}
iStartTime
=
1000
*
(
float
)
atof
(
strStart
.
data
());
InfoP
(
this
)
<<
"rtsp seekTo(ms):"
<<
iStartTime
;
useGOP
=
!
play_src
->
seekTo
((
uint32_t
)
iStartTime
);
}
else
if
(
play_src
->
totalReaderCount
()
==
0
)
{
//第一个消费者
play_src
->
seekTo
(
0
);
}
else
{
play_src
->
speed
(
atof
(
strScale
.
data
()));
}
_StrPrinter
rtp_info
;
...
...
@@ -845,7 +860,17 @@ void RtspSession::handleReq_Pause(const Parser &parser) {
}
sendRtspResponse
(
"200 OK"
);
_enable_send_rtp
=
false
;
auto
play_src
=
_play_src
.
lock
();
if
(
!
play_src
)
{
send_StreamNotFound
();
shutdown
(
SockException
(
Err_shutdown
,
"rtsp stream released"
));
return
;
}
play_src
->
pause
();
//_enable_send_rtp = false;
}
void
RtspSession
::
handleReq_Teardown
(
const
Parser
&
parser
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论