mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-25 20:27:34 +08:00
合并pr:#1025
This commit is contained in:
parent
30b139eaf0
commit
4dbe0a1d3e
@ -6,32 +6,26 @@ set(CMAKE_CXX_STANDARD 11)
|
|||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
#set(CMAKE_BUILD_TYPE "Release")
|
#set(CMAKE_BUILD_TYPE "Release")
|
||||||
|
message(STATUS "编译类型:${CMAKE_BUILD_TYPE}")
|
||||||
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
|
|
||||||
message(STATUS "Release版本")
|
|
||||||
set(BuildType "Release")
|
|
||||||
else ()
|
|
||||||
set(BuildType "Debug")
|
|
||||||
message(STATUS "Debug版本")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
#设置bin和lib库目录
|
#设置bin和lib库目录
|
||||||
set(RELEASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/release)
|
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")
|
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
SET(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/linux${CL_32_64}/${BuildType})
|
SET(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/linux/${CMAKE_BUILD_TYPE})
|
||||||
SET(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/linux${CL_32_64}/${BuildType})
|
SET(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/linux/${CMAKE_BUILD_TYPE})
|
||||||
add_compile_options(-fPIC -Wall -Wno-unused-variable -Wno-unused-value)
|
add_compile_options(-fPIC -Wall -Wno-unused-variable -Wno-unused-value)
|
||||||
elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||||
SET(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/windows${CL_32_64}/${BuildType})
|
if (CMAKE_CL_64)
|
||||||
SET(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/windows${CL_32_64}/${BuildType})
|
set(CL_32_64 64)
|
||||||
|
else ()
|
||||||
|
set(CL_32_64 32)
|
||||||
|
endif ()
|
||||||
|
SET(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/windows${CL_32_64}/${CMAKE_BUILD_TYPE})
|
||||||
|
SET(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/windows${CL_32_64}/${CMAKE_BUILD_TYPE})
|
||||||
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||||
SET(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/mac${CL_32_64}/${BuildType})
|
SET(LIBRARY_OUTPUT_PATH ${RELEASE_DIR}/mac/${CMAKE_BUILD_TYPE})
|
||||||
SET(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/mac${CL_32_64/${BuildType})
|
SET(EXECUTABLE_OUTPUT_PATH ${RELEASE_DIR}/mac/${CMAKE_BUILD_TYPE})
|
||||||
add_compile_options(-Wall -Wno-unused-variable -Wno-unused-value)
|
add_compile_options(-Wall -Wno-unused-variable -Wno-unused-value)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
@ -62,10 +56,9 @@ option(ENABLE_MEM_DEBUG "Enable Memory Debug" false)
|
|||||||
option(ENABLE_ASAN "Enable Address Sanitize" false)
|
option(ENABLE_ASAN "Enable Address Sanitize" false)
|
||||||
option(ENABLE_WEBRTC "Enable WebRTC" false)
|
option(ENABLE_WEBRTC "Enable WebRTC" false)
|
||||||
option(ENABLE_PLAYER "Enable Player" true)
|
option(ENABLE_PLAYER "Enable Player" true)
|
||||||
option(ENABLE_MsvcMT "Enable MSVC Mt/Mtd lib" true)
|
option(ENABLE_MSVC_MT "Enable MSVC Mt/Mtd lib" true)
|
||||||
|
|
||||||
|
if (MSVC AND ENABLE_MSVC_MT)
|
||||||
if (ENABLE_STATIC AND MSVC)
|
|
||||||
set(CompilerFlags
|
set(CompilerFlags
|
||||||
CMAKE_CXX_FLAGS
|
CMAKE_CXX_FLAGS
|
||||||
CMAKE_CXX_FLAGS_DEBUG
|
CMAKE_CXX_FLAGS_DEBUG
|
||||||
@ -147,7 +140,6 @@ if (OPENSSL_FOUND AND ENABLE_OPENSSL)
|
|||||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux" AND OPENSSL_USE_STATIC_LIBS)
|
if (CMAKE_SYSTEM_NAME MATCHES "Linux" AND OPENSSL_USE_STATIC_LIBS)
|
||||||
list(APPEND LINK_LIB_LIST dl)
|
list(APPEND LINK_LIB_LIST dl)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
else ()
|
else ()
|
||||||
message(WARNING "openssl未找到,rtmp将不支持flash播放器,https/wss/rtsps/rtmps也将失效")
|
message(WARNING "openssl未找到,rtmp将不支持flash播放器,https/wss/rtsps/rtmps也将失效")
|
||||||
endif ()
|
endif ()
|
||||||
@ -301,23 +293,28 @@ if (ENABLE_WEBRTC)
|
|||||||
file(GLOB SRC_WEBRTC_LIST ./webrtc/*.cpp ./webrtc/*.h ./webrtc/*.hpp)
|
file(GLOB SRC_WEBRTC_LIST ./webrtc/*.cpp ./webrtc/*.h ./webrtc/*.hpp)
|
||||||
add_library(webrtc ${SRC_WEBRTC_LIST})
|
add_library(webrtc ${SRC_WEBRTC_LIST})
|
||||||
list(APPEND LINK_LIB_LIST webrtc)
|
list(APPEND LINK_LIB_LIST webrtc)
|
||||||
|
message(STATUS "webrtc功能已开启")
|
||||||
else ()
|
else ()
|
||||||
message(WARNING "srtp未找到, webrtc相关功能打开失败")
|
message(WARNING "srtp未找到, webrtc相关功能打开失败")
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT IOS)
|
#ios不编译可执行程序
|
||||||
#测试程序
|
if (IOS)
|
||||||
if (ENABLE_TESTS)
|
return()
|
||||||
add_subdirectory(tests)
|
endif()
|
||||||
endif ()
|
|
||||||
#主服务器
|
|
||||||
if (ENABLE_SERVER)
|
|
||||||
add_subdirectory(server)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
#播放器
|
#测试程序
|
||||||
if (ENABLE_PLAYER)
|
if (ENABLE_TESTS)
|
||||||
add_subdirectory(player)
|
add_subdirectory(tests)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
#主服务器
|
||||||
|
if (ENABLE_SERVER)
|
||||||
|
add_subdirectory(server)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
#播放器
|
||||||
|
if (ENABLE_PLAYER)
|
||||||
|
add_subdirectory(player)
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -143,10 +143,11 @@ 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);
|
typedef int(API_CALL *on_mk_media_seek)(void *user_data,uint32_t stamp_ms);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收到客户端的pause请求时触发该回调
|
* 收到客户端的pause或resume请求时触发该回调
|
||||||
* @param user_data 用户数据指针,通过mk_media_set_on_pause设置
|
* @param user_data 用户数据指针,通过mk_media_set_on_pause设置
|
||||||
|
* @param pause 1:暂停, 0: 恢复
|
||||||
*/
|
*/
|
||||||
typedef int(API_CALL* on_mk_media_pause)(void* user_data);
|
typedef int(API_CALL* on_mk_media_pause)(void* user_data, int pause);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收到客户端的speed请求时触发该回调
|
* 收到客户端的speed请求时触发该回调
|
||||||
|
@ -90,9 +90,9 @@ API_EXPORT void API_CALL mk_player_seekto(mk_player ctx, float progress);
|
|||||||
/**
|
/**
|
||||||
* 设置点播进度条
|
* 设置点播进度条
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param seekPos 取值范围 相对于开始时间增量 单位秒
|
* @param seek_pos 取值范围 相对于开始时间增量 单位秒
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_player_seektoByPos(mk_player ctx, int seekPos);
|
API_EXPORT void API_CALL mk_player_seekto_pos(mk_player ctx, int seek_pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置播放器开启播放结果回调函数
|
* 设置播放器开启播放结果回调函数
|
||||||
@ -124,7 +124,7 @@ API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb
|
|||||||
* 获取视频codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
* 获取视频codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
||||||
* @param ctx 播放器指针
|
* @param ctx 播放器指针
|
||||||
*/
|
*/
|
||||||
API_EXPORT int API_CALL mk_player_video_codecId(mk_player ctx);
|
API_EXPORT int API_CALL mk_player_video_codec_id(mk_player ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取视频codec_id, vendor类型, 私有头数据 codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
* 获取视频codec_id, vendor类型, 私有头数据 codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
||||||
@ -133,7 +133,7 @@ API_EXPORT int API_CALL mk_player_video_codecId(mk_player ctx);
|
|||||||
* @param head 厂家SDK头数据
|
* @param head 厂家SDK头数据
|
||||||
* @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_codec_id_vendor_head(mk_player ctx, char* vendor, char* head, int* headLen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取视频宽度
|
* 获取视频宽度
|
||||||
@ -154,7 +154,7 @@ API_EXPORT float API_CALL mk_player_video_fps(mk_player ctx);
|
|||||||
* 获取音频codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
* 获取音频codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
||||||
* @param ctx 播放器指针
|
* @param ctx 播放器指针
|
||||||
*/
|
*/
|
||||||
API_EXPORT int API_CALL mk_player_audio_codecId(mk_player ctx);
|
API_EXPORT int API_CALL mk_player_audio_codec_id(mk_player ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取音频采样率
|
* 获取音频采样率
|
||||||
|
@ -76,24 +76,24 @@ protected:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool seekTo(MediaSource &sender,uint32_t ui32Stamp) override{
|
bool seekTo(MediaSource &sender, uint32_t stamp) override {
|
||||||
if(!_on_seek){
|
if (!_on_seek) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _on_seek(_on_seek_data,ui32Stamp);
|
return _on_seek(_on_seek_data, stamp);
|
||||||
}
|
}
|
||||||
// 通知暂停
|
|
||||||
bool pause(MediaSource &sender) override {
|
// 通知暂停或恢复
|
||||||
if (!_on_pause)
|
bool pause(MediaSource &sender, bool pause) override {
|
||||||
{
|
if (!_on_pause) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _on_pause(_on_pause_data);
|
return _on_pause(_on_pause_data, pause);
|
||||||
}
|
}
|
||||||
|
|
||||||
//通知倍数播放
|
//通知倍数播放
|
||||||
bool speed(MediaSource& sender, float speed) override {
|
bool speed(MediaSource &sender, float speed) override {
|
||||||
if (!_on_speed)
|
if (!_on_speed) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return _on_speed(_on_pause_data, speed);
|
return _on_speed(_on_pause_data, speed);
|
||||||
@ -130,23 +130,21 @@ API_EXPORT void API_CALL mk_media_set_on_close(mk_media ctx, on_mk_media_close c
|
|||||||
(*obj)->setOnClose(cb, user_data);
|
(*obj)->setOnClose(cb, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_media_set_on_seek(mk_media ctx, on_mk_media_seek cb, void *user_data){
|
API_EXPORT void API_CALL mk_media_set_on_seek(mk_media ctx, on_mk_media_seek cb, void *user_data) {
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
(*obj)->setOnSeek(cb, user_data);
|
(*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)
|
API_EXPORT void API_CALL mk_media_set_on_pause(mk_media ctx, on_mk_media_pause cb, void *user_data) {
|
||||||
{
|
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
(*obj)->setOnPause(cb, user_data);
|
(*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)
|
API_EXPORT void API_CALL mk_media_set_on_speed(mk_media ctx, on_mk_media_speed cb, void *user_data) {
|
||||||
{
|
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaHelper::Ptr* obj = (MediaHelper::Ptr*) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
(*obj)->setOnSpeed(cb, user_data);
|
(*obj)->setOnSpeed(cb, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +171,12 @@ 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) {
|
API_EXPORT void API_CALL mk_player_speed(mk_player ctx, float speed) {
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaPlayerForC& obj = **((MediaPlayerForC::Ptr*)ctx);
|
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *) ctx);
|
||||||
auto player = obj.getPlayer();
|
auto player = obj.getPlayer();
|
||||||
player->getPoller()->async([speed, player]() {
|
player->getPoller()->async([speed, player]() {
|
||||||
//切换线程后再操作
|
//切换线程后再操作
|
||||||
player->speed(speed);
|
player->speed(speed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_player_seekto(mk_player ctx, float progress) {
|
API_EXPORT void API_CALL mk_player_seekto(mk_player ctx, float progress) {
|
||||||
@ -189,14 +189,14 @@ 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){
|
API_EXPORT void API_CALL mk_player_seekto_pos(mk_player ctx, int seek_pos) {
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaPlayerForC& obj = **((MediaPlayerForC::Ptr*)ctx);
|
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *) ctx);
|
||||||
auto player = obj.getPlayer();
|
auto player = obj.getPlayer();
|
||||||
player->getPoller()->async([seekPos, player]() {
|
player->getPoller()->async([seek_pos, player]() {
|
||||||
//切换线程后再操作
|
//切换线程后再操作
|
||||||
player->seekTo((uint32_t)seekPos);
|
player->seekTo((uint32_t) seek_pos);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mk_player_set_on_event(mk_player ctx, on_mk_play_event cb, void *user_data, int type) {
|
static void mk_player_set_on_event(mk_player ctx, on_mk_play_event cb, void *user_data, int type) {
|
||||||
@ -219,30 +219,26 @@ API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb
|
|||||||
obj.setOnData(cb,user_data);
|
obj.setOnData(cb,user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_video_codecId(mk_player ctx){
|
API_EXPORT int API_CALL mk_player_video_codec_id(mk_player ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
||||||
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
||||||
return track ? track->getCodecId() : CodecInvalid;
|
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)
|
API_EXPORT int API_CALL mk_player_video_codec_id_vendor_head(mk_player ctx, char *vendor, char *head, int *head_len) {
|
||||||
{
|
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaPlayerForC& obj = **((MediaPlayerForC::Ptr*)ctx);
|
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *) ctx);
|
||||||
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
||||||
int codecId = track ? track->getCodecId() : CodecInvalid;
|
int codecId = track ? track->getCodecId() : CodecInvalid;
|
||||||
if (codecId == CodecH264)
|
if (codecId == CodecH264) {
|
||||||
{
|
|
||||||
auto h264Track = dynamic_pointer_cast<H264Track>(obj->getTrack(TrackVideo));
|
auto h264Track = dynamic_pointer_cast<H264Track>(obj->getTrack(TrackVideo));
|
||||||
auto pps = h264Track->getPps();
|
auto pps = h264Track->getPps();
|
||||||
auto ppsLen = pps.size();
|
auto ppsLen = pps.size();
|
||||||
if (ppsLen >= (4 + 16))
|
if (ppsLen >= (4 + 16)) {
|
||||||
{
|
|
||||||
std::string temVendor = std::string(pps.c_str() + 4, 16);
|
std::string temVendor = std::string(pps.c_str() + 4, 16);
|
||||||
memcpy(vendor, temVendor.c_str(), temVendor.length());
|
memcpy(vendor, temVendor.c_str(), temVendor.length());
|
||||||
if (ppsLen > (4 + 16))
|
if (ppsLen > (4 + 16)) {
|
||||||
{
|
|
||||||
std::string temHead = std::string(pps.c_str() + 20, ppsLen - 20);
|
std::string temHead = std::string(pps.c_str() + 20, ppsLen - 20);
|
||||||
memcpy(head, temHead.c_str(), temHead.length());
|
memcpy(head, temHead.c_str(), temHead.length());
|
||||||
*head_len = temHead.length();
|
*head_len = temHead.length();
|
||||||
@ -273,7 +269,7 @@ API_EXPORT float API_CALL mk_player_video_fps(mk_player ctx) {
|
|||||||
return track ? track->getVideoFps() : 0;
|
return track ? track->getVideoFps() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_codecId(mk_player ctx){
|
API_EXPORT int API_CALL mk_player_audio_codec_id(mk_player ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
||||||
auto track = dynamic_pointer_cast<AudioTrack>(obj->getTrack(TrackAudio));
|
auto track = dynamic_pointer_cast<AudioTrack>(obj->getTrack(TrackAudio));
|
||||||
|
@ -93,8 +93,8 @@ void API_CALL on_mk_play_event_func(void *user_data, int err_code, const char *e
|
|||||||
log_debug("play success!");
|
log_debug("play success!");
|
||||||
ctx->media = mk_media_create("__defaultVhost__", "live", "test", 0, 0, 0);
|
ctx->media = mk_media_create("__defaultVhost__", "live", "test", 0, 0, 0);
|
||||||
|
|
||||||
int video_codec = mk_player_video_codecId(ctx->player);
|
int video_codec = mk_player_video_codec_id(ctx->player);
|
||||||
int audio_codec = mk_player_audio_codecId(ctx->player);
|
int audio_codec = mk_player_audio_codec_id(ctx->player);
|
||||||
if(video_codec != -1){
|
if(video_codec != -1){
|
||||||
mk_media_init_video(ctx->media, video_codec,
|
mk_media_init_video(ctx->media, video_codec,
|
||||||
mk_player_video_width(ctx->player),
|
mk_player_video_width(ctx->player),
|
||||||
|
@ -90,7 +90,7 @@ static HttpApi toApi(const function<void(API_ARGS_MAP_ASYNC)> &cb) {
|
|||||||
|
|
||||||
//参数解析成map
|
//参数解析成map
|
||||||
auto args = getAllArgs(parser);
|
auto args = getAllArgs(parser);
|
||||||
cb(sender, parser.getHeader(), headerOut, args, val, invoker);
|
cb(sender, headerOut, HttpAllArgs<decltype(args)>(parser, args), val, invoker);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,26 +107,24 @@ static HttpApi toApi(const function<void(API_ARGS_JSON_ASYNC)> &cb) {
|
|||||||
HttpSession::KeyValue headerOut;
|
HttpSession::KeyValue headerOut;
|
||||||
headerOut["Content-Type"] = string("application/json; charset=") + charSet;
|
headerOut["Content-Type"] = string("application/json; charset=") + charSet;
|
||||||
|
|
||||||
Json::Value out;
|
Json::Value val;
|
||||||
out["code"] = API::Success;
|
val["code"] = API::Success;
|
||||||
|
|
||||||
if (parser["Content-Type"].find("application/json") == string::npos) {
|
if (parser["Content-Type"].find("application/json") == string::npos) {
|
||||||
throw InvalidArgsException("该接口只支持json格式的请求");
|
throw InvalidArgsException("该接口只支持json格式的请求");
|
||||||
}
|
}
|
||||||
//参数解析成json对象然后处理
|
//参数解析成json对象然后处理
|
||||||
Json::Value in;
|
Json::Value args;
|
||||||
Json::Reader reader;
|
Json::Reader reader;
|
||||||
reader.parse(parser.Content(), in);
|
reader.parse(parser.Content(), args);
|
||||||
|
|
||||||
//参数解析成map
|
cb(sender, headerOut, HttpAllArgs<decltype(args)>(parser, args), val, invoker);
|
||||||
auto urlArgs = getAllArgs(parser);
|
|
||||||
cb(sender, parser.getHeader(), headerOut, in, urlArgs, out, invoker);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static HttpApi toApi(const function<void(API_ARGS_JSON)> &cb) {
|
static HttpApi toApi(const function<void(API_ARGS_JSON)> &cb) {
|
||||||
return toApi([cb](API_ARGS_JSON_ASYNC) {
|
return toApi([cb](API_ARGS_JSON_ASYNC) {
|
||||||
cb(API_ARGS_JSON_VALUE);
|
cb(API_ARGS_VALUE);
|
||||||
invoker(200, headerOut, val.toStyledString());
|
invoker(200, headerOut, val.toStyledString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -140,7 +138,7 @@ static HttpApi toApi(const function<void(API_ARGS_STRING_ASYNC)> &cb) {
|
|||||||
Json::Value val;
|
Json::Value val;
|
||||||
val["code"] = API::Success;
|
val["code"] = API::Success;
|
||||||
|
|
||||||
cb(sender, parser.getHeader(), headerOut, parser, val, invoker);
|
cb(sender, headerOut, HttpAllArgs<string>(parser, (string &)parser.Content()), val, invoker);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,19 +228,18 @@ static inline void addHttpListener(){
|
|||||||
size = body->remainSize();
|
size = body->remainSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& content = parser.Content();
|
|
||||||
if (size && size < 4 * 1024) {
|
if (size && size < 4 * 1024) {
|
||||||
string contentOut = body->readData(size)->toString();
|
string contentOut = body->readData(size)->toString();
|
||||||
DebugL << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n"
|
DebugL << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n"
|
||||||
<< "# content:\r\n" << (content.size() > 4 * 1024 ? content.substr(0, 4 * 1024) : content) << "\r\n"
|
<< "# content:\r\n" << parser.Content() << "\r\n"
|
||||||
<< "# response:\r\n"
|
<< "# response:\r\n"
|
||||||
<< contentOut << "\r\n";
|
<< contentOut << "\r\n";
|
||||||
invoker(code, headerOut, contentOut);
|
invoker(code, headerOut, contentOut);
|
||||||
} else {
|
} else {
|
||||||
DebugL << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n"
|
DebugL << "\r\n# request:\r\n" << parser.Method() << " " << parser.FullUrl() << "\r\n"
|
||||||
<< "# content:\r\n" << (content.size() > 4 * 1024 ? content.substr(0, 4 * 1024) : content) << "\r\n"
|
<< "# content:\r\n" << parser.Content() << "\r\n"
|
||||||
<< "# response size:"
|
<< "# response size:"
|
||||||
<< size << "\r\n";
|
<< size << "\r\n";
|
||||||
invoker(code, headerOut, body);
|
invoker(code, headerOut, body);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -279,8 +276,8 @@ static recursive_mutex s_ffmpegMapMtx;
|
|||||||
|
|
||||||
#if defined(ENABLE_RTPPROXY)
|
#if defined(ENABLE_RTPPROXY)
|
||||||
//rtp服务器列表
|
//rtp服务器列表
|
||||||
/*static*/ unordered_map<string, RtpServer::Ptr> s_rtpServerMap;
|
static unordered_map<string, RtpServer::Ptr> s_rtpServerMap;
|
||||||
/*static*/ recursive_mutex s_rtpServerMapMtx;
|
static recursive_mutex s_rtpServerMapMtx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline string getProxyKey(const string &vhost, const string &app, const string &stream) {
|
static inline string getProxyKey(const string &vhost, const string &app, const string &stream) {
|
||||||
@ -412,7 +409,7 @@ void installWebApi() {
|
|||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
auto &ini = mINI::Instance();
|
auto &ini = mINI::Instance();
|
||||||
int changed = API::Success;
|
int changed = API::Success;
|
||||||
for (auto &pr : allArgs) {
|
for (auto &pr : allArgs.getArgs()) {
|
||||||
if (ini.find(pr.first) == ini.end()) {
|
if (ini.find(pr.first) == ini.end()) {
|
||||||
#if 1
|
#if 1
|
||||||
//没有这个key
|
//没有这个key
|
||||||
@ -564,7 +561,7 @@ void installWebApi() {
|
|||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
Value jsession;
|
Value jsession;
|
||||||
uint16_t local_port = allArgs["local_port"].as<uint16_t>();
|
uint16_t local_port = allArgs["local_port"].as<uint16_t>();
|
||||||
string &peer_ip = allArgs["peer_ip"];
|
string peer_ip = allArgs["peer_ip"];
|
||||||
|
|
||||||
SessionMap::Instance().for_each_session([&](const string &id,const Session::Ptr &session){
|
SessionMap::Instance().for_each_session([&](const string &id,const Session::Ptr &session){
|
||||||
if(local_port != 0 && local_port != session->get_local_port()){
|
if(local_port != 0 && local_port != session->get_local_port()){
|
||||||
@ -602,7 +599,7 @@ void installWebApi() {
|
|||||||
api_regist("/index/api/kick_sessions",[](API_ARGS_MAP){
|
api_regist("/index/api/kick_sessions",[](API_ARGS_MAP){
|
||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
uint16_t local_port = allArgs["local_port"].as<uint16_t>();
|
uint16_t local_port = allArgs["local_port"].as<uint16_t>();
|
||||||
string &peer_ip = allArgs["peer_ip"];
|
string peer_ip = allArgs["peer_ip"];
|
||||||
size_t count_hit = 0;
|
size_t count_hit = 0;
|
||||||
|
|
||||||
list<Session::Ptr> session_list;
|
list<Session::Ptr> session_list;
|
||||||
@ -859,7 +856,7 @@ void installWebApi() {
|
|||||||
//测试url http://127.0.0.1/index/api/downloadBin
|
//测试url http://127.0.0.1/index/api/downloadBin
|
||||||
api_regist("/index/api/downloadBin",[](API_ARGS_MAP_ASYNC){
|
api_regist("/index/api/downloadBin",[](API_ARGS_MAP_ASYNC){
|
||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
invoker.responseFile(headerIn,StrCaseMap(),exePath());
|
invoker.responseFile(allArgs.getParser().getHeader(),StrCaseMap(),exePath());
|
||||||
});
|
});
|
||||||
|
|
||||||
#if defined(ENABLE_RTPPROXY)
|
#if defined(ENABLE_RTPPROXY)
|
||||||
@ -935,56 +932,21 @@ void installWebApi() {
|
|||||||
api_regist("/index/api/startSendRtp",[](API_ARGS_MAP_ASYNC){
|
api_regist("/index/api/startSendRtp",[](API_ARGS_MAP_ASYNC){
|
||||||
CHECK_SECRET();
|
CHECK_SECRET();
|
||||||
CHECK_ARGS("vhost", "app", "stream", "ssrc", "dst_url", "dst_port", "is_udp");
|
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();
|
|
||||||
|
|
||||||
MediaSource::findAsync(info, session_ptr, [=](const MediaSource::Ptr& src_in) mutable {
|
auto src = MediaSource::find(allArgs["vhost"], allArgs["app"], allArgs["stream"]);
|
||||||
if (!src_in) {
|
if (!src) {
|
||||||
val["code"] = API::OtherFailed;
|
throw ApiRetException("该媒体流不存在", 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());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
//src_port为空时,则随机本地端口
|
||||||
auto src = MediaSource::find(allArgs["vhost"], allArgs["app"], allArgs["stream"]);
|
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 (!src) {
|
if (ex) {
|
||||||
throw ApiRetException("该媒体流不存在", API::OtherFailed);
|
val["code"] = API::OtherFailed;
|
||||||
|
val["msg"] = ex.what();
|
||||||
}
|
}
|
||||||
|
val["local_port"] = local_port;
|
||||||
//src_port为空时,则随机本地端口
|
invoker(200, headerOut, val.toStyledString());
|
||||||
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){
|
api_regist("/index/api/stopSendRtp",[](API_ARGS_MAP){
|
||||||
@ -1149,7 +1111,7 @@ void installWebApi() {
|
|||||||
|
|
||||||
//截图存在,且未过期,那么返回之
|
//截图存在,且未过期,那么返回之
|
||||||
res_old_snap = true;
|
res_old_snap = true;
|
||||||
responseSnap(path, headerIn, invoker);
|
responseSnap(path, allArgs.getParser().getHeader(), invoker);
|
||||||
//中断遍历
|
//中断遍历
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@ -1171,7 +1133,7 @@ void installWebApi() {
|
|||||||
|
|
||||||
//启动FFmpeg进程,开始截图,生成临时文件,截图成功后替换为正式文件
|
//启动FFmpeg进程,开始截图,生成临时文件,截图成功后替换为正式文件
|
||||||
auto new_snap_tmp = new_snap + ".tmp";
|
auto new_snap_tmp = new_snap + ".tmp";
|
||||||
FFmpegSnap::makeSnap(allArgs["url"], new_snap_tmp, allArgs["timeout_sec"], [invoker, headerIn, new_snap, new_snap_tmp](bool success) {
|
FFmpegSnap::makeSnap(allArgs["url"], new_snap_tmp, allArgs["timeout_sec"], [invoker, allArgs, new_snap, new_snap_tmp](bool success) {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
//生成截图失败,可能残留空文件
|
//生成截图失败,可能残留空文件
|
||||||
File::delete_file(new_snap_tmp.data());
|
File::delete_file(new_snap_tmp.data());
|
||||||
@ -1180,7 +1142,7 @@ void installWebApi() {
|
|||||||
File::delete_file(new_snap.data());
|
File::delete_file(new_snap.data());
|
||||||
rename(new_snap_tmp.data(), new_snap.data());
|
rename(new_snap_tmp.data(), new_snap.data());
|
||||||
}
|
}
|
||||||
responseSnap(new_snap, headerIn, invoker);
|
responseSnap(new_snap, allArgs.getParser().getHeader(), invoker);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1217,9 +1179,9 @@ void installWebApi() {
|
|||||||
api_regist("/index/api/webrtc",[](API_ARGS_STRING_ASYNC){
|
api_regist("/index/api/webrtc",[](API_ARGS_STRING_ASYNC){
|
||||||
CHECK_ARGS("app", "stream");
|
CHECK_ARGS("app", "stream");
|
||||||
|
|
||||||
auto offer_sdp = allArgs.Content();
|
auto offer_sdp = allArgs.getArgs();
|
||||||
auto type = allArgs.getUrlArgs()["type"];
|
auto type = allArgs["type"];
|
||||||
MediaInfo info(StrPrinter << "rtc://" << headerIn["Host"] << "/" << allArgs.getUrlArgs()["app"] << "/" << allArgs.getUrlArgs()["stream"] << "?" << allArgs.Params());
|
MediaInfo info(StrPrinter << "rtc://" << allArgs["Host"] << "/" << allArgs["app"] << "/" << allArgs["stream"] << "?" << allArgs.getParser().Params());
|
||||||
|
|
||||||
//设置返回类型
|
//设置返回类型
|
||||||
headerOut["Content-Type"] = HttpFileManager::getContentType(".json");
|
headerOut["Content-Type"] = HttpFileManager::getContentType(".json");
|
||||||
|
131
server/WebApi.h
131
server/WebApi.h
@ -79,16 +79,117 @@ public:
|
|||||||
~SuccessException() = default;
|
~SuccessException() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ApiArgsType = map<string, variant, StrCaseCompare>;
|
using ApiArgsType = map<string, string, StrCaseCompare>;
|
||||||
|
|
||||||
#define API_ARGS_MAP SockInfo &sender, HttpSession::KeyValue &headerIn, HttpSession::KeyValue &headerOut, ApiArgsType &allArgs, Json::Value &val
|
template<typename Args, typename First>
|
||||||
|
string getValue(Args &args, const First &first) {
|
||||||
|
return args[first];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename First>
|
||||||
|
string getValue(Json::Value &args, const First &first) {
|
||||||
|
return args[first].asString();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename First>
|
||||||
|
string getValue(string &args, const First &first) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename First>
|
||||||
|
string getValue(const Parser &parser, const First &first) {
|
||||||
|
auto ret = parser.getUrlArgs()[first];
|
||||||
|
if (!ret.empty()) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return parser.getHeader()[first];
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename First>
|
||||||
|
string getValue(Parser &parser, const First &first) {
|
||||||
|
return getValue((const Parser &) parser, first);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Args, typename First>
|
||||||
|
string getValue(const Parser &parser, Args &args, const First &first) {
|
||||||
|
auto ret = getValue(args, first);
|
||||||
|
if (!ret.empty()) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return getValue(parser, first);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Args>
|
||||||
|
class HttpAllArgs {
|
||||||
|
public:
|
||||||
|
HttpAllArgs(const Parser &parser, Args &args) {
|
||||||
|
_get_args = [&args]() {
|
||||||
|
return (void *) &args;
|
||||||
|
};
|
||||||
|
_get_parser = [&parser]() -> const Parser & {
|
||||||
|
return parser;
|
||||||
|
};
|
||||||
|
_get_value = [](HttpAllArgs &that, const string &key) {
|
||||||
|
return getValue(that.getParser(), that.getArgs(), key);
|
||||||
|
};
|
||||||
|
_clone = [&](HttpAllArgs &that) {
|
||||||
|
that._get_args = [args]() {
|
||||||
|
return (void *) &args;
|
||||||
|
};
|
||||||
|
that._get_parser = [parser]() -> const Parser & {
|
||||||
|
return parser;
|
||||||
|
};
|
||||||
|
that._get_value = [](HttpAllArgs &that, const string &key) {
|
||||||
|
return getValue(that.getParser(), that.getArgs(), key);
|
||||||
|
};
|
||||||
|
that._cache_able = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpAllArgs(const HttpAllArgs &that) {
|
||||||
|
if (that._cache_able) {
|
||||||
|
_get_args = that._get_args;
|
||||||
|
_get_parser = that._get_parser;
|
||||||
|
_get_value = that._get_value;
|
||||||
|
} else {
|
||||||
|
that._clone(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~HttpAllArgs() = default;
|
||||||
|
|
||||||
|
template<typename Key>
|
||||||
|
variant operator[](const Key &key) const {
|
||||||
|
return (variant)_get_value(*(HttpAllArgs*)this, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Parser &getParser() const {
|
||||||
|
return _get_parser();
|
||||||
|
}
|
||||||
|
|
||||||
|
Args &getArgs() {
|
||||||
|
return *((Args *) _get_args());
|
||||||
|
}
|
||||||
|
|
||||||
|
const Args &getArgs() const {
|
||||||
|
return *((Args *) _get_args());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _cache_able = false;
|
||||||
|
function<void *() > _get_args;
|
||||||
|
function<const Parser &() > _get_parser;
|
||||||
|
function<string(HttpAllArgs &that, const string &key)> _get_value;
|
||||||
|
function<void(HttpAllArgs &that) > _clone;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define API_ARGS_MAP SockInfo &sender, HttpSession::KeyValue &headerOut, const HttpAllArgs<ApiArgsType> &allArgs, Json::Value &val
|
||||||
#define API_ARGS_MAP_ASYNC API_ARGS_MAP, const HttpSession::HttpResponseInvoker &invoker
|
#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 &bodyArgs, ApiArgsType &allArgs, Json::Value &val
|
#define API_ARGS_JSON SockInfo &sender, HttpSession::KeyValue &headerOut, const HttpAllArgs<Json::Value> &allArgs, Json::Value &val
|
||||||
#define API_ARGS_JSON_ASYNC API_ARGS_JSON, const HttpSession::HttpResponseInvoker &invoker
|
#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 SockInfo &sender, HttpSession::KeyValue &headerOut, const HttpAllArgs<string> &allArgs, Json::Value &val
|
||||||
#define API_ARGS_STRING_ASYNC API_ARGS_STRING, const HttpSession::HttpResponseInvoker &invoker
|
#define API_ARGS_STRING_ASYNC API_ARGS_STRING, const HttpSession::HttpResponseInvoker &invoker
|
||||||
#define API_ARGS_VALUE sender, headerIn, headerOut, allArgs, val
|
#define API_ARGS_VALUE sender, headerOut, allArgs, val
|
||||||
#define API_ARGS_JSON_VALUE sender, headerIn, headerOut, bodyArgs, allArgs, val
|
|
||||||
|
|
||||||
//注册http请求参数是map<string, variant, StrCaseCompare>类型的http api
|
//注册http请求参数是map<string, variant, StrCaseCompare>类型的http api
|
||||||
void api_regist(const string &api_path, const function<void(API_ARGS_MAP)> &func);
|
void api_regist(const string &api_path, const function<void(API_ARGS_MAP)> &func);
|
||||||
@ -106,26 +207,16 @@ void api_regist(const string &api_path, const function<void(API_ARGS_STRING)> &f
|
|||||||
void api_regist(const string &api_path, const function<void(API_ARGS_STRING_ASYNC)> &func);
|
void api_regist(const string &api_path, const function<void(API_ARGS_STRING_ASYNC)> &func);
|
||||||
|
|
||||||
template<typename Args, typename First>
|
template<typename Args, typename First>
|
||||||
bool checkArgs(Args &&args, First &&first) {
|
bool checkArgs(Args &args, const First &first) {
|
||||||
return !args[first].empty();
|
return !args[first].empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Args, typename First, typename ...KeyTypes>
|
template<typename Args, typename First, typename ...KeyTypes>
|
||||||
bool checkArgs(Args &&args, First &&first, KeyTypes &&...keys) {
|
bool checkArgs(Args &args, const First &first, const KeyTypes &...keys) {
|
||||||
return !args[first].empty() && checkArgs(std::forward<Args>(args), std::forward<KeyTypes>(keys)...);
|
return checkArgs(args, first) && checkArgs(args, keys...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename First>
|
//检查http url中或body中或http header参数是否为空的宏
|
||||||
bool checkArgs(const Parser &args, First &&first) {
|
|
||||||
return !args.getUrlArgs()[first].empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename First, typename ...KeyTypes>
|
|
||||||
bool checkArgs(const Parser &args, First &&first, KeyTypes &&...keys) {
|
|
||||||
return !args.getUrlArgs()[first].empty() && checkArgs(args, std::forward<KeyTypes>(keys)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
//检查http参数是否为空的宏
|
|
||||||
#define CHECK_ARGS(...) \
|
#define CHECK_ARGS(...) \
|
||||||
if(!checkArgs(allArgs,##__VA_ARGS__)){ \
|
if(!checkArgs(allArgs,##__VA_ARGS__)){ \
|
||||||
throw InvalidArgsException("缺少必要参数:" #__VA_ARGS__); \
|
throw InvalidArgsException("缺少必要参数:" #__VA_ARGS__); \
|
||||||
|
@ -157,17 +157,15 @@ bool MediaSource::seekTo(uint32_t stamp) {
|
|||||||
return listener->seekTo(*this, stamp);
|
return listener->seekTo(*this, stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaSource::pause()
|
bool MediaSource::pause(bool pause) {
|
||||||
{
|
|
||||||
auto listener = _listener.lock();
|
auto listener = _listener.lock();
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return listener->pause(*this);
|
return listener->pause(*this, pause);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaSource::speed(float speed)
|
bool MediaSource::speed(float speed) {
|
||||||
{
|
|
||||||
auto listener = _listener.lock();
|
auto listener = _listener.lock();
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
return false;
|
return false;
|
||||||
@ -601,17 +599,15 @@ bool MediaSourceEventInterceptor::seekTo(MediaSource &sender, uint32_t stamp) {
|
|||||||
return listener->seekTo(sender, stamp);
|
return listener->seekTo(sender, stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaSourceEventInterceptor::pause(MediaSource& sender)
|
bool MediaSourceEventInterceptor::pause(MediaSource &sender, bool pause) {
|
||||||
{
|
|
||||||
auto listener = _listener.lock();
|
auto listener = _listener.lock();
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return listener->pause(sender);
|
return listener->pause(sender, pause);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaSourceEventInterceptor::speed(MediaSource& sender, float speed)
|
bool MediaSourceEventInterceptor::speed(MediaSource &sender, float speed) {
|
||||||
{
|
|
||||||
auto listener = _listener.lock();
|
auto listener = _listener.lock();
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -67,10 +67,10 @@ public:
|
|||||||
|
|
||||||
// 通知拖动进度条
|
// 通知拖动进度条
|
||||||
virtual bool seekTo(MediaSource &sender, uint32_t stamp) { return false; }
|
virtual bool seekTo(MediaSource &sender, uint32_t stamp) { return false; }
|
||||||
// 通知暂停
|
// 通知暂停或恢复
|
||||||
virtual bool pause(MediaSource& sender) { return false; }
|
virtual bool pause(MediaSource &sender, bool pause) { return false; }
|
||||||
// 通知倍数
|
// 通知倍数
|
||||||
virtual bool speed(MediaSource& sender, float speed) { return false; }
|
virtual bool speed(MediaSource &sender, float speed) { return false; }
|
||||||
// 通知其停止产生流
|
// 通知其停止产生流
|
||||||
virtual bool close(MediaSource &sender, bool force) { return false; }
|
virtual bool close(MediaSource &sender, bool force) { return false; }
|
||||||
// 获取观看总人数
|
// 获取观看总人数
|
||||||
@ -110,8 +110,8 @@ public:
|
|||||||
std::shared_ptr<SockInfo> getOriginSock(MediaSource &sender) const override;
|
std::shared_ptr<SockInfo> getOriginSock(MediaSource &sender) const override;
|
||||||
|
|
||||||
bool seekTo(MediaSource &sender, uint32_t stamp) override;
|
bool seekTo(MediaSource &sender, uint32_t stamp) override;
|
||||||
bool pause(MediaSource& sender) override;
|
bool pause(MediaSource &sender, bool pause) override;
|
||||||
bool speed(MediaSource& sender, float speed) override;
|
bool speed(MediaSource &sender, float speed) override;
|
||||||
bool close(MediaSource &sender, bool force) override;
|
bool close(MediaSource &sender, bool force) override;
|
||||||
int totalReaderCount(MediaSource &sender) override;
|
int totalReaderCount(MediaSource &sender) override;
|
||||||
void onReaderChanged(MediaSource &sender, int size) override;
|
void onReaderChanged(MediaSource &sender, int size) override;
|
||||||
@ -256,8 +256,7 @@ public:
|
|||||||
// 拖动进度条
|
// 拖动进度条
|
||||||
bool seekTo(uint32_t stamp);
|
bool seekTo(uint32_t stamp);
|
||||||
//暂停
|
//暂停
|
||||||
bool pause();
|
bool pause(bool pause);
|
||||||
|
|
||||||
//倍数播放
|
//倍数播放
|
||||||
bool speed(float speed);
|
bool speed(float speed);
|
||||||
// 关闭该流
|
// 关闭该流
|
||||||
|
@ -33,11 +33,11 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onResponseBody(const char *buf, size_t size, size_t recvedSize, size_t totalSize) override;
|
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;
|
ssize_t onResponseHeader(const string &status, const HttpHeader &headers) override;
|
||||||
void onResponseCompleted() override;
|
void onResponseCompleted() override;
|
||||||
void onDisconnect(const SockException &ex) override;
|
void onDisconnect(const SockException &ex) override;
|
||||||
|
|
||||||
|
private:
|
||||||
void closeFile();
|
void closeFile();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -130,7 +130,7 @@ void HttpSession::onManager() {
|
|||||||
|
|
||||||
if(_ticker.elapsedTime() > keepAliveSec * 1000){
|
if(_ticker.elapsedTime() > keepAliveSec * 1000){
|
||||||
//1分钟超时
|
//1分钟超时
|
||||||
shutdown(SockException(Err_timeout,"session timeouted"));
|
shutdown(SockException(Err_timeout,"session timeout"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +64,7 @@ void MediaPlayer::pause(bool pause) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaPlayer::speed(float speed)
|
void MediaPlayer::speed(float speed) {
|
||||||
{
|
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
_delegate->speed(speed);
|
_delegate->speed(speed);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public:
|
|||||||
virtual ~MediaPlayer();
|
virtual ~MediaPlayer();
|
||||||
void play(const string &url) override;
|
void play(const string &url) override;
|
||||||
void pause(bool pause) override;
|
void pause(bool pause) override;
|
||||||
void speed(float speed)override;
|
void speed(float speed) override;
|
||||||
void teardown() override;
|
void teardown() override;
|
||||||
EventPoller::Ptr getPoller();
|
EventPoller::Ptr getPoller();
|
||||||
void setOnCreateSocket(Socket::onCreateSocket cb);
|
void setOnCreateSocket(Socket::onCreateSocket cb);
|
||||||
|
@ -102,7 +102,6 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取播放进度pos,取值 相对开始时间增量 单位秒
|
* 获取播放进度pos,取值 相对开始时间增量 单位秒
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
virtual uint32_t getProgressPos() const { return 0; }
|
virtual uint32_t getProgressPos() const { return 0; }
|
||||||
|
|
||||||
@ -152,15 +151,16 @@ public:
|
|||||||
typedef std::shared_ptr<PlayerImp> Ptr;
|
typedef std::shared_ptr<PlayerImp> Ptr;
|
||||||
|
|
||||||
template<typename ...ArgsType>
|
template<typename ...ArgsType>
|
||||||
PlayerImp(ArgsType &&...args):Parent(std::forward<ArgsType>(args)...){}
|
PlayerImp(ArgsType &&...args):Parent(std::forward<ArgsType>(args)...) {}
|
||||||
|
virtual ~PlayerImp() {}
|
||||||
|
|
||||||
virtual ~PlayerImp(){}
|
|
||||||
void setOnShutdown(const function<void(const SockException &)> &cb) override {
|
void setOnShutdown(const function<void(const SockException &)> &cb) override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
_delegate->setOnShutdown(cb);
|
_delegate->setOnShutdown(cb);
|
||||||
}
|
}
|
||||||
_shutdownCB = cb;
|
_shutdownCB = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
|
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
_delegate->setOnPlayResult(cb);
|
_delegate->setOnPlayResult(cb);
|
||||||
@ -175,31 +175,35 @@ public:
|
|||||||
_resumeCB = cb;
|
_resumeCB = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInited(int analysisMs) override{
|
bool isInited(int analysisMs) override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
return _delegate->isInited(analysisMs);
|
return _delegate->isInited(analysisMs);
|
||||||
}
|
}
|
||||||
return Parent::isInited(analysisMs);
|
return Parent::isInited(analysisMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
float getDuration() const override {
|
float getDuration() const override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
return _delegate->getDuration();
|
return _delegate->getDuration();
|
||||||
}
|
}
|
||||||
return Parent::getDuration();
|
return Parent::getDuration();
|
||||||
}
|
}
|
||||||
float getProgress() const override{
|
|
||||||
|
float getProgress() const override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
return _delegate->getProgress();
|
return _delegate->getProgress();
|
||||||
}
|
}
|
||||||
return Parent::getProgress();
|
return Parent::getProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getProgressPos() const override {
|
uint32_t getProgressPos() const override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
return _delegate->getProgressPos();
|
return _delegate->getProgressPos();
|
||||||
}
|
}
|
||||||
return Parent::getProgressPos();
|
return Parent::getProgressPos();
|
||||||
}
|
}
|
||||||
void seekTo(float fProgress) override{
|
|
||||||
|
void seekTo(float fProgress) override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
return _delegate->seekTo(fProgress);
|
return _delegate->seekTo(fProgress);
|
||||||
}
|
}
|
||||||
@ -213,21 +217,21 @@ public:
|
|||||||
return Parent::seekTo(seekPos);
|
return Parent::seekTo(seekPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMediaSource(const MediaSource::Ptr & src) override {
|
void setMediaSource(const MediaSource::Ptr &src) override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
_delegate->setMediaSource(src);
|
_delegate->setMediaSource(src);
|
||||||
}
|
}
|
||||||
_pMediaSrc = src;
|
_pMediaSrc = src;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Track::Ptr> getTracks(bool trackReady = true) const override{
|
vector<Track::Ptr> getTracks(bool trackReady = true) const override {
|
||||||
if (_delegate) {
|
if (_delegate) {
|
||||||
return _delegate->getTracks(trackReady);
|
return _delegate->getTracks(trackReady);
|
||||||
}
|
}
|
||||||
return Parent::getTracks(trackReady);
|
return Parent::getTracks(trackReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<SockInfo> getSockInfo() const{
|
std::shared_ptr<SockInfo> getSockInfo() const {
|
||||||
return dynamic_pointer_cast<SockInfo>(_delegate);
|
return dynamic_pointer_cast<SockInfo>(_delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,6 @@ void MP4Recorder::createFile() {
|
|||||||
}
|
}
|
||||||
_strFileTmp = strFileTmp;
|
_strFileTmp = strFileTmp;
|
||||||
_strFile = strFile;
|
_strFile = strFile;
|
||||||
_createFileTicker.resetTime();
|
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
WarnL << ex.what();
|
WarnL << ex.what();
|
||||||
}
|
}
|
||||||
@ -107,21 +106,21 @@ void MP4Recorder::closeFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MP4Recorder::inputFrame(const Frame::Ptr &frame) {
|
void MP4Recorder::inputFrame(const Frame::Ptr &frame) {
|
||||||
if (_baseSec == 0)
|
if (_baseSec == 0) {
|
||||||
_baseSec = frame->dts();
|
_baseSec = frame->dts();
|
||||||
auto dis = frame->dts() - _baseSec;
|
}
|
||||||
if(!_muxer || ((dis > _max_second * 1000) &&
|
|
||||||
(!_haveVideo || (_haveVideo && frame->keyFrame()))) ){
|
auto duration = frame->dts() - _baseSec;
|
||||||
|
if (!_muxer || ((duration > _max_second * 1000) && (!_haveVideo || (_haveVideo && frame->keyFrame())))) {
|
||||||
//成立条件
|
//成立条件
|
||||||
//1、_muxer为空
|
//1、_muxer为空
|
||||||
//2、到了切片时间,并且只有音频
|
//2、到了切片时间,并且只有音频
|
||||||
//3、到了切片时间,有视频并且遇到视频的关键帧
|
//3、到了切片时间,有视频并且遇到视频的关键帧
|
||||||
DebugL << "create file dts:" << frame->dts() << " baseSec:" << _baseSec;
|
|
||||||
_baseSec = 0;
|
_baseSec = 0;
|
||||||
createFile();
|
createFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_muxer){
|
if (_muxer) {
|
||||||
//生成mp4文件
|
//生成mp4文件
|
||||||
_muxer->inputFrame(frame);
|
_muxer->inputFrame(frame);
|
||||||
}
|
}
|
||||||
@ -139,7 +138,6 @@ void MP4Recorder::resetTracks() {
|
|||||||
closeFile();
|
closeFile();
|
||||||
_tracks.clear();
|
_tracks.clear();
|
||||||
_haveVideo = false;
|
_haveVideo = false;
|
||||||
_createFileTicker.resetTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace mediakit */
|
} /* namespace mediakit */
|
||||||
|
@ -61,11 +61,9 @@ private:
|
|||||||
string _strPath;
|
string _strPath;
|
||||||
string _strFile;
|
string _strFile;
|
||||||
string _strFileTmp;
|
string _strFileTmp;
|
||||||
Ticker _createFileTicker;
|
|
||||||
RecordInfo _info;
|
RecordInfo _info;
|
||||||
MP4Muxer::Ptr _muxer;
|
MP4Muxer::Ptr _muxer;
|
||||||
list<Track::Ptr> _tracks;
|
list<Track::Ptr> _tracks;
|
||||||
|
|
||||||
uint64_t _baseSec = 0;
|
uint64_t _baseSec = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,8 +171,7 @@ void RtmpPlayer::pause(bool bPause) {
|
|||||||
send_pause(bPause);
|
send_pause(bPause);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtmpPlayer::speed(float speed)
|
void RtmpPlayer::speed(float speed) {
|
||||||
{
|
|
||||||
//todo
|
//todo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
|
|
||||||
void play(const string &strUrl) override;
|
void play(const string &strUrl) override;
|
||||||
void pause(bool bPause) override;
|
void pause(bool bPause) override;
|
||||||
void speed(float speed)override;
|
void speed(float speed) override;
|
||||||
void teardown() override;
|
void teardown() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void seekTo(uint32_t seekPos) override {
|
void seekTo(uint32_t seekPos) override {
|
||||||
uint32_t pos = MAX(float(0), MIN(seekPos, getDuration()))*1000;
|
uint32_t pos = MAX(float(0), MIN(seekPos, getDuration())) * 1000;
|
||||||
seekToMilliSecond(pos);
|
seekToMilliSecond(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,23 +413,18 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
|
|||||||
sendUserControl(paused ? CONTROL_STREAM_EOF : CONTROL_STREAM_BEGIN, STREAM_MEDIA);
|
sendUserControl(paused ? CONTROL_STREAM_EOF : CONTROL_STREAM_BEGIN, STREAM_MEDIA);
|
||||||
_paused = paused;
|
_paused = paused;
|
||||||
|
|
||||||
auto stongSrc = _player_src.lock();
|
auto strongSrc = _player_src.lock();
|
||||||
if (stongSrc) {
|
if (strongSrc) {
|
||||||
if (_paused)
|
strongSrc->pause(paused);
|
||||||
stongSrc->pause();
|
|
||||||
else
|
|
||||||
stongSrc->seekTo(-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtmpSession::onCmd_playCtrl(AMFDecoder& dec)
|
void RtmpSession::onCmd_playCtrl(AMFDecoder &dec) {
|
||||||
{
|
|
||||||
dec.load<AMFValue>();
|
dec.load<AMFValue>();
|
||||||
auto ctrlObj = dec.load<AMFValue>();
|
auto ctrlObj = dec.load<AMFValue>();
|
||||||
int ctrlType = ctrlObj["ctrlType"].as_integer();
|
int ctrlType = ctrlObj["ctrlType"].as_integer();
|
||||||
float speed = ctrlObj["speed"].as_number();
|
float speed = ctrlObj["speed"].as_number();
|
||||||
|
|
||||||
|
|
||||||
AMFValue status(AMF_OBJECT);
|
AMFValue status(AMF_OBJECT);
|
||||||
status.set("level", "status");
|
status.set("level", "status");
|
||||||
status.set("code", "NetStream.Speed.Notify");
|
status.set("code", "NetStream.Speed.Notify");
|
||||||
|
@ -53,7 +53,7 @@ private:
|
|||||||
|
|
||||||
void onCmd_seek(AMFDecoder &dec);
|
void onCmd_seek(AMFDecoder &dec);
|
||||||
void onCmd_pause(AMFDecoder &dec);
|
void onCmd_pause(AMFDecoder &dec);
|
||||||
void onCmd_playCtrl(AMFDecoder& dec);
|
void onCmd_playCtrl(AMFDecoder &dec);
|
||||||
void setMetaData(AMFDecoder &dec);
|
void setMetaData(AMFDecoder &dec);
|
||||||
|
|
||||||
void onSendMedia(const RtmpPacket::Ptr &pkt);
|
void onSendMedia(const RtmpPacket::Ptr &pkt);
|
||||||
|
@ -419,9 +419,8 @@ void RtspPlayer::pause(bool bPause) {
|
|||||||
sendPause(bPause ? type_pause : type_seek, getProgressMilliSecond());
|
sendPause(bPause ? type_pause : type_seek, getProgressMilliSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspPlayer::speed(float speed)
|
void RtspPlayer::speed(float speed) {
|
||||||
{
|
sendRtspRequest("PLAY", _content_base, {"Scale", StrPrinter << speed});
|
||||||
sendRtspRequest("PLAY", _content_base, { "Scale",StrPrinter << speed });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspPlayer::handleResPAUSE(const Parser& parser,int type) {
|
void RtspPlayer::handleResPAUSE(const Parser& parser,int type) {
|
||||||
|
@ -41,8 +41,8 @@ public:
|
|||||||
~RtspPlayer() override;
|
~RtspPlayer() override;
|
||||||
|
|
||||||
void play(const string &strUrl) override;
|
void play(const string &strUrl) override;
|
||||||
void pause(bool bPause) override;
|
void pause(bool pause) override;
|
||||||
void speed(float speed)override;
|
void speed(float speed) override;
|
||||||
void teardown() override;
|
void teardown() override;
|
||||||
float getPacketLossRate(TrackType type) const override;
|
float getPacketLossRate(TrackType type) const override;
|
||||||
|
|
||||||
|
@ -47,12 +47,11 @@ public:
|
|||||||
return getProgressMilliSecond();
|
return getProgressMilliSecond();
|
||||||
}
|
}
|
||||||
return PlayerBase::getProgressPos();
|
return PlayerBase::getProgressPos();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
void seekTo(float fProgress) override {
|
||||||
|
fProgress = MAX(float(0), MIN(fProgress, float(1.0)));
|
||||||
void seekTo(float fProgress) override{
|
seekToMilliSecond((uint32_t) (fProgress * getDuration() * 1000));
|
||||||
fProgress = MAX(float(0),MIN(fProgress,float(1.0)));
|
|
||||||
seekToMilliSecond((uint32_t)(fProgress * getDuration() * 1000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void seekTo(uint32_t seekPos) override {
|
void seekTo(uint32_t seekPos) override {
|
||||||
|
@ -101,13 +101,13 @@ void RtspSession::onManager() {
|
|||||||
|
|
||||||
if (_push_src && _alive_ticker.elapsedTime() > keep_alive_sec * 1000) {
|
if (_push_src && _alive_ticker.elapsedTime() > keep_alive_sec * 1000) {
|
||||||
//推流超时
|
//推流超时
|
||||||
shutdown(SockException(Err_timeout, "pusher session timeouted"));
|
shutdown(SockException(Err_timeout, "pusher session timeout"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_push_src && _rtp_type == Rtsp::RTP_UDP && _enable_send_rtp && _alive_ticker.elapsedTime() > keep_alive_sec * 4000) {
|
if (!_push_src && _rtp_type == Rtsp::RTP_UDP && _enable_send_rtp && _alive_ticker.elapsedTime() > keep_alive_sec * 4000) {
|
||||||
//rtp over udp播放器超时
|
//rtp over udp播放器超时
|
||||||
shutdown(SockException(Err_timeout, "rtp over udp player timeouted"));
|
shutdown(SockException(Err_timeout, "rtp over udp player timeout"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,36 +774,27 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool useGOP = true;
|
bool useGOP = true;
|
||||||
//_enable_send_rtp = false;
|
|
||||||
float iStartTime = 0;
|
float iStartTime = 0;
|
||||||
auto strRange = parser["Range"];
|
auto &strRange = parser["Range"];
|
||||||
auto strScale = parser["Scale"];
|
auto &strScale = parser["Scale"];
|
||||||
if (strScale.size() == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (strRange.size()) {
|
if (!strScale.empty()) {
|
||||||
//这个是seek操作
|
//这是设置播放速度
|
||||||
auto strStart = FindField(strRange.data(), "npt=", "-");
|
auto speed = atof(strScale.data());
|
||||||
if (strStart == "now") {
|
play_src->speed(speed);
|
||||||
strStart = "0";
|
InfoP(this) << "rtp set play speed:" << speed;
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
if (!strRange.empty()) {
|
||||||
play_src->speed(atof(strScale.data()));
|
//这是seek操作
|
||||||
|
_enable_send_rtp = false;
|
||||||
|
auto strStart = FindField(strRange.data(), "npt=", "-");
|
||||||
|
if (strStart == "now") {
|
||||||
|
strStart = "0";
|
||||||
|
}
|
||||||
|
iStartTime = 1000 * (float) atof(strStart.data());
|
||||||
|
useGOP = !play_src->seekTo((uint32_t) iStartTime);
|
||||||
|
InfoP(this) << "rtsp seekTo(ms):" << iStartTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
_StrPrinter rtp_info;
|
_StrPrinter rtp_info;
|
||||||
@ -828,7 +819,10 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
|||||||
"RTP-Info",rtp_info
|
"RTP-Info",rtp_info
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//在回复rtsp信令后再恢复播放
|
||||||
_enable_send_rtp = true;
|
_enable_send_rtp = true;
|
||||||
|
play_src->pause(false);
|
||||||
|
|
||||||
setSocketFlags();
|
setSocketFlags();
|
||||||
|
|
||||||
if (!_play_reader && _rtp_type != Rtsp::RTP_MULTICAST) {
|
if (!_play_reader && _rtp_type != Rtsp::RTP_MULTICAST) {
|
||||||
@ -856,26 +850,21 @@ void RtspSession::handleReq_Play(const Parser &parser) {
|
|||||||
void RtspSession::handleReq_Pause(const Parser &parser) {
|
void RtspSession::handleReq_Pause(const Parser &parser) {
|
||||||
if (parser["Session"] != _sessionid) {
|
if (parser["Session"] != _sessionid) {
|
||||||
send_SessionNotFound();
|
send_SessionNotFound();
|
||||||
throw SockException(Err_shutdown,"session not found when pause");
|
throw SockException(Err_shutdown, "session not found when pause");
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRtspResponse("200 OK");
|
sendRtspResponse("200 OK");
|
||||||
|
_enable_send_rtp = false;
|
||||||
|
|
||||||
auto play_src = _play_src.lock();
|
auto play_src = _play_src.lock();
|
||||||
if (!play_src) {
|
if (play_src) {
|
||||||
send_StreamNotFound();
|
play_src->pause(true);
|
||||||
shutdown(SockException(Err_shutdown, "rtsp stream released"));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
play_src->pause();
|
|
||||||
//_enable_send_rtp = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspSession::handleReq_Teardown(const Parser &parser) {
|
void RtspSession::handleReq_Teardown(const Parser &parser) {
|
||||||
sendRtspResponse("200 OK");
|
sendRtspResponse("200 OK");
|
||||||
throw SockException(Err_shutdown,"rtsp player send teardown request");
|
throw SockException(Err_shutdown,"recv teardown request");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspSession::handleReq_Get(const Parser &parser) {
|
void RtspSession::handleReq_Get(const Parser &parser) {
|
||||||
|
Loading…
Reference in New Issue
Block a user