mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-23 03:10:04 +08:00
同步代码
This commit is contained in:
commit
ea53da64ca
@ -1 +1 @@
|
|||||||
Subproject commit 065b75623da5f9bb5916cecd853936a6670d71c5
|
Subproject commit 1126175e2aabd811ba906e9699b43caf5837179d
|
@ -13,6 +13,7 @@ android {
|
|||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
cmake {
|
cmake {
|
||||||
cppFlags "-std=c++11 -frtti -fexceptions"
|
cppFlags "-std=c++11 -frtti -fexceptions"
|
||||||
|
arguments "-DENABLE_API=off", "-DENABLE_TESTS=off", "-DENABLE_PLAYER=off", "-DENABLE_SERVER_LIB=on"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ndk {
|
ndk {
|
||||||
|
@ -6,106 +6,33 @@ set(CMAKE_CXX_STANDARD 11)
|
|||||||
#设置生成的so动态库最后输出的路径
|
#设置生成的so动态库最后输出的路径
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libs_export/${ANDROID_ABI})
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libs_export/${ANDROID_ABI})
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libs_export/${ANDROID_ABI})
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libs_export/${ANDROID_ABI})
|
||||||
|
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/libs_export/${ANDROID_ABI}/binary)
|
||||||
LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH})
|
set(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${ANDROID_ABI}")
|
||||||
|
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
|
||||||
|
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/libcrypto.a")
|
||||||
|
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/libssl.a")
|
||||||
|
|
||||||
#设置工程源码根目录
|
#设置工程源码根目录
|
||||||
set(ZLMediaKit_Root ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../)
|
|
||||||
set(JNI_Root ${CMAKE_CURRENT_SOURCE_DIR})
|
set(JNI_Root ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
set(ToolKit_Root ${ZLMediaKit_Root}/3rdpart/ZLToolKit/src)
|
set(ZLMediaKit_Root ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../)
|
||||||
set(MediaKit_Root ${ZLMediaKit_Root}/src)
|
|
||||||
set(MediaServer_Root ${ZLMediaKit_Root}/3rdpart/media-server/)
|
|
||||||
|
|
||||||
#设置头文件目录
|
#添加主工程cmake
|
||||||
INCLUDE_DIRECTORIES(${ToolKit_Root})
|
add_subdirectory(${ZLMediaKit_Root} ${EXECUTABLE_OUTPUT_PATH})
|
||||||
INCLUDE_DIRECTORIES(${MediaKit_Root})
|
|
||||||
INCLUDE_DIRECTORIES(${JNI_Root})
|
|
||||||
|
|
||||||
#收集源代码
|
#设置include
|
||||||
file(GLOB ToolKit_src_list ${ToolKit_Root}/*/*.cpp ${ToolKit_Root}/*/*.h ${ToolKit_Root}/*/*.c)
|
include_directories(${JNI_Root})
|
||||||
file(GLOB MediaKit_src_list ${MediaKit_Root}/*/*.cpp ${MediaKit_Root}/*/*.h ${MediaKit_Root}/*/*.c)
|
include_directories(${ZLMediaKit_Root}/src)
|
||||||
|
include_directories(${ZLMediaKit_Root}/srt)
|
||||||
|
include_directories(${ZLMediaKit_Root}/webrtc)
|
||||||
|
include_directories(${ZLMediaKit_Root}/server)
|
||||||
|
include_directories(${ZLMediaKit_Root}/3rdpart)
|
||||||
|
include_directories(${ZLMediaKit_Root}/3rdpart/media-server)
|
||||||
|
include_directories(${ZLMediaKit_Root}/3rdpart/ZLToolKit/src)
|
||||||
|
|
||||||
|
#收集源代码添加动态库
|
||||||
file(GLOB JNI_src_list ${JNI_Root}/*.cpp ${JNI_Root}/*.h)
|
file(GLOB JNI_src_list ${JNI_Root}/*.cpp ${JNI_Root}/*.h)
|
||||||
|
|
||||||
#去除win32的适配代码
|
|
||||||
if (NOT WIN32)
|
|
||||||
list(REMOVE_ITEM ToolKit_src_list ${ToolKit_Root}/win32/getopt.c)
|
|
||||||
else()
|
|
||||||
#防止Windows.h包含Winsock.h
|
|
||||||
add_definitions(-DWIN32_LEAN_AND_MEAN -DMP4V2_NO_STDINT_DEFS)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(ENABLE_HLS true)
|
|
||||||
set(ENABLE_OPENSSL true)
|
|
||||||
set(ENABLE_MYSQL false)
|
|
||||||
set(ENABLE_FAAC false)
|
|
||||||
set(ENABLE_X264 false)
|
|
||||||
set(ENABLE_MP4 true)
|
|
||||||
|
|
||||||
#添加两个静态库
|
|
||||||
if(ENABLE_HLS)
|
|
||||||
message(STATUS "ENABLE_HLS defined")
|
|
||||||
add_definitions(-DENABLE_HLS)
|
|
||||||
set(LINK_LIB_LIST zlmediakit zltoolkit mpeg)
|
|
||||||
else()
|
|
||||||
set(LINK_LIB_LIST zlmediakit zltoolkit)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if(ENABLE_MP4)
|
|
||||||
message(STATUS "ENABLE_MP4 defined")
|
|
||||||
add_definitions(-DENABLE_MP4)
|
|
||||||
list(APPEND LINK_LIB_LIST mov flv)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ENABLE_OPENSSL)
|
|
||||||
#openssl
|
|
||||||
add_definitions(-DENABLE_OPENSSL)
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI}/include)
|
|
||||||
LINK_DIRECTORIES(${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI}/)
|
|
||||||
list(APPEND LINK_LIB_LIST ssl crypto)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
#libmpeg
|
|
||||||
if(ENABLE_HLS)
|
|
||||||
aux_source_directory(${MediaServer_Root}/libmpeg/include src_mpeg)
|
|
||||||
aux_source_directory(${MediaServer_Root}/libmpeg/source src_mpeg)
|
|
||||||
include_directories(${MediaServer_Root}/libmpeg/include)
|
|
||||||
add_library(mpeg STATIC ${src_mpeg})
|
|
||||||
if(MSVC)
|
|
||||||
set_target_properties(mpeg PROPERTIES COMPILE_FLAGS ${VS_FALGS} )
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ENABLE_MP4)
|
|
||||||
aux_source_directory(${MediaServer_Root}/libmov/include src_mov)
|
|
||||||
aux_source_directory(${MediaServer_Root}/libmov/source src_mov)
|
|
||||||
include_directories(${MediaServer_Root}/libmov/include)
|
|
||||||
aux_source_directory(${MediaServer_Root}/libflv/include src_flv)
|
|
||||||
aux_source_directory(${MediaServer_Root}/libflv/source src_flv)
|
|
||||||
include_directories(${MediaServer_Root}/libflv/include)
|
|
||||||
add_library(mov STATIC ${src_mov})
|
|
||||||
add_library(flv STATIC ${src_flv})
|
|
||||||
if(MSVC)
|
|
||||||
set_target_properties(mov flv PROPERTIES COMPILE_FLAGS ${VS_FALGS} )
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
#添加库
|
|
||||||
add_library(zltoolkit STATIC ${ToolKit_src_list})
|
|
||||||
add_library(zlmediakit STATIC ${MediaKit_src_list})
|
|
||||||
add_library(zlmediakit_jni SHARED ${JNI_src_list})
|
add_library(zlmediakit_jni SHARED ${JNI_src_list})
|
||||||
|
|
||||||
add_definitions(-DDISABLE_MAIN)
|
|
||||||
#添加json以及MediaServer相关代码
|
|
||||||
include_directories(${ZLMediaKit_Root}/3rdpart)
|
|
||||||
include_directories(${ZLMediaKit_Root}/server)
|
|
||||||
file(GLOB jsoncpp_src_list ${ZLMediaKit_Root}/3rdpart/jsoncpp/*.cpp)
|
|
||||||
file(GLOB MediaServer_src_list ${ZLMediaKit_Root}/server/*.cpp)
|
|
||||||
add_library(jsoncpp STATIC ${jsoncpp_src_list})
|
|
||||||
add_library(MediaServer STATIC ${MediaServer_src_list})
|
|
||||||
|
|
||||||
#链接
|
#链接
|
||||||
target_link_libraries(zlmediakit_jni MediaServer jsoncpp ${LINK_LIB_LIST} log z)
|
target_link_libraries(zlmediakit_jni -Wl,--start-group log z ${LINK_LIB_LIST} -Wl,--end-group)
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,92 +15,94 @@
|
|||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
#include "Player/MediaPlayer.h"
|
#include "Player/MediaPlayer.h"
|
||||||
#include "Extension/Frame.h"
|
#include "Extension/Frame.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
using namespace mediakit;
|
using namespace mediakit;
|
||||||
|
|
||||||
#define JNI_API(retType,funName,...) extern "C" JNIEXPORT retType Java_com_zlmediakit_jni_ZLMediaKit_##funName(JNIEnv* env, jclass cls,##__VA_ARGS__)
|
#define JNI_API(retType, funName, ...) extern "C" JNIEXPORT retType Java_com_zlmediakit_jni_ZLMediaKit_##funName(JNIEnv* env, jclass cls,##__VA_ARGS__)
|
||||||
#define MediaPlayerCallBackSign "com/zlmediakit/jni/ZLMediaKit$MediaPlayerCallBack"
|
#define MediaPlayerCallBackSign "com/zlmediakit/jni/ZLMediaKit$MediaPlayerCallBack"
|
||||||
#define MediaFrameSign "com/zlmediakit/jni/ZLMediaKit$MediaFrame"
|
#define MediaFrameSign "com/zlmediakit/jni/ZLMediaKit$MediaFrame"
|
||||||
|
|
||||||
|
string stringFromJstring(JNIEnv *env, jstring jstr) {
|
||||||
string stringFromJstring(JNIEnv *env,jstring jstr){
|
if (!env || !jstr) {
|
||||||
if(!env || !jstr){
|
|
||||||
WarnL << "invalid args";
|
WarnL << "invalid args";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
const char *field_char = env->GetStringUTFChars(jstr, 0);
|
const char *field_char = env->GetStringUTFChars(jstr, 0);
|
||||||
string ret(field_char,env->GetStringUTFLength(jstr));
|
string ret(field_char, env->GetStringUTFLength(jstr));
|
||||||
env->ReleaseStringUTFChars(jstr, field_char);
|
env->ReleaseStringUTFChars(jstr, field_char);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
string stringFromJbytes(JNIEnv *env,jbyteArray jbytes){
|
|
||||||
if(!env || !jbytes){
|
string stringFromJbytes(JNIEnv *env, jbyteArray jbytes) {
|
||||||
|
if (!env || !jbytes) {
|
||||||
WarnL << "invalid args";
|
WarnL << "invalid args";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
jbyte *bytes = env->GetByteArrayElements(jbytes, 0);
|
jbyte *bytes = env->GetByteArrayElements(jbytes, 0);
|
||||||
string ret((char *)bytes,env->GetArrayLength(jbytes));
|
string ret((char *) bytes, env->GetArrayLength(jbytes));
|
||||||
env->ReleaseByteArrayElements(jbytes,bytes,0);
|
env->ReleaseByteArrayElements(jbytes, bytes, 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
string stringFieldFromJava(JNIEnv *env, jobject jdata,jfieldID jid){
|
|
||||||
if(!env || !jdata || !jid){
|
string stringFieldFromJava(JNIEnv *env, jobject jdata, jfieldID jid) {
|
||||||
|
if (!env || !jdata || !jid) {
|
||||||
WarnL << "invalid args";
|
WarnL << "invalid args";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
jstring field_str = (jstring)env->GetObjectField(jdata,jid);
|
jstring field_str = (jstring) env->GetObjectField(jdata, jid);
|
||||||
auto ret = stringFromJstring(env,field_str);
|
auto ret = stringFromJstring(env, field_str);
|
||||||
env->DeleteLocalRef(field_str);
|
env->DeleteLocalRef(field_str);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
string bytesFieldFromJava(JNIEnv *env, jobject jdata,jfieldID jid){
|
string bytesFieldFromJava(JNIEnv *env, jobject jdata, jfieldID jid) {
|
||||||
if(!env || !jdata || !jid){
|
if (!env || !jdata || !jid) {
|
||||||
WarnL << "invalid args";
|
WarnL << "invalid args";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
jbyteArray jbufArray = (jbyteArray)env->GetObjectField(jdata, jid);
|
jbyteArray jbufArray = (jbyteArray) env->GetObjectField(jdata, jid);
|
||||||
string ret = stringFromJbytes(env,jbufArray);
|
string ret = stringFromJbytes(env, jbufArray);
|
||||||
env->DeleteLocalRef(jbufArray);
|
env->DeleteLocalRef(jbufArray);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring jstringFromString(JNIEnv* env, const char* pat) {
|
jstring jstringFromString(JNIEnv *env, const char *pat) {
|
||||||
return (jstring)env->NewStringUTF(pat);
|
return (jstring) env->NewStringUTF(pat);
|
||||||
}
|
}
|
||||||
|
|
||||||
jbyteArray jbyteArrayFromString(JNIEnv* env, const char* pat,int len = 0){
|
jbyteArray jbyteArrayFromString(JNIEnv *env, const char *pat, int len = 0) {
|
||||||
if(len <= 0){
|
if (len <= 0) {
|
||||||
len = strlen(pat);
|
len = strlen(pat);
|
||||||
}
|
}
|
||||||
jbyteArray jarray = env->NewByteArray(len);
|
jbyteArray jarray = env->NewByteArray(len);
|
||||||
env->SetByteArrayRegion(jarray, 0, len, (jbyte *)(pat));
|
env->SetByteArrayRegion(jarray, 0, len, (jbyte * )(pat));
|
||||||
return jarray;
|
return jarray;
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject makeJavaFrame(JNIEnv* env,const Frame::Ptr &frame){
|
jobject makeJavaFrame(JNIEnv *env, const Frame::Ptr &frame) {
|
||||||
static jclass jclass_obj = (jclass)env->NewGlobalRef(env->FindClass(MediaFrameSign));
|
static jclass jclass_obj = (jclass) env->NewGlobalRef(env->FindClass(MediaFrameSign));
|
||||||
static jmethodID jmethodID_init = env->GetMethodID(jclass_obj, "<init>", "()V");
|
static jmethodID jmethodID_init = env->GetMethodID(jclass_obj, "<init>", "()V");
|
||||||
static jfieldID jfieldID_dts = env->GetFieldID(jclass_obj,"dts","I");
|
static jfieldID jfieldID_dts = env->GetFieldID(jclass_obj, "dts", "I");
|
||||||
static jfieldID jfieldID_pts = env->GetFieldID(jclass_obj,"pts","I");
|
static jfieldID jfieldID_pts = env->GetFieldID(jclass_obj, "pts", "I");
|
||||||
static jfieldID jfieldID_prefixSize = env->GetFieldID(jclass_obj,"prefixSize","I");
|
static jfieldID jfieldID_prefixSize = env->GetFieldID(jclass_obj, "prefixSize", "I");
|
||||||
static jfieldID jfieldID_keyFrame = env->GetFieldID(jclass_obj,"keyFrame","Z");
|
static jfieldID jfieldID_keyFrame = env->GetFieldID(jclass_obj, "keyFrame", "Z");
|
||||||
static jfieldID jfieldID_data = env->GetFieldID(jclass_obj,"data","[B");
|
static jfieldID jfieldID_data = env->GetFieldID(jclass_obj, "data", "[B");
|
||||||
static jfieldID jfieldID_trackType = env->GetFieldID(jclass_obj,"trackType","I");
|
static jfieldID jfieldID_trackType = env->GetFieldID(jclass_obj, "trackType", "I");
|
||||||
static jfieldID jfieldID_codecId = env->GetFieldID(jclass_obj,"codecId","I");
|
static jfieldID jfieldID_codecId = env->GetFieldID(jclass_obj, "codecId", "I");
|
||||||
|
|
||||||
if(!frame){
|
if (!frame) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
jobject ret = env->NewObject(jclass_obj, jmethodID_init);
|
jobject ret = env->NewObject(jclass_obj, jmethodID_init);
|
||||||
env->SetIntField(ret,jfieldID_dts,frame->dts());
|
env->SetIntField(ret, jfieldID_dts, frame->dts());
|
||||||
env->SetIntField(ret,jfieldID_pts,frame->pts());
|
env->SetIntField(ret, jfieldID_pts, frame->pts());
|
||||||
env->SetIntField(ret,jfieldID_prefixSize,frame->prefixSize());
|
env->SetIntField(ret, jfieldID_prefixSize, frame->prefixSize());
|
||||||
env->SetBooleanField(ret,jfieldID_keyFrame,frame->keyFrame());
|
env->SetBooleanField(ret, jfieldID_keyFrame, frame->keyFrame());
|
||||||
env->SetObjectField(ret,jfieldID_data,jbyteArrayFromString(env,frame->data(),frame->size()));
|
env->SetObjectField(ret, jfieldID_data, jbyteArrayFromString(env, frame->data(), frame->size()));
|
||||||
env->SetIntField(ret,jfieldID_trackType,frame->getTrackType());
|
env->SetIntField(ret, jfieldID_trackType, frame->getTrackType());
|
||||||
env->SetIntField(ret,jfieldID_codecId,frame->getCodecId());
|
env->SetIntField(ret, jfieldID_codecId, frame->getCodecId());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +162,8 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved){
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern int start_main(int argc,char *argv[]);
|
extern int start_main(int argc,char *argv[]);
|
||||||
JNI_API(jboolean,startDemo,jstring ini_dir){
|
|
||||||
|
JNI_API(jboolean, startDemo, jstring ini_dir){
|
||||||
string sd_path = stringFromJstring(env,ini_dir);
|
string sd_path = stringFromJstring(env,ini_dir);
|
||||||
string ini_file = sd_path + "/zlmediakit.ini";
|
string ini_file = sd_path + "/zlmediakit.ini";
|
||||||
|
|
||||||
@ -185,9 +188,9 @@ JNI_API(jboolean,startDemo,jstring ini_dir){
|
|||||||
mINI::Instance()["rtsp.port"] = 8554;
|
mINI::Instance()["rtsp.port"] = 8554;
|
||||||
mINI::Instance()["rtsp.sslport"] = 8332;
|
mINI::Instance()["rtsp.sslport"] = 8332;
|
||||||
mINI::Instance()["general.enableVhost"] = 0;
|
mINI::Instance()["general.enableVhost"] = 0;
|
||||||
for(auto &pr : mINI::Instance()){
|
for (auto &pr : mINI::Instance()) {
|
||||||
//替换hook默认地址
|
//替换hook默认地址
|
||||||
replace(pr.second,"https://127.0.0.1/","http://127.0.0.1:8080/");
|
replace(pr.second, "https://127.0.0.1/", "http://127.0.0.1:8080/");
|
||||||
}
|
}
|
||||||
//默认打开hook
|
//默认打开hook
|
||||||
mINI::Instance()["hook.enable"] = 0;
|
mINI::Instance()["hook.enable"] = 0;
|
||||||
@ -195,10 +198,9 @@ JNI_API(jboolean,startDemo,jstring ini_dir){
|
|||||||
mINI::Instance()["api.apiDebug"] = 1;
|
mINI::Instance()["api.apiDebug"] = 1;
|
||||||
|
|
||||||
int argc = 5;
|
int argc = 5;
|
||||||
const char *argv[] = {"","-c",ini_file.data(),"-s",pem_file.data()};
|
const char *argv[] = {"", "-c", ini_file.data(), "-s", pem_file.data()};
|
||||||
|
start_main(argc, (char **) argv);
|
||||||
start_main(argc,(char **)argv);
|
} catch (std::exception &ex) {
|
||||||
}catch (std::exception &ex){
|
|
||||||
WarnL << ex.what();
|
WarnL << ex.what();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -210,7 +212,7 @@ JNI_API(jboolean,startDemo,jstring ini_dir){
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
JNI_API(jlong,createMediaPlayer,jstring url,jobject callback){
|
JNI_API(jlong, createMediaPlayer, jstring url, jobject callback){
|
||||||
static auto loadFrameClass = makeJavaFrame(env,nullptr);
|
static auto loadFrameClass = makeJavaFrame(env,nullptr);
|
||||||
MediaPlayer::Ptr *ret = new MediaPlayer::Ptr(new MediaPlayer());
|
MediaPlayer::Ptr *ret = new MediaPlayer::Ptr(new MediaPlayer());
|
||||||
MediaPlayer::Ptr &player = *ret;
|
MediaPlayer::Ptr &player = *ret;
|
||||||
@ -260,8 +262,6 @@ JNI_API(jlong,createMediaPlayer,jstring url,jobject callback){
|
|||||||
return (jlong)(ret);
|
return (jlong)(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
JNI_API(void,releaseMediaPlayer,jlong ptr){
|
JNI_API(void,releaseMediaPlayer,jlong ptr){
|
||||||
MediaPlayer::Ptr *player = (MediaPlayer::Ptr *)ptr;
|
MediaPlayer::Ptr *player = (MediaPlayer::Ptr *)ptr;
|
||||||
delete player;
|
delete player;
|
||||||
|
@ -98,11 +98,12 @@ option(ENABLE_API "Enable C API SDK" true)
|
|||||||
option(ENABLE_CXX_API "Enable C++ API SDK" false)
|
option(ENABLE_CXX_API "Enable C++ API SDK" false)
|
||||||
option(ENABLE_TESTS "Enable Tests" true)
|
option(ENABLE_TESTS "Enable Tests" true)
|
||||||
option(ENABLE_SERVER "Enable Server" true)
|
option(ENABLE_SERVER "Enable Server" true)
|
||||||
|
option(ENABLE_SERVER_LIB "Enable server as android static library" false)
|
||||||
option(ENABLE_MEM_DEBUG "Enable Memory Debug" false)
|
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" true)
|
option(ENABLE_WEBRTC "Enable WebRTC" true)
|
||||||
option(ENABLE_PLAYER "Enable Player" true)
|
option(ENABLE_PLAYER "Enable Player" true)
|
||||||
option(ENABLE_FFMPEG "Enable FFmpeg" true)
|
option(ENABLE_FFMPEG "Enable FFmpeg" false)
|
||||||
option(ENABLE_MSVC_MT "Enable MSVC Mt/Mtd lib" true)
|
option(ENABLE_MSVC_MT "Enable MSVC Mt/Mtd lib" true)
|
||||||
option(ENABLE_API_STATIC_LIB "Enable mk_api static lib" false)
|
option(ENABLE_API_STATIC_LIB "Enable mk_api static lib" false)
|
||||||
option(USE_SOLUTION_FOLDERS "Enable solution dir supported" ON)
|
option(USE_SOLUTION_FOLDERS "Enable solution dir supported" ON)
|
||||||
@ -307,7 +308,7 @@ if (JEMALLOC_FOUND)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
#查找openssl是否安装
|
#查找openssl是否安装
|
||||||
find_package(OpenSSL QUIET)
|
find_package(OPENSSL QUIET)
|
||||||
if (OPENSSL_FOUND AND ENABLE_OPENSSL)
|
if (OPENSSL_FOUND AND ENABLE_OPENSSL)
|
||||||
message(STATUS "found library:${OPENSSL_LIBRARIES},ENABLE_OPENSSL defined")
|
message(STATUS "found library:${OPENSSL_LIBRARIES},ENABLE_OPENSSL defined")
|
||||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||||
@ -521,3 +522,7 @@ endif ()
|
|||||||
if (ENABLE_PLAYER)
|
if (ENABLE_PLAYER)
|
||||||
add_subdirectory(player)
|
add_subdirectory(player)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (ENABLE_SERVER_LIB)
|
||||||
|
set(LINK_LIB_LIST ${LINK_LIB_LIST} PARENT_SCOPE)
|
||||||
|
endif ()
|
||||||
|
@ -157,6 +157,10 @@ on_server_keepalive=https://127.0.0.1/index/hook/on_server_keepalive
|
|||||||
timeoutSec=10
|
timeoutSec=10
|
||||||
#keepalive hook触发间隔,单位秒,float类型
|
#keepalive hook触发间隔,单位秒,float类型
|
||||||
alive_interval=10.0
|
alive_interval=10.0
|
||||||
|
#hook通知失败重试次数,正整数。为0不重试,1时重试一次,以此类推
|
||||||
|
retry=1
|
||||||
|
#hook通知失败重试延时,单位秒,float型
|
||||||
|
retry_delay=3.0
|
||||||
|
|
||||||
[cluster]
|
[cluster]
|
||||||
#设置源站拉流url模板, 格式跟printf类似,第一个%s指定app,第二个%s指定stream_id,
|
#设置源站拉流url模板, 格式跟printf类似,第一个%s指定app,第二个%s指定stream_id,
|
||||||
@ -200,10 +204,13 @@ dirMenu=1
|
|||||||
#访问 http://127.0.0.1/app_b/file_b 对应的文件路径为 /path/to/b/file_b
|
#访问 http://127.0.0.1/app_b/file_b 对应的文件路径为 /path/to/b/file_b
|
||||||
#访问其他http路径,对应的文件路径还是在rootPath内
|
#访问其他http路径,对应的文件路径还是在rootPath内
|
||||||
virtualPath=
|
virtualPath=
|
||||||
#禁止后缀的文件缓存,使用“,”隔开
|
#禁止后缀的文件使用mmap缓存,使用“,”隔开
|
||||||
#例如赋值为 .mp4,.flv
|
#例如赋值为 .mp4,.flv
|
||||||
#那么访问后缀为.mp4与.flv 的文件不缓存
|
#那么访问后缀为.mp4与.flv 的文件不缓存
|
||||||
forbidCacheSuffix=
|
forbidCacheSuffix=
|
||||||
|
#可以把http代理前真实客户端ip放在http头中:https://github.com/ZLMediaKit/ZLMediaKit/issues/1388
|
||||||
|
#切勿暴露此key,否则可能导致伪造客户端ip
|
||||||
|
forwarded_ip_header=
|
||||||
|
|
||||||
[multicast]
|
[multicast]
|
||||||
#rtp组播截止组播ip地址
|
#rtp组播截止组播ip地址
|
||||||
|
@ -3,6 +3,14 @@ file(GLOB jsoncpp_src_list ../3rdpart/jsoncpp/*.cpp ../3rdpart/jsoncpp/*.h )
|
|||||||
add_library(jsoncpp STATIC ${jsoncpp_src_list})
|
add_library(jsoncpp STATIC ${jsoncpp_src_list})
|
||||||
file(GLOB MediaServer_src_list ./*.cpp ./*.h)
|
file(GLOB MediaServer_src_list ./*.cpp ./*.h)
|
||||||
|
|
||||||
|
if (ENABLE_SERVER_LIB)
|
||||||
|
add_definitions(-DDISABLE_MAIN)
|
||||||
|
add_library(MediaServer STATIC ${MediaServer_src_list})
|
||||||
|
list(APPEND LINK_LIB_LIST MediaServer jsoncpp)
|
||||||
|
set(LINK_LIB_LIST ${LINK_LIB_LIST} PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_executable(MediaServer ${MediaServer_src_list})
|
add_executable(MediaServer ${MediaServer_src_list})
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
@ -47,6 +47,8 @@ const string kOnServerStarted = HOOK_FIELD"on_server_started";
|
|||||||
const string kOnServerKeepalive = HOOK_FIELD"on_server_keepalive";
|
const string kOnServerKeepalive = HOOK_FIELD"on_server_keepalive";
|
||||||
const string kAdminParams = HOOK_FIELD"admin_params";
|
const string kAdminParams = HOOK_FIELD"admin_params";
|
||||||
const string kAliveInterval = HOOK_FIELD"alive_interval";
|
const string kAliveInterval = HOOK_FIELD"alive_interval";
|
||||||
|
const string kRetry = HOOK_FIELD"retry";
|
||||||
|
const string kRetryDelay = HOOK_FIELD"retry_delay";
|
||||||
|
|
||||||
onceToken token([](){
|
onceToken token([](){
|
||||||
mINI::Instance()[kEnable] = false;
|
mINI::Instance()[kEnable] = false;
|
||||||
@ -68,6 +70,8 @@ onceToken token([](){
|
|||||||
mINI::Instance()[kOnServerKeepalive] = "";
|
mINI::Instance()[kOnServerKeepalive] = "";
|
||||||
mINI::Instance()[kAdminParams] = "secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc";
|
mINI::Instance()[kAdminParams] = "secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc";
|
||||||
mINI::Instance()[kAliveInterval] = 30.0;
|
mINI::Instance()[kAliveInterval] = 30.0;
|
||||||
|
mINI::Instance()[kRetry] = 1;
|
||||||
|
mINI::Instance()[kRetryDelay] = 3.0;
|
||||||
},nullptr);
|
},nullptr);
|
||||||
}//namespace Hook
|
}//namespace Hook
|
||||||
|
|
||||||
@ -147,9 +151,10 @@ string getVhost(const HttpArgs &value) {
|
|||||||
return val != value.end() ? val->second : "";
|
return val != value.end() ? val->second : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_http_hook(const string &url,const ArgsType &body,const function<void(const Value &,const string &)> &func){
|
void do_http_hook(const string &url, const ArgsType &body, const function<void(const Value &, const string &)> &func, uint32_t retry) {
|
||||||
GET_CONFIG(string, mediaServerId, General::kMediaServerId);
|
GET_CONFIG(string, mediaServerId, General::kMediaServerId);
|
||||||
GET_CONFIG(float, hook_timeoutSec, Hook::kTimeoutSec);
|
GET_CONFIG(float, hook_timeoutSec, Hook::kTimeoutSec);
|
||||||
|
GET_CONFIG(float, retry_delay, Hook::kRetryDelay);
|
||||||
|
|
||||||
const_cast<ArgsType &>(body)["mediaServerId"] = mediaServerId;
|
const_cast<ArgsType &>(body)["mediaServerId"] = mediaServerId;
|
||||||
HttpRequester::Ptr requester(new HttpRequester);
|
HttpRequester::Ptr requester(new HttpRequester);
|
||||||
@ -161,25 +166,40 @@ void do_http_hook(const string &url,const ArgsType &body,const function<void(con
|
|||||||
if (!vhost.empty()) {
|
if (!vhost.empty()) {
|
||||||
requester->addHeader("X-VHOST", vhost);
|
requester->addHeader("X-VHOST", vhost);
|
||||||
}
|
}
|
||||||
std::shared_ptr<Ticker> pTicker(new Ticker);
|
Ticker ticker;
|
||||||
requester->startRequester(url, [url, func, bodyStr, requester, pTicker](const SockException &ex,
|
requester->startRequester(url, [url, func, bodyStr, body, requester, ticker, retry](const SockException &ex, const Parser &res) mutable {
|
||||||
const Parser &res) mutable{
|
onceToken token(nullptr, [&]() mutable { requester.reset(); });
|
||||||
onceToken token(nullptr, [&]() mutable{
|
parse_http_response(ex, res, [&](const Value &obj, const string &err) {
|
||||||
requester.reset();
|
if (!err.empty()) {
|
||||||
});
|
// hook失败
|
||||||
parse_http_response(ex, res, [&](const Value &obj, const string &err) {
|
WarnL << "hook " << url << " " << ticker.elapsedTime() << "ms,failed" << err << ":" << bodyStr;
|
||||||
|
|
||||||
|
if (retry-- > 0) {
|
||||||
|
requester->getPoller()->doDelayTask(MAX(retry_delay, 0.0) * 1000, [url, body, func, retry] {
|
||||||
|
do_http_hook(url, body, func, retry);
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
//重试不需要触发回调
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (ticker.elapsedTime() > 500) {
|
||||||
|
//hook成功,但是hook响应超过500ms,打印警告日志
|
||||||
|
DebugL << "hook " << url << " " << ticker.elapsedTime() << "ms,success:" << bodyStr;
|
||||||
|
}
|
||||||
|
|
||||||
if (func) {
|
if (func) {
|
||||||
func(obj, err);
|
func(obj, err);
|
||||||
}
|
}
|
||||||
if (!err.empty()) {
|
|
||||||
WarnL << "hook " << url << " " << pTicker->elapsedTime() << "ms,failed" << err << ":" << bodyStr;
|
|
||||||
} else if (pTicker->elapsedTime() > 500) {
|
|
||||||
DebugL << "hook " << url << " " << pTicker->elapsedTime() << "ms,success:" << bodyStr;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, hook_timeoutSec);
|
}, hook_timeoutSec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_http_hook(const string &url, const ArgsType &body, const function<void(const Value &, const string &)> &func) {
|
||||||
|
GET_CONFIG(uint32_t, hook_retry, Hook::kRetry);
|
||||||
|
do_http_hook(url, body, func, hook_retry);
|
||||||
|
}
|
||||||
|
|
||||||
static ArgsType make_json(const MediaInfo &args){
|
static ArgsType make_json(const MediaInfo &args){
|
||||||
ArgsType body;
|
ArgsType body;
|
||||||
body["schema"] = args._schema;
|
body["schema"] = args._schema;
|
||||||
|
@ -233,10 +233,17 @@ toolkit::EventPoller::Ptr MediaSource::getOwnerPoller() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MediaSource::onReaderChanged(int size) {
|
void MediaSource::onReaderChanged(int size) {
|
||||||
auto listener = _listener.lock();
|
weak_ptr<MediaSource> weak_self = shared_from_this();
|
||||||
if (listener) {
|
getOwnerPoller()->async([weak_self, size]() {
|
||||||
listener->onReaderChanged(*this, size);
|
auto strong_self = weak_self.lock();
|
||||||
}
|
if (!strong_self) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto listener = strong_self->_listener.lock();
|
||||||
|
if (listener) {
|
||||||
|
listener->onReaderChanged(*strong_self, size);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaSource::setupRecord(Recorder::type type, bool start, const string &custom_path, size_t max_second){
|
bool MediaSource::setupRecord(Recorder::type type, bool start, const string &custom_path, size_t max_second){
|
||||||
@ -581,7 +588,7 @@ MediaSource::Ptr MediaSource::createFromMP4(const string &schema, const string &
|
|||||||
/////////////////////////////////////MediaSourceEvent//////////////////////////////////////
|
/////////////////////////////////////MediaSourceEvent//////////////////////////////////////
|
||||||
|
|
||||||
void MediaSourceEvent::onReaderChanged(MediaSource &sender, int size){
|
void MediaSourceEvent::onReaderChanged(MediaSource &sender, int size){
|
||||||
if (size) {
|
if (size || totalReaderCount(sender)) {
|
||||||
//还有人观看该视频,不触发关闭事件
|
//还有人观看该视频,不触发关闭事件
|
||||||
_async_close_timer = nullptr;
|
_async_close_timer = nullptr;
|
||||||
return;
|
return;
|
||||||
@ -618,7 +625,7 @@ void MediaSourceEvent::onReaderChanged(MediaSource &sender, int size){
|
|||||||
strong_sender->close(false);
|
strong_sender->close(false);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}, getOwnerPoller(sender));
|
}, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
string MediaSourceEvent::getOriginUrl(MediaSource &sender) const {
|
string MediaSourceEvent::getOriginUrl(MediaSource &sender) const {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "Stamp.h"
|
#include "Stamp.h"
|
||||||
|
|
||||||
//时间戳最大允许跳变30秒,主要是防止网络抖动导致的跳变
|
//时间戳最大允许跳变30秒,主要是防止网络抖动导致的跳变
|
||||||
#define MAX_DELTA_STAMP (30 * 1000)
|
#define MAX_DELTA_STAMP (3 * 1000)
|
||||||
#define STAMP_LOOP_DELTA (60 * 1000)
|
#define STAMP_LOOP_DELTA (60 * 1000)
|
||||||
#define MAX_CTS 500
|
#define MAX_CTS 500
|
||||||
#define ABS(x) ((x) > 0 ? (x) : (-x))
|
#define ABS(x) ((x) > 0 ? (x) : (-x))
|
||||||
|
@ -124,6 +124,7 @@ const string kVirtualPath = HTTP_FIELD "virtualPath";
|
|||||||
const string kNotFound = HTTP_FIELD "notFound";
|
const string kNotFound = HTTP_FIELD "notFound";
|
||||||
const string kDirMenu = HTTP_FIELD "dirMenu";
|
const string kDirMenu = HTTP_FIELD "dirMenu";
|
||||||
const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix";
|
const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix";
|
||||||
|
const string kForwardedIpHeader = HTTP_FIELD "forwarded_ip_header";
|
||||||
|
|
||||||
static onceToken token([]() {
|
static onceToken token([]() {
|
||||||
mINI::Instance()[kSendBufSize] = 64 * 1024;
|
mINI::Instance()[kSendBufSize] = 64 * 1024;
|
||||||
@ -150,6 +151,7 @@ static onceToken token([]() {
|
|||||||
"</html>"
|
"</html>"
|
||||||
<< endl;
|
<< endl;
|
||||||
mINI::Instance()[kForbidCacheSuffix] = "";
|
mINI::Instance()[kForbidCacheSuffix] = "";
|
||||||
|
mINI::Instance()[kForwardedIpHeader] = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
} // namespace Http
|
} // namespace Http
|
||||||
|
@ -223,6 +223,8 @@ extern const std::string kNotFound;
|
|||||||
extern const std::string kDirMenu;
|
extern const std::string kDirMenu;
|
||||||
// 禁止缓存文件的后缀
|
// 禁止缓存文件的后缀
|
||||||
extern const std::string kForbidCacheSuffix;
|
extern const std::string kForbidCacheSuffix;
|
||||||
|
// 可以把http代理前真实客户端ip放在http头中:https://github.com/ZLMediaKit/ZLMediaKit/issues/1388
|
||||||
|
extern const std::string kForwardedIpHeader;
|
||||||
} // namespace Http
|
} // namespace Http
|
||||||
|
|
||||||
////////////SHELL配置///////////
|
////////////SHELL配置///////////
|
||||||
|
@ -29,26 +29,6 @@ void HttpCookie::setHost(const string &host) {
|
|||||||
_host = host;
|
_host = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long s_gmtoff = 0; //时间差
|
|
||||||
static onceToken s_token([]() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
TIME_ZONE_INFORMATION tzinfo;
|
|
||||||
DWORD dwStandardDaylight;
|
|
||||||
long bias;
|
|
||||||
dwStandardDaylight = GetTimeZoneInformation(&tzinfo);
|
|
||||||
bias = tzinfo.Bias;
|
|
||||||
if (dwStandardDaylight == TIME_ZONE_ID_STANDARD) {
|
|
||||||
bias += tzinfo.StandardBias;
|
|
||||||
}
|
|
||||||
if (dwStandardDaylight == TIME_ZONE_ID_DAYLIGHT) {
|
|
||||||
bias += tzinfo.DaylightBias;
|
|
||||||
}
|
|
||||||
s_gmtoff = -bias * 60; //时间差(分钟)
|
|
||||||
#else
|
|
||||||
s_gmtoff = getLocalTime(time(nullptr)).tm_gmtoff;
|
|
||||||
#endif // _WIN32
|
|
||||||
});
|
|
||||||
|
|
||||||
// from https://gmbabar.wordpress.com/2010/12/01/mktime-slow-use-custom-function/#comment-58
|
// from https://gmbabar.wordpress.com/2010/12/01/mktime-slow-use-custom-function/#comment-58
|
||||||
static time_t time_to_epoch(const struct tm *ltm, int utcdiff) {
|
static time_t time_to_epoch(const struct tm *ltm, int utcdiff) {
|
||||||
const int mon_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
const int mon_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
@ -74,7 +54,7 @@ static time_t timeStrToInt(const string &date) {
|
|||||||
struct tm tt;
|
struct tm tt;
|
||||||
strptime(date.data(), "%a, %b %d %Y %H:%M:%S %Z", &tt);
|
strptime(date.data(), "%a, %b %d %Y %H:%M:%S %Z", &tt);
|
||||||
// mktime内部有使用互斥锁,非常影响性能
|
// mktime内部有使用互斥锁,非常影响性能
|
||||||
return time_to_epoch(&tt, s_gmtoff / 3600); // mktime(&tt);
|
return time_to_epoch(&tt, getGMTOff() / 3600); // mktime(&tt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpCookie::setExpires(const string &expires, const string &server_date) {
|
void HttpCookie::setExpires(const string &expires, const string &server_date) {
|
||||||
|
@ -465,6 +465,12 @@ static string getFilePath(const Parser &parser,const MediaInfo &media_info, TcpS
|
|||||||
path = rootPath;
|
path = rootPath;
|
||||||
url = parser.Url();
|
url = parser.Url();
|
||||||
}
|
}
|
||||||
|
for (auto &ch : url) {
|
||||||
|
if (ch == '\\') {
|
||||||
|
//如果url中存在"\",这种目录是Windows样式的;需要批量转换为标准的"/"; 防止访问目录权限外的文件
|
||||||
|
ch = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
auto ret = File::absolutePath(enableVhost ? media_info._vhost + url : url, path);
|
auto ret = File::absolutePath(enableVhost ? media_info._vhost + url : url, path);
|
||||||
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpBeforeAccess, parser, ret, static_cast<SockInfo &>(sender));
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpBeforeAccess, parser, ret, static_cast<SockInfo &>(sender));
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -670,6 +670,11 @@ bool HttpSession::emitHttpEvent(bool doInvoke){
|
|||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string HttpSession::get_peer_ip() {
|
||||||
|
GET_CONFIG(string, forwarded_ip_header, Http::kForwardedIpHeader);
|
||||||
|
return forwarded_ip_header.empty() ? TcpSession::get_peer_ip() : _parser.getHeader()[forwarded_ip_header];
|
||||||
|
}
|
||||||
|
|
||||||
void HttpSession::Handle_Req_POST(ssize_t &content_len) {
|
void HttpSession::Handle_Req_POST(ssize_t &content_len) {
|
||||||
GET_CONFIG(size_t,maxReqSize,Http::kMaxReqSize);
|
GET_CONFIG(size_t,maxReqSize,Http::kMaxReqSize);
|
||||||
|
|
||||||
|
@ -97,6 +97,9 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void onWebSocketDecodeComplete(const WebSocketHeader &header_in) override;
|
void onWebSocketDecodeComplete(const WebSocketHeader &header_in) override;
|
||||||
|
|
||||||
|
//重载获取客户端ip
|
||||||
|
std::string get_peer_ip() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Handle_Req_GET(ssize_t &content_len);
|
void Handle_Req_GET(ssize_t &content_len);
|
||||||
void Handle_Req_GET_l(ssize_t &content_len, bool sendBody);
|
void Handle_Req_GET_l(ssize_t &content_len, bool sendBody);
|
||||||
|
@ -119,7 +119,7 @@ bool RtpProcess::inputFrame(const Frame::Ptr &frame) {
|
|||||||
return _muxer->inputFrame(frame);
|
return _muxer->inputFrame(frame);
|
||||||
}
|
}
|
||||||
if (_cached_func.size() > kMaxCachedFrame) {
|
if (_cached_func.size() > kMaxCachedFrame) {
|
||||||
WarnL << "cached frame of track(" << frame->getCodecName() << ") is too much, now dropped";
|
WarnL << "cached frame of track(" << frame->getCodecName() << ") is too much, now dropped, please check your on_publish hook url in config.ini file";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto frame_cached = Frame::getCacheAbleFrame(frame);
|
auto frame_cached = Frame::getCacheAbleFrame(frame);
|
||||||
@ -278,7 +278,7 @@ std::shared_ptr<SockInfo> RtpProcess::getOriginSock(MediaSource &sender) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toolkit::EventPoller::Ptr RtpProcess::getOwnerPoller(MediaSource &sender) {
|
toolkit::EventPoller::Ptr RtpProcess::getOwnerPoller(MediaSource &sender) {
|
||||||
return _sock ? _sock->getPoller() : MediaSourceEventInterceptor::getOwnerPoller(sender);
|
return _sock ? _sock->getPoller() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
@ -491,9 +491,15 @@ void RtspPlayer::onRtpPacket(const char *data, size_t len) {
|
|||||||
uint8_t interleaved = data[1];
|
uint8_t interleaved = data[1];
|
||||||
if(interleaved %2 == 0){
|
if(interleaved %2 == 0){
|
||||||
trackIdx = getTrackIndexByInterleaved(interleaved);
|
trackIdx = getTrackIndexByInterleaved(interleaved);
|
||||||
|
if (trackIdx == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
handleOneRtp(trackIdx, _sdp_track[trackIdx]->_type, _sdp_track[trackIdx]->_samplerate, (uint8_t *)data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
|
handleOneRtp(trackIdx, _sdp_track[trackIdx]->_type, _sdp_track[trackIdx]->_samplerate, (uint8_t *)data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
|
||||||
}else{
|
}else{
|
||||||
trackIdx = getTrackIndexByInterleaved(interleaved - 1);
|
trackIdx = getTrackIndexByInterleaved(interleaved - 1);
|
||||||
|
if (trackIdx == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
onRtcpPacket(trackIdx, _sdp_track[trackIdx], (uint8_t *) data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
|
onRtcpPacket(trackIdx, _sdp_track[trackIdx], (uint8_t *) data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -711,7 +717,8 @@ int RtspPlayer::getTrackIndexByInterleaved(int interleaved) const {
|
|||||||
if (_sdp_track.size() == 1) {
|
if (_sdp_track.size() == 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
throw SockException(Err_shutdown, StrPrinter << "no such track with interleaved:" << interleaved);
|
WarnL << "no such track with interleaved:" << interleaved;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspPlayer::getTrackIndexByTrackType(TrackType track_type) const {
|
int RtspPlayer::getTrackIndexByTrackType(TrackType track_type) const {
|
||||||
|
@ -237,11 +237,16 @@ std::string PacketQueue::dump() {
|
|||||||
|
|
||||||
//////////////////// PacketRecvQueue //////////////////////////////////
|
//////////////////// PacketRecvQueue //////////////////////////////////
|
||||||
|
|
||||||
PacketRecvQueue::PacketRecvQueue(uint32_t max_size, uint32_t init_seq, uint32_t latency)
|
PacketRecvQueue::PacketRecvQueue(uint32_t max_size, uint32_t init_seq, uint32_t latency,uint32_t flag)
|
||||||
: _pkt_cap(max_size)
|
: _pkt_cap(max_size)
|
||||||
, _pkt_latency(latency)
|
, _pkt_latency(latency)
|
||||||
, _pkt_expected_seq(init_seq)
|
, _pkt_expected_seq(init_seq)
|
||||||
, _pkt_buf(max_size) {}
|
, _pkt_buf(max_size)
|
||||||
|
, _srt_flag(flag) {}
|
||||||
|
|
||||||
|
bool PacketRecvQueue::TLPKTDrop(){
|
||||||
|
return (_srt_flag&HSExtMessage::HS_EXT_MSG_TLPKTDROP) && (_srt_flag &HSExtMessage::HS_EXT_MSG_TSBPDRCV);
|
||||||
|
}
|
||||||
bool PacketRecvQueue::inputPacket(DataPacket::Ptr pkt, std::list<DataPacket::Ptr> &out) {
|
bool PacketRecvQueue::inputPacket(DataPacket::Ptr pkt, std::list<DataPacket::Ptr> &out) {
|
||||||
// TraceL << dump() << " seq:" << pkt->packet_seq_number;
|
// TraceL << dump() << " seq:" << pkt->packet_seq_number;
|
||||||
while (_size > 0 && _start == _end) {
|
while (_size > 0 && _start == _end) {
|
||||||
@ -265,7 +270,7 @@ bool PacketRecvQueue::inputPacket(DataPacket::Ptr pkt, std::list<DataPacket::Ptr
|
|||||||
_start = (_start + 1) % _pkt_cap;
|
_start = (_start + 1) % _pkt_cap;
|
||||||
it = _pkt_buf[_start];
|
it = _pkt_buf[_start];
|
||||||
}
|
}
|
||||||
while (timeLatency() > _pkt_latency) {
|
while (timeLatency() > _pkt_latency && TLPKTDrop()) {
|
||||||
it = _pkt_buf[_start];
|
it = _pkt_buf[_start];
|
||||||
if (it) {
|
if (it) {
|
||||||
_pkt_buf[_start] = nullptr;
|
_pkt_buf[_start] = nullptr;
|
||||||
|
@ -65,7 +65,7 @@ class PacketRecvQueue : public PacketQueueInterface {
|
|||||||
public:
|
public:
|
||||||
using Ptr = std::shared_ptr<PacketRecvQueue>;
|
using Ptr = std::shared_ptr<PacketRecvQueue>;
|
||||||
|
|
||||||
PacketRecvQueue(uint32_t max_size, uint32_t init_seq, uint32_t latency);
|
PacketRecvQueue(uint32_t max_size, uint32_t init_seq, uint32_t latency,uint32_t flag = 0xbf);
|
||||||
~PacketRecvQueue() = default;
|
~PacketRecvQueue() = default;
|
||||||
bool inputPacket(DataPacket::Ptr pkt, std::list<DataPacket::Ptr> &out);
|
bool inputPacket(DataPacket::Ptr pkt, std::list<DataPacket::Ptr> &out);
|
||||||
|
|
||||||
@ -85,12 +85,15 @@ private:
|
|||||||
void insertToCycleBuf(DataPacket::Ptr pkt, uint32_t diff);
|
void insertToCycleBuf(DataPacket::Ptr pkt, uint32_t diff);
|
||||||
DataPacket::Ptr getFirst();
|
DataPacket::Ptr getFirst();
|
||||||
DataPacket::Ptr getLast();
|
DataPacket::Ptr getLast();
|
||||||
|
bool TLPKTDrop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t _pkt_cap;
|
uint32_t _pkt_cap;
|
||||||
uint32_t _pkt_latency;
|
uint32_t _pkt_latency;
|
||||||
uint32_t _pkt_expected_seq;
|
uint32_t _pkt_expected_seq;
|
||||||
|
|
||||||
|
uint32_t _srt_flag;
|
||||||
|
|
||||||
std::vector<DataPacket::Ptr> _pkt_buf;
|
std::vector<DataPacket::Ptr> _pkt_buf;
|
||||||
uint32_t _start = 0;
|
uint32_t _start = 0;
|
||||||
uint32_t _end = 0;
|
uint32_t _end = 0;
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
namespace SRT {
|
namespace SRT {
|
||||||
|
|
||||||
PacketSendQueue::PacketSendQueue(uint32_t max_size, uint32_t latency)
|
PacketSendQueue::PacketSendQueue(uint32_t max_size, uint32_t latency,uint32_t flag)
|
||||||
: _pkt_cap(max_size)
|
: _pkt_cap(max_size)
|
||||||
, _pkt_latency(latency) {}
|
, _pkt_latency(latency)
|
||||||
|
, _srt_flag(flag) {}
|
||||||
|
|
||||||
bool PacketSendQueue::drop(uint32_t num) {
|
bool PacketSendQueue::drop(uint32_t num) {
|
||||||
decltype(_pkt_cache.begin()) it;
|
decltype(_pkt_cache.begin()) it;
|
||||||
@ -24,12 +25,16 @@ bool PacketSendQueue::inputPacket(DataPacket::Ptr pkt) {
|
|||||||
while (_pkt_cache.size() > _pkt_cap) {
|
while (_pkt_cache.size() > _pkt_cap) {
|
||||||
_pkt_cache.pop_front();
|
_pkt_cache.pop_front();
|
||||||
}
|
}
|
||||||
while (timeLatency() > _pkt_latency) {
|
while (timeLatency() > _pkt_latency && TLPKTDrop()) {
|
||||||
_pkt_cache.pop_front();
|
_pkt_cache.pop_front();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PacketSendQueue::TLPKTDrop(){
|
||||||
|
return (_srt_flag&HSExtMessage::HS_EXT_MSG_TLPKTDROP) && (_srt_flag &HSExtMessage::HS_EXT_MSG_TSBPDSND);
|
||||||
|
}
|
||||||
|
|
||||||
std::list<DataPacket::Ptr> PacketSendQueue::findPacketBySeq(uint32_t start, uint32_t end) {
|
std::list<DataPacket::Ptr> PacketSendQueue::findPacketBySeq(uint32_t start, uint32_t end) {
|
||||||
std::list<DataPacket::Ptr> re;
|
std::list<DataPacket::Ptr> re;
|
||||||
decltype(_pkt_cache.begin()) it;
|
decltype(_pkt_cache.begin()) it;
|
||||||
|
@ -16,7 +16,7 @@ public:
|
|||||||
using Ptr = std::shared_ptr<PacketSendQueue>;
|
using Ptr = std::shared_ptr<PacketSendQueue>;
|
||||||
using LostPair = std::pair<uint32_t, uint32_t>;
|
using LostPair = std::pair<uint32_t, uint32_t>;
|
||||||
|
|
||||||
PacketSendQueue(uint32_t max_size, uint32_t latency);
|
PacketSendQueue(uint32_t max_size, uint32_t latency,uint32_t flag = 0xbf);
|
||||||
~PacketSendQueue() = default;
|
~PacketSendQueue() = default;
|
||||||
|
|
||||||
bool drop(uint32_t num);
|
bool drop(uint32_t num);
|
||||||
@ -25,7 +25,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t timeLatency();
|
uint32_t timeLatency();
|
||||||
|
bool TLPKTDrop();
|
||||||
private:
|
private:
|
||||||
|
uint32_t _srt_flag;
|
||||||
uint32_t _pkt_cap;
|
uint32_t _pkt_cap;
|
||||||
uint32_t _pkt_latency;
|
uint32_t _pkt_latency;
|
||||||
std::list<DataPacket::Ptr> _pkt_cache;
|
std::list<DataPacket::Ptr> _pkt_cache;
|
||||||
|
@ -182,9 +182,9 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad
|
|||||||
}
|
}
|
||||||
if (req) {
|
if (req) {
|
||||||
if (req->srt_flag != srt_flag) {
|
if (req->srt_flag != srt_flag) {
|
||||||
WarnL << " not support flag " << req->srt_flag;
|
WarnL << " flag " << req->srt_flag;
|
||||||
}
|
}
|
||||||
// srt_flag = req->srt_flag;
|
srt_flag = req->srt_flag;
|
||||||
delay = delay <= req->recv_tsbpd_delay ? req->recv_tsbpd_delay : delay;
|
delay = delay <= req->recv_tsbpd_delay ? req->recv_tsbpd_delay : delay;
|
||||||
}
|
}
|
||||||
TraceL << getIdentifier() << " CONCLUSION Phase ";
|
TraceL << getIdentifier() << " CONCLUSION Phase ";
|
||||||
@ -214,8 +214,8 @@ void SrtTransport::handleHandshakeConclusion(HandshakePacket &pkt, struct sockad
|
|||||||
sendControlPacket(res, true);
|
sendControlPacket(res, true);
|
||||||
TraceL << " buf size = " << res->max_flow_window_size << " init seq =" << _init_seq_number
|
TraceL << " buf size = " << res->max_flow_window_size << " init seq =" << _init_seq_number
|
||||||
<< " latency=" << delay;
|
<< " latency=" << delay;
|
||||||
_recv_buf = std::make_shared<PacketRecvQueue>(getPktBufSize(), _init_seq_number, delay * 1e3);
|
_recv_buf = std::make_shared<PacketRecvQueue>(getPktBufSize(), _init_seq_number, delay * 1e3,srt_flag);
|
||||||
_send_buf = std::make_shared<PacketSendQueue>(getPktBufSize(), delay * 1e3);
|
_send_buf = std::make_shared<PacketSendQueue>(getPktBufSize(), delay * 1e3,srt_flag);
|
||||||
_send_packet_seq_number = _init_seq_number;
|
_send_packet_seq_number = _init_seq_number;
|
||||||
_buf_delay = delay;
|
_buf_delay = delay;
|
||||||
onHandShakeFinished(_stream_id, addr);
|
onHandShakeFinished(_stream_id, addr);
|
||||||
@ -413,6 +413,7 @@ void SrtTransport::sendACKPacket() {
|
|||||||
_last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number;
|
_last_ack_pkt_seq_num = pkt->last_ack_pkt_seq_number;
|
||||||
sendControlPacket(pkt, true);
|
sendControlPacket(pkt, true);
|
||||||
// TraceL<<"send ack "<<pkt->dump();
|
// TraceL<<"send ack "<<pkt->dump();
|
||||||
|
// TraceL<<_recv_buf->dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrtTransport::sendLightACKPacket() {
|
void SrtTransport::sendLightACKPacket() {
|
||||||
|
@ -38,6 +38,7 @@ static bool loadFile(const char *path){
|
|||||||
uint16_t len;
|
uint16_t len;
|
||||||
char rtp[0xFFFF];
|
char rtp[0xFFFF];
|
||||||
struct sockaddr_storage addr = {0};
|
struct sockaddr_storage addr = {0};
|
||||||
|
addr.ss_family = AF_INET;
|
||||||
auto sock = Socket::createSocket();
|
auto sock = Socket::createSocket();
|
||||||
size_t total_size = 0;
|
size_t total_size = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#ifdef ENABLE_SCTP
|
#ifdef ENABLE_SCTP
|
||||||
|
|
||||||
#define MS_CLASS "RTC::SctpAssociation"
|
#define MS_CLASS "RTC::SctpAssociation"
|
||||||
// #define MS_LOG_DEV_LEVEL 3
|
// #define MS_LOG_DEV_LEVEL 3
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#ifndef MS_RTC_SCTP_ASSOCIATION_HPP
|
#ifndef MS_RTC_SCTP_ASSOCIATION_HPP
|
||||||
#define MS_RTC_SCTP_ASSOCIATION_HPP
|
#define MS_RTC_SCTP_ASSOCIATION_HPP
|
||||||
|
|
||||||
#ifdef ENABLE_SCTP
|
#ifdef ENABLE_SCTP
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
#define MS_TRACE()
|
#define MS_TRACE()
|
||||||
#define MS_ERROR PrintE
|
#define MS_ERROR PrintE
|
||||||
#define MS_THROW_ERROR(...) do { PrintE(__VA_ARGS__); throw std::runtime_error("error"); } while(false)
|
#define MS_THROW_ERROR(...) do { PrintE(__VA_ARGS__); throw std::runtime_error("MS_THROW_ERROR"); } while(false)
|
||||||
#define MS_DUMP PrintT
|
#define MS_DUMP PrintT
|
||||||
#define MS_DEBUG_2TAGS(tag1, tag2, ...) PrintD(__VA_ARGS__)
|
#define MS_DEBUG_2TAGS(tag1, tag2, ...) PrintD(__VA_ARGS__)
|
||||||
#define MS_WARN_2TAGS(tag1, tag2, ...) PrintW(__VA_ARGS__)
|
#define MS_WARN_2TAGS(tag1, tag2, ...) PrintW(__VA_ARGS__)
|
||||||
#define MS_DEBUG_TAG(tag, ...) PrintD(__VA_ARGS__)
|
#define MS_DEBUG_TAG(tag, ...) PrintD(__VA_ARGS__)
|
||||||
#define MS_ASSERT(con, ...) do { if(!(con)) { PrintE(__VA_ARGS__); abort(); } } while(false)
|
#define MS_ASSERT(con, ...) do { if(!(con)) { PrintE(__VA_ARGS__); std::runtime_error("MS_ASSERT"); } } while(false)
|
||||||
#define MS_ABORT(...) do { PrintE(__VA_ARGS__); abort(); } while(false)
|
#define MS_ABORT(...) do { PrintE(__VA_ARGS__); abort(); } while(false)
|
||||||
#define MS_WARN_TAG(tag, ...) PrintW(__VA_ARGS__)
|
#define MS_WARN_TAG(tag, ...) PrintW(__VA_ARGS__)
|
||||||
#define MS_DEBUG_DEV PrintD
|
#define MS_DEBUG_DEV PrintD
|
Loading…
Reference in New Issue
Block a user