Commit 1168174c by xiongziliang

tab统一替换为4个空格键:#242

parent 2a0d78fd
ZLToolKit @ d985d49f
Subproject commit 34b42499ce9ee055b5c7cac9a270239984d0e839 Subproject commit d985d49f28b441216bf50020b7c6587edb5f43dc
...@@ -31,12 +31,12 @@ ...@@ -31,12 +31,12 @@
#if defined(_WIN32) #if defined(_WIN32)
#if defined(MediaKitApi_EXPORTS) #if defined(MediaKitApi_EXPORTS)
#define API_EXPORT __declspec(dllexport) #define API_EXPORT __declspec(dllexport)
#else #else
#define API_EXPORT __declspec(dllimport) #define API_EXPORT __declspec(dllimport)
#endif #endif
#define API_CALL __cdecl #define API_CALL __cdecl
#else #else
#define API_EXPORT #define API_EXPORT
#define API_CALL #define API_CALL
......
...@@ -32,41 +32,41 @@ using namespace toolkit; ...@@ -32,41 +32,41 @@ using namespace toolkit;
using namespace mediakit; using namespace mediakit;
API_EXPORT mk_player API_CALL mk_player_create() { API_EXPORT mk_player API_CALL mk_player_create() {
MediaPlayer::Ptr *obj = new MediaPlayer::Ptr(new MediaPlayer()); MediaPlayer::Ptr *obj = new MediaPlayer::Ptr(new MediaPlayer());
return obj; return obj;
} }
API_EXPORT void API_CALL mk_player_release(mk_player ctx) { API_EXPORT void API_CALL mk_player_release(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr *obj = (MediaPlayer::Ptr *)ctx; MediaPlayer::Ptr *obj = (MediaPlayer::Ptr *)ctx;
delete obj; delete obj;
} }
API_EXPORT void API_CALL mk_player_set_option(mk_player ctx,const char* key,const char *val){ API_EXPORT void API_CALL mk_player_set_option(mk_player ctx,const char* key,const char *val){
assert(ctx && key && val); assert(ctx && key && val);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
string key_str(key), val_str(val); string key_str(key), val_str(val);
player->getPoller()->async([key_str,val_str,player](){ player->getPoller()->async([key_str,val_str,player](){
//切换线程后再操作 //切换线程后再操作
(*player)[key_str] = val_str; (*player)[key_str] = val_str;
}); });
} }
API_EXPORT void API_CALL mk_player_play(mk_player ctx, const char *url) { API_EXPORT void API_CALL mk_player_play(mk_player ctx, const char *url) {
assert(ctx && url); assert(ctx && url);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
string url_str(url); string url_str(url);
player->getPoller()->async([url_str,player](){ player->getPoller()->async([url_str,player](){
//切换线程后再操作 //切换线程后再操作
player->play(url_str); player->play(url_str);
}); });
} }
API_EXPORT void API_CALL mk_player_pause(mk_player ctx, int pause) { API_EXPORT void API_CALL mk_player_pause(mk_player ctx, int pause) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
player->getPoller()->async([pause,player](){ player->getPoller()->async([pause,player](){
//切换线程后再操作 //切换线程后再操作
player->pause(pause); player->pause(pause);
}); });
} }
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) {
...@@ -79,100 +79,100 @@ API_EXPORT void API_CALL mk_player_seekto(mk_player ctx, float progress) { ...@@ -79,100 +79,100 @@ API_EXPORT void API_CALL mk_player_seekto(mk_player ctx, float progress) {
} }
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) {
assert(ctx && cb); assert(ctx && cb);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
player->getPoller()->async([cb,user_data,type,player](){ player->getPoller()->async([cb,user_data,type,player](){
//切换线程后再操作 //切换线程后再操作
if(type == 0){ if(type == 0){
player->setOnPlayResult([cb,user_data](const SockException &ex){ player->setOnPlayResult([cb,user_data](const SockException &ex){
cb(user_data,ex.getErrCode(),ex.what()); cb(user_data,ex.getErrCode(),ex.what());
}); });
}else{ }else{
player->setOnShutdown([cb,user_data](const SockException &ex){ player->setOnShutdown([cb,user_data](const SockException &ex){
cb(user_data,ex.getErrCode(),ex.what()); cb(user_data,ex.getErrCode(),ex.what());
}); });
} }
}); });
} }
API_EXPORT void API_CALL mk_player_set_on_result(mk_player ctx, on_mk_play_event cb, void *user_data) { API_EXPORT void API_CALL mk_player_set_on_result(mk_player ctx, on_mk_play_event cb, void *user_data) {
mk_player_set_on_event(ctx,cb,user_data,0); mk_player_set_on_event(ctx,cb,user_data,0);
} }
API_EXPORT void API_CALL mk_player_set_on_shutdown(mk_player ctx, on_mk_play_event cb, void *user_data) { API_EXPORT void API_CALL mk_player_set_on_shutdown(mk_player ctx, on_mk_play_event cb, void *user_data) {
mk_player_set_on_event(ctx,cb,user_data,1); mk_player_set_on_event(ctx,cb,user_data,1);
} }
API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb, void *user_data) { API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb, void *user_data) {
assert(ctx && cb); assert(ctx && cb);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
player->getPoller()->async([player,cb,user_data](){ player->getPoller()->async([player,cb,user_data](){
//切换线程后再操作 //切换线程后再操作
auto delegate = std::make_shared<FrameWriterInterfaceHelper>([cb,user_data](const Frame::Ptr &frame){ auto delegate = std::make_shared<FrameWriterInterfaceHelper>([cb,user_data](const Frame::Ptr &frame){
cb(user_data,frame->getTrackType(),frame->getCodecId(),frame->data(),frame->size(),frame->dts(),frame->pts()); cb(user_data,frame->getTrackType(),frame->getCodecId(),frame->data(),frame->size(),frame->dts(),frame->pts());
}); });
for(auto &track : player->getTracks()){ for(auto &track : player->getTracks()){
track->addDelegate(delegate); track->addDelegate(delegate);
} }
}); });
} }
API_EXPORT int API_CALL mk_player_video_width(mk_player ctx) { API_EXPORT int API_CALL mk_player_video_width(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
auto track = dynamic_pointer_cast<VideoTrack>(player->getTrack(TrackVideo)); auto track = dynamic_pointer_cast<VideoTrack>(player->getTrack(TrackVideo));
return track ? track->getVideoWidth() : 0; return track ? track->getVideoWidth() : 0;
} }
API_EXPORT int API_CALL mk_player_video_height(mk_player ctx) { API_EXPORT int API_CALL mk_player_video_height(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
auto track = dynamic_pointer_cast<VideoTrack>(player->getTrack(TrackVideo)); auto track = dynamic_pointer_cast<VideoTrack>(player->getTrack(TrackVideo));
return track ? track->getVideoHeight() : 0; return track ? track->getVideoHeight() : 0;
} }
API_EXPORT int API_CALL mk_player_video_fps(mk_player ctx) { API_EXPORT int API_CALL mk_player_video_fps(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
auto track = dynamic_pointer_cast<VideoTrack>(player->getTrack(TrackVideo)); auto track = dynamic_pointer_cast<VideoTrack>(player->getTrack(TrackVideo));
return track ? track->getVideoFps() : 0; return track ? track->getVideoFps() : 0;
} }
API_EXPORT int API_CALL mk_player_audio_samplerate(mk_player ctx) { API_EXPORT int API_CALL mk_player_audio_samplerate(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
auto track = dynamic_pointer_cast<AudioTrack>(player->getTrack(TrackAudio)); auto track = dynamic_pointer_cast<AudioTrack>(player->getTrack(TrackAudio));
return track ? track->getAudioSampleRate() : 0; return track ? track->getAudioSampleRate() : 0;
} }
API_EXPORT int API_CALL mk_player_audio_bit(mk_player ctx) { API_EXPORT int API_CALL mk_player_audio_bit(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
auto track = dynamic_pointer_cast<AudioTrack>(player->getTrack(TrackAudio)); auto track = dynamic_pointer_cast<AudioTrack>(player->getTrack(TrackAudio));
return track ? track->getAudioSampleBit() : 0; return track ? track->getAudioSampleBit() : 0;
} }
API_EXPORT int API_CALL mk_player_audio_channel(mk_player ctx) { API_EXPORT int API_CALL mk_player_audio_channel(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
auto track = dynamic_pointer_cast<AudioTrack>(player->getTrack(TrackAudio)); auto track = dynamic_pointer_cast<AudioTrack>(player->getTrack(TrackAudio));
return track ? track->getAudioChannel() : 0; return track ? track->getAudioChannel() : 0;
} }
API_EXPORT float API_CALL mk_player_duration(mk_player ctx) { API_EXPORT float API_CALL mk_player_duration(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
return player->getDuration(); return player->getDuration();
} }
API_EXPORT float API_CALL mk_player_progress(mk_player ctx) { API_EXPORT float API_CALL mk_player_progress(mk_player ctx) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
return player->getProgress(); return player->getProgress();
} }
API_EXPORT float API_CALL mk_player_loss_rate(mk_player ctx, int track_type) { API_EXPORT float API_CALL mk_player_loss_rate(mk_player ctx, int track_type) {
assert(ctx); assert(ctx);
MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx);
return player->getPacketLossRate((TrackType)track_type); return player->getPacketLossRate((TrackType)track_type);
} }
...@@ -42,7 +42,7 @@ onceToken token([]() { ...@@ -42,7 +42,7 @@ onceToken token([]() {
//windows下先关闭FFmpeg日志(目前不支持日志重定向) //windows下先关闭FFmpeg日志(目前不支持日志重定向)
mINI::Instance()[kCmd] = "%s -re -i \"%s\" -loglevel quiet -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s "; mINI::Instance()[kCmd] = "%s -re -i \"%s\" -loglevel quiet -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s ";
#else #else
string ffmpeg_bin = System::execute("which ffmpeg"); string ffmpeg_bin = System::execute("which ffmpeg");
mINI::Instance()[kCmd] = "%s -re -i \"%s\" -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s "; mINI::Instance()[kCmd] = "%s -re -i \"%s\" -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s ";
#endif #endif
//默认ffmpeg命令路径为环境变量中路径 //默认ffmpeg命令路径为环境变量中路径
......
...@@ -46,92 +46,92 @@ ...@@ -46,92 +46,92 @@
using namespace toolkit; using namespace toolkit;
void Process::run(const string &cmd, const string &log_file_tmp) { void Process::run(const string &cmd, const string &log_file_tmp) {
kill(2000); kill(2000);
#ifdef _WIN32 #ifdef _WIN32
STARTUPINFO si; STARTUPINFO si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si)); //结构体初始化; ZeroMemory(&si, sizeof(si)); //结构体初始化;
ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&pi, sizeof(pi));
LPTSTR lpDir = const_cast<char*>(cmd.data()); LPTSTR lpDir = const_cast<char*>(cmd.data());
if (CreateProcess(NULL, lpDir, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ if (CreateProcess(NULL, lpDir, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程 //下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
_pid = pi.dwProcessId; _pid = pi.dwProcessId;
InfoL << "start child proces " << _pid; InfoL << "start child proces " << _pid;
} else { } else {
WarnL << "start child proces fail: " << GetLastError(); WarnL << "start child proces fail: " << GetLastError();
} }
#else #else
_pid = fork(); _pid = fork();
if (_pid < 0) { if (_pid < 0) {
throw std::runtime_error(StrPrinter << "fork child process falied,err:" << get_uv_errmsg()); throw std::runtime_error(StrPrinter << "fork child process falied,err:" << get_uv_errmsg());
} }
if (_pid == 0) { if (_pid == 0) {
//子进程关闭core文件生成 //子进程关闭core文件生成
struct rlimit rlim = { 0,0 }; struct rlimit rlim = { 0,0 };
setrlimit(RLIMIT_CORE, &rlim); setrlimit(RLIMIT_CORE, &rlim);
//在启动子进程时,暂时禁用SIGINT、SIGTERM信号 //在启动子进程时,暂时禁用SIGINT、SIGTERM信号
// ignore the SIGINT and SIGTERM // ignore the SIGINT and SIGTERM
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN); signal(SIGTERM, SIG_IGN);
string log_file; string log_file;
if (log_file_tmp.empty()) { if (log_file_tmp.empty()) {
log_file = "/dev/null"; log_file = "/dev/null";
} }
else { else {
log_file = StrPrinter << log_file_tmp << "." << getpid(); log_file = StrPrinter << log_file_tmp << "." << getpid();
} }
int log_fd = -1; int log_fd = -1;
int flags = O_CREAT | O_WRONLY | O_APPEND; int flags = O_CREAT | O_WRONLY | O_APPEND;
mode_t mode = S_IRWXO | S_IRWXG | S_IRWXU;// S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; mode_t mode = S_IRWXO | S_IRWXG | S_IRWXU;// S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
File::createfile_path(log_file.data(), mode); File::createfile_path(log_file.data(), mode);
if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) { if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) {
fprintf(stderr, "open log file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno)); fprintf(stderr, "open log file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
} }
else { else {
// dup to stdout and stderr. // dup to stdout and stderr.
if (dup2(log_fd, STDOUT_FILENO) < 0) { if (dup2(log_fd, STDOUT_FILENO) < 0) {
fprintf(stderr, "dup2 stdout file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno)); fprintf(stderr, "dup2 stdout file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
} }
if (dup2(log_fd, STDERR_FILENO) < 0) { if (dup2(log_fd, STDERR_FILENO) < 0) {
fprintf(stderr, "dup2 stderr file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno)); fprintf(stderr, "dup2 stderr file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
} }
// close log fd // close log fd
::close(log_fd); ::close(log_fd);
} }
fprintf(stderr, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", getpid(), cmd.data()); fprintf(stderr, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", getpid(), cmd.data());
// close other fds // close other fds
// TODO: do in right way. // TODO: do in right way.
for (int i = 3; i < 1024; i++) { for (int i = 3; i < 1024; i++) {
::close(i); ::close(i);
} }
auto params = split(cmd, " "); auto params = split(cmd, " ");
// memory leak in child process, it's ok. // memory leak in child process, it's ok.
char **charpv_params = new char *[params.size() + 1]; char **charpv_params = new char *[params.size() + 1];
for (int i = 0; i < (int)params.size(); i++) { for (int i = 0; i < (int)params.size(); i++) {
std::string &p = params[i]; std::string &p = params[i];
charpv_params[i] = (char *)p.data(); charpv_params[i] = (char *)p.data();
} }
// EOF: NULL // EOF: NULL
charpv_params[params.size()] = NULL; charpv_params[params.size()] = NULL;
// TODO: execv or execvp // TODO: execv or execvp
auto ret = execv(params[0].c_str(), charpv_params); auto ret = execv(params[0].c_str(), charpv_params);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "fork process failed, errno=%d(%s)\r\n", errno, strerror(errno)); fprintf(stderr, "fork process failed, errno=%d(%s)\r\n", errno, strerror(errno));
} }
exit(ret); exit(ret);
} }
InfoL << "start child proces " << _pid; InfoL << "start child proces " << _pid;
#endif // _WIN32 #endif // _WIN32
} }
...@@ -148,27 +148,27 @@ static bool s_wait(pid_t pid,int *exit_code_ptr,bool block) { ...@@ -148,27 +148,27 @@ static bool s_wait(pid_t pid,int *exit_code_ptr,bool block) {
} }
int status = 0; int status = 0;
#ifdef _WIN32 #ifdef _WIN32
HANDLE hProcess = NULL; HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程 hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程
if (hProcess == NULL) { if (hProcess == NULL) {
return false; return false;
} }
CloseHandle(hProcess); CloseHandle(hProcess);
#else #else
pid_t p = waitpid(pid, &status, block ? 0 : WNOHANG); pid_t p = waitpid(pid, &status, block ? 0 : WNOHANG);
int exit_code = (status & 0xFF00) >> 8; int exit_code = (status & 0xFF00) >> 8;
if (exit_code_ptr) { if (exit_code_ptr) {
*exit_code_ptr = (status & 0xFF00) >> 8; *exit_code_ptr = (status & 0xFF00) >> 8;
} }
if (p < 0) { if (p < 0) {
WarnL << "waitpid failed, pid=" << pid << ", err=" << get_uv_errmsg(); WarnL << "waitpid failed, pid=" << pid << ", err=" << get_uv_errmsg();
return false; return false;
} }
if (p > 0) { if (p > 0) {
InfoL << "process terminated, pid=" << pid << ", exit code=" << exit_code; InfoL << "process terminated, pid=" << pid << ", exit code=" << exit_code;
return false; return false;
} }
#endif // _WIN32 #endif // _WIN32
return true; return true;
...@@ -180,22 +180,22 @@ static void s_kill(pid_t pid,int max_delay,bool force){ ...@@ -180,22 +180,22 @@ static void s_kill(pid_t pid,int max_delay,bool force){
return; return;
} }
#ifdef _WIN32 #ifdef _WIN32
HANDLE hProcess = NULL; HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程 hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程
if (hProcess == NULL) { if (hProcess == NULL) {
WarnL << "\nOpen Process fAiled: " << GetLastError(); WarnL << "\nOpen Process fAiled: " << GetLastError();
return; return;
} }
DWORD ret = TerminateProcess(hProcess, 0); //结束目标进程 DWORD ret = TerminateProcess(hProcess, 0); //结束目标进程
if (ret == 0) { if (ret == 0) {
WarnL << GetLastError; WarnL << GetLastError;
} }
#else #else
if (::kill(pid, force ? SIGKILL : SIGTERM) == -1) { if (::kill(pid, force ? SIGKILL : SIGTERM) == -1) {
//进程可能已经退出了 //进程可能已经退出了
WarnL << "kill process " << pid << " failed:" << get_uv_errmsg(); WarnL << "kill process " << pid << " failed:" << get_uv_errmsg();
return; return;
} }
#endif // _WIN32 #endif // _WIN32
......
...@@ -774,9 +774,9 @@ void installWebApi() { ...@@ -774,9 +774,9 @@ void installWebApi() {
val["status"] = (int)status; val["status"] = (int)status;
}); });
//获取录像文件夹列表或mp4文件列表 //获取录像文件夹列表或mp4文件列表
//http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01 //http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01
api_regist1("/index/api/getMp4RecordFile", [](API_ARGS1){ api_regist1("/index/api/getMp4RecordFile", [](API_ARGS1){
CHECK_SECRET(); CHECK_SECRET();
CHECK_ARGS("vhost", "app", "stream"); CHECK_ARGS("vhost", "app", "stream");
auto record_path = Recorder::getRecordPath(Recorder::type_mp4, allArgs["vhost"], allArgs["app"],allArgs["stream"]); auto record_path = Recorder::getRecordPath(Recorder::type_mp4, allArgs["vhost"], allArgs["app"],allArgs["stream"]);
...@@ -809,7 +809,7 @@ void installWebApi() { ...@@ -809,7 +809,7 @@ void installWebApi() {
val["data"]["rootPath"] = record_path; val["data"]["rootPath"] = record_path;
val["data"]["paths"] = paths; val["data"]["paths"] = paths;
}); });
////////////以下是注册的Hook API//////////// ////////////以下是注册的Hook API////////////
api_regist1("/index/hook/on_publish",[](API_ARGS1){ api_regist1("/index/hook/on_publish",[](API_ARGS1){
......
...@@ -359,7 +359,7 @@ int start_main(int argc,char *argv[]) { ...@@ -359,7 +359,7 @@ int start_main(int argc,char *argv[]) {
InfoL << "程序退出中,请等待..."; InfoL << "程序退出中,请等待...";
sleep(1); sleep(1);
InfoL << "程序退出完毕!"; InfoL << "程序退出完毕!";
return 0; return 0;
} }
#ifndef DISABLE_MAIN #ifndef DISABLE_MAIN
......
...@@ -47,73 +47,73 @@ AACEncoder::AACEncoder() { ...@@ -47,73 +47,73 @@ AACEncoder::AACEncoder() {
} }
AACEncoder::~AACEncoder() { AACEncoder::~AACEncoder() {
if (_hEncoder != nullptr) { if (_hEncoder != nullptr) {
faacEncClose(_hEncoder); faacEncClose(_hEncoder);
_hEncoder = nullptr; _hEncoder = nullptr;
} }
if (_pucAacBuf != nullptr) { if (_pucAacBuf != nullptr) {
delete[] _pucAacBuf; delete[] _pucAacBuf;
_pucAacBuf = nullptr; _pucAacBuf = nullptr;
} }
if (_pucPcmBuf != nullptr) { if (_pucPcmBuf != nullptr) {
delete[] _pucPcmBuf; delete[] _pucPcmBuf;
_pucPcmBuf = nullptr; _pucPcmBuf = nullptr;
} }
} }
bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) { bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
if (iSampleBit != 16) { if (iSampleBit != 16) {
return false; return false;
} }
// (1) Open FAAC engine // (1) Open FAAC engine
_hEncoder = faacEncOpen(iSampleRate, iChannels, &_ulInputSamples, _hEncoder = faacEncOpen(iSampleRate, iChannels, &_ulInputSamples,
&_ulMaxOutputBytes); &_ulMaxOutputBytes);
if (_hEncoder == NULL) { if (_hEncoder == NULL) {
return false; return false;
} }
_pucAacBuf = new unsigned char[_ulMaxOutputBytes]; _pucAacBuf = new unsigned char[_ulMaxOutputBytes];
_ulMaxInputBytes = _ulInputSamples * iSampleBit / 8; _ulMaxInputBytes = _ulInputSamples * iSampleBit / 8;
_pucPcmBuf = new unsigned char[_ulMaxInputBytes * 4]; _pucPcmBuf = new unsigned char[_ulMaxInputBytes * 4];
// (2.1) Get current encoding configuration // (2.1) Get current encoding configuration
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(_hEncoder); faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(_hEncoder);
if (pConfiguration == NULL) { if (pConfiguration == NULL) {
faacEncClose(_hEncoder); faacEncClose(_hEncoder);
return false; return false;
} }
pConfiguration->aacObjectType =LOW; pConfiguration->aacObjectType =LOW;
pConfiguration->mpegVersion = 4; pConfiguration->mpegVersion = 4;
pConfiguration->useTns = 1; pConfiguration->useTns = 1;
pConfiguration->shortctl = SHORTCTL_NORMAL; pConfiguration->shortctl = SHORTCTL_NORMAL;
pConfiguration->useLfe = 1; pConfiguration->useLfe = 1;
pConfiguration->allowMidside = 1; pConfiguration->allowMidside = 1;
pConfiguration->bitRate = 0; pConfiguration->bitRate = 0;
pConfiguration->bandWidth = 0; pConfiguration->bandWidth = 0;
pConfiguration->quantqual = 50; pConfiguration->quantqual = 50;
pConfiguration->outputFormat = 1; pConfiguration->outputFormat = 1;
pConfiguration->inputFormat = FAAC_INPUT_16BIT; pConfiguration->inputFormat = FAAC_INPUT_16BIT;
// (2.2) Set encoding configuration // (2.2) Set encoding configuration
if(!faacEncSetConfiguration(_hEncoder, pConfiguration)){ if(!faacEncSetConfiguration(_hEncoder, pConfiguration)){
ErrorL << "faacEncSetConfiguration failed"; ErrorL << "faacEncSetConfiguration failed";
faacEncClose(_hEncoder); faacEncClose(_hEncoder);
return false; return false;
} }
return true; return true;
} }
int AACEncoder::inputData(char *pcPcmBufr, int iLen, unsigned char **ppucOutBuffer) { int AACEncoder::inputData(char *pcPcmBufr, int iLen, unsigned char **ppucOutBuffer) {
memcpy(_pucPcmBuf + _uiPcmLen, pcPcmBufr, iLen); memcpy(_pucPcmBuf + _uiPcmLen, pcPcmBufr, iLen);
_uiPcmLen += iLen; _uiPcmLen += iLen;
if (_uiPcmLen < _ulMaxInputBytes) { if (_uiPcmLen < _ulMaxInputBytes) {
return 0; return 0;
} }
int nRet = faacEncEncode(_hEncoder, (int32_t *) (_pucPcmBuf), _ulInputSamples, _pucAacBuf, _ulMaxOutputBytes); int nRet = faacEncEncode(_hEncoder, (int32_t *) (_pucPcmBuf), _ulInputSamples, _pucAacBuf, _ulMaxOutputBytes);
_uiPcmLen -= _ulMaxInputBytes; _uiPcmLen -= _ulMaxInputBytes;
memmove(_pucPcmBuf, _pucPcmBuf + _ulMaxInputBytes, _uiPcmLen); memmove(_pucPcmBuf, _pucPcmBuf + _ulMaxInputBytes, _uiPcmLen);
*ppucOutBuffer = _pucAacBuf; *ppucOutBuffer = _pucAacBuf;
return nRet; return nRet;
} }
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -32,21 +32,21 @@ namespace mediakit { ...@@ -32,21 +32,21 @@ namespace mediakit {
class AACEncoder { class AACEncoder {
public: public:
AACEncoder(void); AACEncoder(void);
virtual ~AACEncoder(void); virtual ~AACEncoder(void);
bool init(int iSampleRate, int iAudioChannel, int iAudioSampleBit); bool init(int iSampleRate, int iAudioChannel, int iAudioSampleBit);
int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer); int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer);
private: private:
unsigned char *_pucPcmBuf = nullptr; unsigned char *_pucPcmBuf = nullptr;
unsigned int _uiPcmLen = 0; unsigned int _uiPcmLen = 0;
unsigned char *_pucAacBuf = nullptr; unsigned char *_pucAacBuf = nullptr;
void *_hEncoder = nullptr; void *_hEncoder = nullptr;
unsigned long _ulInputSamples = 0; unsigned long _ulInputSamples = 0;
unsigned long _ulMaxInputBytes = 0; unsigned long _ulMaxInputBytes = 0;
unsigned long _ulMaxOutputBytes = 0; unsigned long _ulMaxOutputBytes = 0;
}; };
......
...@@ -42,21 +42,21 @@ namespace mediakit { ...@@ -42,21 +42,21 @@ namespace mediakit {
class H264Encoder { class H264Encoder {
public: public:
typedef struct { typedef struct {
int iType; int iType;
int iLength; int iLength;
uint8_t *pucData; uint8_t *pucData;
} H264Frame; } H264Frame;
H264Encoder(void); H264Encoder(void);
virtual ~H264Encoder(void); virtual ~H264Encoder(void);
bool init(int iWidth, int iHeight, int iFps); bool init(int iWidth, int iHeight, int iFps);
int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame); int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame);
private: private:
x264_t* _pX264Handle = nullptr; x264_t* _pX264Handle = nullptr;
x264_picture_t* _pPicIn = nullptr; x264_picture_t* _pPicIn = nullptr;
x264_picture_t* _pPicOut = nullptr; x264_picture_t* _pPicOut = nullptr;
H264Frame _aFrames[10]; H264Frame _aFrames[10];
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -42,8 +42,8 @@ DevChannel::DevChannel(const string &strVhost, ...@@ -42,8 +42,8 @@ DevChannel::DevChannel(const string &strVhost,
const string &strApp, const string &strApp,
const string &strId, const string &strId,
float fDuration, float fDuration,
bool bEanbleRtsp, bool bEanbleRtsp,
bool bEanbleRtmp, bool bEanbleRtmp,
bool bEanbleHls, bool bEanbleHls,
bool bEnableMp4) : bool bEnableMp4) :
MultiMediaSourceMuxer(strVhost, strApp, strId, fDuration, bEanbleRtsp, bEanbleRtmp, bEanbleHls, bEnableMp4) {} MultiMediaSourceMuxer(strVhost, strApp, strId, fDuration, bEanbleRtsp, bEanbleRtmp, bEanbleHls, bEnableMp4) {}
...@@ -52,50 +52,50 @@ DevChannel::~DevChannel() {} ...@@ -52,50 +52,50 @@ DevChannel::~DevChannel() {}
#ifdef ENABLE_X264 #ifdef ENABLE_X264
void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) { void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) {
//TimeTicker1(50); //TimeTicker1(50);
if (!_pH264Enc) { if (!_pH264Enc) {
_pH264Enc.reset(new H264Encoder()); _pH264Enc.reset(new H264Encoder());
if (!_pH264Enc->init(_video->iWidth, _video->iHeight, _video->iFrameRate)) { if (!_pH264Enc->init(_video->iWidth, _video->iHeight, _video->iFrameRate)) {
_pH264Enc.reset(); _pH264Enc.reset();
WarnL << "H264Encoder init failed!"; WarnL << "H264Encoder init failed!";
} }
} }
if (_pH264Enc) { if (_pH264Enc) {
H264Encoder::H264Frame *pOut; H264Encoder::H264Frame *pOut;
int iFrames = _pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut); int iFrames = _pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut);
for (int i = 0; i < iFrames; i++) { for (int i = 0; i < iFrames; i++) {
inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp); inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp);
} }
} }
} }
#endif //ENABLE_X264 #endif //ENABLE_X264
#ifdef ENABLE_FAAC #ifdef ENABLE_FAAC
void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) { void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
if (!_pAacEnc) { if (!_pAacEnc) {
_pAacEnc.reset(new AACEncoder()); _pAacEnc.reset(new AACEncoder());
if (!_pAacEnc->init(_audio->iSampleRate, _audio->iChannel, _audio->iSampleBit)) { if (!_pAacEnc->init(_audio->iSampleRate, _audio->iChannel, _audio->iSampleBit)) {
_pAacEnc.reset(); _pAacEnc.reset();
WarnL << "AACEncoder init failed!"; WarnL << "AACEncoder init failed!";
} }
} }
if (_pAacEnc) { if (_pAacEnc) {
unsigned char *pucOut; unsigned char *pucOut;
int iRet = _pAacEnc->inputData(pcData, iDataLen, &pucOut); int iRet = _pAacEnc->inputData(pcData, iDataLen, &pucOut);
if (iRet > 0) { if (iRet > 0) {
inputAAC((char *) pucOut, iRet, uiStamp); inputAAC((char *) pucOut, iRet, uiStamp);
} }
} }
} }
#endif //ENABLE_FAAC #endif //ENABLE_FAAC
void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32_t pts) { void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32_t pts) {
if(dts == 0){ if(dts == 0){
dts = (uint32_t)_aTicker[0].elapsedTime(); dts = (uint32_t)_aTicker[0].elapsedTime();
}
if(pts == 0){
pts = dts;
} }
if(pts == 0){
pts = dts;
}
int prefixeSize; int prefixeSize;
if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) { if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) {
prefixeSize = 4; prefixeSize = 4;
...@@ -105,46 +105,46 @@ void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32 ...@@ -105,46 +105,46 @@ void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32
prefixeSize = 0; prefixeSize = 0;
} }
H264Frame::Ptr frame = std::make_shared<H264Frame>(); H264Frame::Ptr frame = std::make_shared<H264Frame>();
frame->_dts = dts; frame->_dts = dts;
frame->_pts = pts; frame->_pts = pts;
frame->_buffer.assign("\x00\x00\x00\x01",4); frame->_buffer.assign("\x00\x00\x00\x01",4);
frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize);
frame->_prefix_size = 4; frame->_prefix_size = 4;
inputFrame(frame); inputFrame(frame);
} }
void DevChannel::inputH265(const char* pcData, int iDataLen, uint32_t dts,uint32_t pts) { void DevChannel::inputH265(const char* pcData, int iDataLen, uint32_t dts,uint32_t pts) {
if(dts == 0){ if(dts == 0){
dts = (uint32_t)_aTicker[0].elapsedTime(); dts = (uint32_t)_aTicker[0].elapsedTime();
} }
if(pts == 0){ if(pts == 0){
pts = dts; pts = dts;
} }
int prefixeSize; int prefixeSize;
if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) { if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) {
prefixeSize = 4; prefixeSize = 4;
} else if (memcmp("\x00\x00\x01", pcData, 3) == 0) { } else if (memcmp("\x00\x00\x01", pcData, 3) == 0) {
prefixeSize = 3; prefixeSize = 3;
} else { } else {
prefixeSize = 0; prefixeSize = 0;
} }
H265Frame::Ptr frame = std::make_shared<H265Frame>(); H265Frame::Ptr frame = std::make_shared<H265Frame>();
frame->_dts = dts; frame->_dts = dts;
frame->_pts = pts; frame->_pts = pts;
frame->_buffer.assign("\x00\x00\x00\x01",4); frame->_buffer.assign("\x00\x00\x00\x01",4);
frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize);
frame->_prefix_size = 4; frame->_prefix_size = 4;
inputFrame(frame); inputFrame(frame);
} }
void DevChannel::inputAAC(const char* pcData, int iDataLen, uint32_t uiStamp,bool withAdtsHeader) { void DevChannel::inputAAC(const char* pcData, int iDataLen, uint32_t uiStamp,bool withAdtsHeader) {
if(withAdtsHeader){ if(withAdtsHeader){
inputAAC(pcData+7,iDataLen-7,uiStamp,pcData); inputAAC(pcData+7,iDataLen-7,uiStamp,pcData);
} else if(_audio) { } else if(_audio) {
inputAAC(pcData,iDataLen,uiStamp,(char *)_adtsHeader); inputAAC(pcData,iDataLen,uiStamp,(char *)_adtsHeader);
} }
} }
void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader){ void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader){
...@@ -152,54 +152,54 @@ void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t u ...@@ -152,54 +152,54 @@ void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t u
uiStamp = (uint32_t)_aTicker[1].elapsedTime(); uiStamp = (uint32_t)_aTicker[1].elapsedTime();
} }
if(pcAdtsHeader + 7 == pcDataWithoutAdts){ if(pcAdtsHeader + 7 == pcDataWithoutAdts){
inputFrame(std::make_shared<AACFrameNoCacheAble>((char *)pcDataWithoutAdts - 7,iDataLen + 7,uiStamp,7)); inputFrame(std::make_shared<AACFrameNoCacheAble>((char *)pcDataWithoutAdts - 7,iDataLen + 7,uiStamp,7));
} else { } else {
char *dataWithAdts = new char[iDataLen + 7]; char *dataWithAdts = new char[iDataLen + 7];
memcpy(dataWithAdts,pcAdtsHeader,7); memcpy(dataWithAdts,pcAdtsHeader,7);
memcpy(dataWithAdts + 7 , pcDataWithoutAdts , iDataLen); memcpy(dataWithAdts + 7 , pcDataWithoutAdts , iDataLen);
inputFrame(std::make_shared<AACFrameNoCacheAble>(dataWithAdts,iDataLen + 7,uiStamp,7)); inputFrame(std::make_shared<AACFrameNoCacheAble>(dataWithAdts,iDataLen + 7,uiStamp,7));
delete [] dataWithAdts; delete [] dataWithAdts;
} }
} }
void DevChannel::initVideo(const VideoInfo& info) { void DevChannel::initVideo(const VideoInfo& info) {
_video = std::make_shared<VideoInfo>(info); _video = std::make_shared<VideoInfo>(info);
addTrack(std::make_shared<H264Track>()); addTrack(std::make_shared<H264Track>());
} }
void DevChannel::initH265Video(const VideoInfo &info){ void DevChannel::initH265Video(const VideoInfo &info){
_video = std::make_shared<VideoInfo>(info); _video = std::make_shared<VideoInfo>(info);
addTrack(std::make_shared<H265Track>()); addTrack(std::make_shared<H265Track>());
} }
void DevChannel::initAudio(const AudioInfo& info) { void DevChannel::initAudio(const AudioInfo& info) {
_audio = std::make_shared<AudioInfo>(info); _audio = std::make_shared<AudioInfo>(info);
addTrack(std::make_shared<AACTrack>()); addTrack(std::make_shared<AACTrack>());
AACFrame adtsHeader; AACFrame adtsHeader;
adtsHeader.syncword = 0x0FFF; adtsHeader.syncword = 0x0FFF;
adtsHeader.id = 0; adtsHeader.id = 0;
adtsHeader.layer = 0; adtsHeader.layer = 0;
adtsHeader.protection_absent = 1; adtsHeader.protection_absent = 1;
adtsHeader.profile = info.iProfile;//audioObjectType - 1; adtsHeader.profile = info.iProfile;//audioObjectType - 1;
int i = 0; int i = 0;
for(auto rate : samplingFrequencyTable){ for(auto rate : samplingFrequencyTable){
if(rate == info.iSampleRate){ if(rate == info.iSampleRate){
adtsHeader.sf_index = i; adtsHeader.sf_index = i;
}; };
++i; ++i;
} }
adtsHeader.private_bit = 0; adtsHeader.private_bit = 0;
adtsHeader.channel_configuration = info.iChannel; adtsHeader.channel_configuration = info.iChannel;
adtsHeader.original = 0; adtsHeader.original = 0;
adtsHeader.home = 0; adtsHeader.home = 0;
adtsHeader.copyright_identification_bit = 0; adtsHeader.copyright_identification_bit = 0;
adtsHeader.copyright_identification_start = 0; adtsHeader.copyright_identification_start = 0;
adtsHeader.aac_frame_length = 7; adtsHeader.aac_frame_length = 7;
adtsHeader.adts_buffer_fullness = 2047; adtsHeader.adts_buffer_fullness = 2047;
adtsHeader.no_raw_data_blocks_in_frame = 0; adtsHeader.no_raw_data_blocks_in_frame = 0;
writeAdtsHeader(adtsHeader,_adtsHeader); writeAdtsHeader(adtsHeader,_adtsHeader);
} }
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -51,16 +51,16 @@ namespace mediakit { ...@@ -51,16 +51,16 @@ namespace mediakit {
class VideoInfo { class VideoInfo {
public: public:
int iWidth; int iWidth;
int iHeight; int iHeight;
float iFrameRate; float iFrameRate;
}; };
class AudioInfo { class AudioInfo {
public: public:
int iChannel; int iChannel;
int iSampleBit; int iSampleBit;
int iSampleRate; int iSampleRate;
int iProfile; int iProfile;
}; };
/** /**
...@@ -68,82 +68,82 @@ public: ...@@ -68,82 +68,82 @@ public:
*/ */
class DevChannel : public MultiMediaSourceMuxer{ class DevChannel : public MultiMediaSourceMuxer{
public: public:
typedef std::shared_ptr<DevChannel> Ptr; typedef std::shared_ptr<DevChannel> Ptr;
//fDuration<=0为直播,否则为点播 //fDuration<=0为直播,否则为点播
DevChannel(const string &strVhost, DevChannel(const string &strVhost,
const string &strApp, const string &strApp,
const string &strId, const string &strId,
float fDuration = 0, float fDuration = 0,
bool bEanbleRtsp = true, bool bEanbleRtsp = true,
bool bEanbleRtmp = true, bool bEanbleRtmp = true,
bool bEanbleHls = true, bool bEanbleHls = true,
bool bEnableMp4 = false); bool bEnableMp4 = false);
virtual ~DevChannel(); virtual ~DevChannel();
/** /**
* 初始化h264视频Track * 初始化h264视频Track
* 相当于MultiMediaSourceMuxer::addTrack(H264Track::Ptr ); * 相当于MultiMediaSourceMuxer::addTrack(H264Track::Ptr );
* @param info * @param info
*/ */
void initVideo(const VideoInfo &info); void initVideo(const VideoInfo &info);
/** /**
* 初始化h265视频Track * 初始化h265视频Track
* @param info * @param info
*/ */
void initH265Video(const VideoInfo &info); void initH265Video(const VideoInfo &info);
/** /**
* 初始化aac音频Track * 初始化aac音频Track
* 相当于MultiMediaSourceMuxer::addTrack(AACTrack::Ptr ); * 相当于MultiMediaSourceMuxer::addTrack(AACTrack::Ptr );
* @param info * @param info
*/ */
void initAudio(const AudioInfo &info); void initAudio(const AudioInfo &info);
/** /**
* 输入264帧 * 输入264帧
* @param pcData 264单帧数据指针 * @param pcData 264单帧数据指针
* @param iDataLen 数据指针长度 * @param iDataLen 数据指针长度
* @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳 * @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳
* @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts * @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts
*/ */
void inputH264(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0); void inputH264(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0);
/** /**
* 输入265帧 * 输入265帧
* @param pcData 265单帧数据指针 * @param pcData 265单帧数据指针
* @param iDataLen 数据指针长度 * @param iDataLen 数据指针长度
* @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳 * @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳
* @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts * @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts
*/ */
void inputH265(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0); void inputH265(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0);
/** /**
* 输入可能带adts头的aac帧 * 输入可能带adts头的aac帧
* @param pcDataWithAdts 可能带adts头的aac帧 * @param pcDataWithAdts 可能带adts头的aac帧
* @param iDataLen 帧数据长度 * @param iDataLen 帧数据长度
* @param uiStamp 时间戳,单位毫秒,等于0时内部会自动生成时间戳 * @param uiStamp 时间戳,单位毫秒,等于0时内部会自动生成时间戳
* @param withAdtsHeader 是否带adts头 * @param withAdtsHeader 是否带adts头
*/ */
void inputAAC(const char *pcDataWithAdts, int iDataLen, uint32_t uiStamp, bool withAdtsHeader = true); void inputAAC(const char *pcDataWithAdts, int iDataLen, uint32_t uiStamp, bool withAdtsHeader = true);
/** /**
* 输入不带adts头的aac帧 * 输入不带adts头的aac帧
* @param pcDataWithoutAdts 不带adts头的aac帧 * @param pcDataWithoutAdts 不带adts头的aac帧
* @param iDataLen 帧数据长度 * @param iDataLen 帧数据长度
* @param uiStamp 时间戳,单位毫秒 * @param uiStamp 时间戳,单位毫秒
* @param pcAdtsHeader adts头 * @param pcAdtsHeader adts头
*/ */
void inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader); void inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader);
#ifdef ENABLE_X264 #ifdef ENABLE_X264
/** /**
* 输入yuv420p视频帧,内部会完成编码并调用inputH264方法 * 输入yuv420p视频帧,内部会完成编码并调用inputH264方法
* @param apcYuv * @param apcYuv
* @param aiYuvLen * @param aiYuvLen
* @param uiStamp * @param uiStamp
*/ */
void inputYUV(char *apcYuv[3], int aiYuvLen[3], uint32_t uiStamp); void inputYUV(char *apcYuv[3], int aiYuvLen[3], uint32_t uiStamp);
#endif //ENABLE_X264 #endif //ENABLE_X264
...@@ -160,11 +160,11 @@ public: ...@@ -160,11 +160,11 @@ public:
private: private:
#ifdef ENABLE_X264 #ifdef ENABLE_X264
std::shared_ptr<H264Encoder> _pH264Enc; std::shared_ptr<H264Encoder> _pH264Enc;
#endif //ENABLE_X264 #endif //ENABLE_X264
#ifdef ENABLE_FAAC #ifdef ENABLE_FAAC
std::shared_ptr<AACEncoder> _pAacEnc; std::shared_ptr<AACEncoder> _pAacEnc;
#endif //ENABLE_FAAC #endif //ENABLE_FAAC
std::shared_ptr<VideoInfo> _video; std::shared_ptr<VideoInfo> _video;
std::shared_ptr<AudioInfo> _audio; std::shared_ptr<AudioInfo> _audio;
......
...@@ -42,15 +42,15 @@ bool loadIniConfig(const char *ini_path){ ...@@ -42,15 +42,15 @@ bool loadIniConfig(const char *ini_path){
}else{ }else{
ini = exePath() + ".ini"; ini = exePath() + ".ini";
} }
try{ try{
mINI::Instance().parseFile(ini); mINI::Instance().parseFile(ini);
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
return true; return true;
}catch (std::exception &ex) { }catch (std::exception &ex) {
InfoL << "dump ini file to:" << ini; InfoL << "dump ini file to:" << ini;
mINI::Instance().dumpFile(ini); mINI::Instance().dumpFile(ini);
return false; return false;
} }
} }
////////////广播名称/////////// ////////////广播名称///////////
namespace Broadcast { namespace Broadcast {
...@@ -90,12 +90,12 @@ onceToken token([](){ ...@@ -90,12 +90,12 @@ onceToken token([](){
mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000; mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000;
mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000; mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000;
mINI::Instance()[kEnableVhost] = 0; mINI::Instance()[kEnableVhost] = 0;
mINI::Instance()[kUltraLowDelay] = 1; mINI::Instance()[kUltraLowDelay] = 1;
mINI::Instance()[kAddMuteAudio] = 1; mINI::Instance()[kAddMuteAudio] = 1;
mINI::Instance()[kResetWhenRePlay] = 1; mINI::Instance()[kResetWhenRePlay] = 1;
mINI::Instance()[kPublishToRtxp] = 1; mINI::Instance()[kPublishToRtxp] = 1;
mINI::Instance()[kPublishToHls] = 1; mINI::Instance()[kPublishToHls] = 1;
mINI::Instance()[kPublishToMP4] = 0; mINI::Instance()[kPublishToMP4] = 0;
},nullptr); },nullptr);
}//namespace General }//namespace General
...@@ -117,26 +117,26 @@ const string kRootPath = HTTP_FIELD"rootPath"; ...@@ -117,26 +117,26 @@ const string kRootPath = HTTP_FIELD"rootPath";
const string kNotFound = HTTP_FIELD"notFound"; const string kNotFound = HTTP_FIELD"notFound";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kSendBufSize] = 64 * 1024; mINI::Instance()[kSendBufSize] = 64 * 1024;
mINI::Instance()[kMaxReqSize] = 4*1024; mINI::Instance()[kMaxReqSize] = 4*1024;
mINI::Instance()[kKeepAliveSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15;
#if defined(_WIN32) #if defined(_WIN32)
mINI::Instance()[kCharSet] = "gb2312"; mINI::Instance()[kCharSet] = "gb2312";
#else #else
mINI::Instance()[kCharSet] ="utf-8"; mINI::Instance()[kCharSet] ="utf-8";
#endif #endif
mINI::Instance()[kRootPath] = "./www"; mINI::Instance()[kRootPath] = "./www";
mINI::Instance()[kNotFound] = mINI::Instance()[kNotFound] =
"<html>" "<html>"
"<head><title>404 Not Found</title></head>" "<head><title>404 Not Found</title></head>"
"<body bgcolor=\"white\">" "<body bgcolor=\"white\">"
"<center><h1>您访问的资源不存在!</h1></center>" "<center><h1>您访问的资源不存在!</h1></center>"
"<hr><center>" "<hr><center>"
SERVER_NAME SERVER_NAME
"</center>" "</center>"
"</body>" "</body>"
"</html>"; "</html>";
},nullptr); },nullptr);
}//namespace Http }//namespace Http
...@@ -147,7 +147,7 @@ namespace Shell { ...@@ -147,7 +147,7 @@ namespace Shell {
const string kMaxReqSize = SHELL_FIELD"maxReqSize"; const string kMaxReqSize = SHELL_FIELD"maxReqSize";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kMaxReqSize] = 1024; mINI::Instance()[kMaxReqSize] = 1024;
},nullptr); },nullptr);
} //namespace Shell } //namespace Shell
...@@ -160,11 +160,11 @@ const string kKeepAliveSecond = RTSP_FIELD"keepAliveSecond"; ...@@ -160,11 +160,11 @@ const string kKeepAliveSecond = RTSP_FIELD"keepAliveSecond";
const string kDirectProxy = RTSP_FIELD"directProxy"; const string kDirectProxy = RTSP_FIELD"directProxy";
onceToken token([](){ onceToken token([](){
//默认Md5方式认证 //默认Md5方式认证
mINI::Instance()[kAuthBasic] = 0; mINI::Instance()[kAuthBasic] = 0;
mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kHandshakeSecond] = 15;
mINI::Instance()[kKeepAliveSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15;
mINI::Instance()[kDirectProxy] = 1; mINI::Instance()[kDirectProxy] = 1;
},nullptr); },nullptr);
} //namespace Rtsp } //namespace Rtsp
...@@ -176,7 +176,7 @@ const string kHandshakeSecond = RTMP_FIELD"handshakeSecond"; ...@@ -176,7 +176,7 @@ const string kHandshakeSecond = RTMP_FIELD"handshakeSecond";
const string kKeepAliveSecond = RTMP_FIELD"keepAliveSecond"; const string kKeepAliveSecond = RTMP_FIELD"keepAliveSecond";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kModifyStamp] = false; mINI::Instance()[kModifyStamp] = false;
mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kHandshakeSecond] = 15;
mINI::Instance()[kKeepAliveSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15;
},nullptr); },nullptr);
...@@ -197,11 +197,11 @@ const string kClearCount = RTP_FIELD"clearCount"; ...@@ -197,11 +197,11 @@ const string kClearCount = RTP_FIELD"clearCount";
const string kCycleMS = RTP_FIELD"cycleMS"; const string kCycleMS = RTP_FIELD"cycleMS";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kVideoMtuSize] = 1400; mINI::Instance()[kVideoMtuSize] = 1400;
mINI::Instance()[kAudioMtuSize] = 600; mINI::Instance()[kAudioMtuSize] = 600;
mINI::Instance()[kMaxRtpCount] = 50; mINI::Instance()[kMaxRtpCount] = 50;
mINI::Instance()[kClearCount] = 10; mINI::Instance()[kClearCount] = 10;
mINI::Instance()[kCycleMS] = 13*60*60*1000; mINI::Instance()[kCycleMS] = 13*60*60*1000;
},nullptr); },nullptr);
} //namespace Rtsp } //namespace Rtsp
...@@ -216,9 +216,9 @@ const string kAddrMax = MULTI_FIELD"addrMax"; ...@@ -216,9 +216,9 @@ const string kAddrMax = MULTI_FIELD"addrMax";
const string kUdpTTL = MULTI_FIELD"udpTTL"; const string kUdpTTL = MULTI_FIELD"udpTTL";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kAddrMin] = "239.0.0.0"; mINI::Instance()[kAddrMin] = "239.0.0.0";
mINI::Instance()[kAddrMax] = "239.255.255.255"; mINI::Instance()[kAddrMax] = "239.255.255.255";
mINI::Instance()[kUdpTTL] = 64; mINI::Instance()[kUdpTTL] = 64;
},nullptr); },nullptr);
} //namespace MultiCast } //namespace MultiCast
...@@ -241,13 +241,13 @@ const string kFastStart = RECORD_FIELD"fastStart"; ...@@ -241,13 +241,13 @@ const string kFastStart = RECORD_FIELD"fastStart";
const string kFileRepeat = RECORD_FIELD"fileRepeat"; const string kFileRepeat = RECORD_FIELD"fileRepeat";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kAppName] = "record"; mINI::Instance()[kAppName] = "record";
mINI::Instance()[kSampleMS] = 500; mINI::Instance()[kSampleMS] = 500;
mINI::Instance()[kFileSecond] = 60*60; mINI::Instance()[kFileSecond] = 60*60;
mINI::Instance()[kFilePath] = "./www"; mINI::Instance()[kFilePath] = "./www";
mINI::Instance()[kFileBufSize] = 64 * 1024; mINI::Instance()[kFileBufSize] = 64 * 1024;
mINI::Instance()[kFastStart] = false; mINI::Instance()[kFastStart] = false;
mINI::Instance()[kFileRepeat] = false; mINI::Instance()[kFileRepeat] = false;
},nullptr); },nullptr);
} //namespace Record } //namespace Record
...@@ -266,11 +266,11 @@ const string kFileBufSize = HLS_FIELD"fileBufSize"; ...@@ -266,11 +266,11 @@ const string kFileBufSize = HLS_FIELD"fileBufSize";
const string kFilePath = HLS_FIELD"filePath"; const string kFilePath = HLS_FIELD"filePath";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kSegmentDuration] = 2; mINI::Instance()[kSegmentDuration] = 2;
mINI::Instance()[kSegmentNum] = 3; mINI::Instance()[kSegmentNum] = 3;
mINI::Instance()[kSegmentRetain] = 5; mINI::Instance()[kSegmentRetain] = 5;
mINI::Instance()[kFileBufSize] = 64 * 1024; mINI::Instance()[kFileBufSize] = 64 * 1024;
mINI::Instance()[kFilePath] = "./www"; mINI::Instance()[kFilePath] = "./www";
},nullptr); },nullptr);
} //namespace Hls } //namespace Hls
...@@ -286,9 +286,9 @@ const string kCheckSource = RTP_PROXY_FIELD"checkSource"; ...@@ -286,9 +286,9 @@ const string kCheckSource = RTP_PROXY_FIELD"checkSource";
const string kTimeoutSec = RTP_PROXY_FIELD"timeoutSec"; const string kTimeoutSec = RTP_PROXY_FIELD"timeoutSec";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kDumpDir] = ""; mINI::Instance()[kDumpDir] = "";
mINI::Instance()[kCheckSource] = 1; mINI::Instance()[kCheckSource] = 1;
mINI::Instance()[kTimeoutSec] = 15; mINI::Instance()[kTimeoutSec] = 15;
},nullptr); },nullptr);
} //namespace RtpProxy } //namespace RtpProxy
......
...@@ -88,24 +88,24 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { ...@@ -88,24 +88,24 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
* Type==7:SPS frame * Type==7:SPS frame
* Type==8:PPS frame * Type==8:PPS frame
*/ */
/* /*
RTF3984 5.2节 Common Structure of the RTP Payload Format RTF3984 5.2节 Common Structure of the RTP Payload Format
Table 1. Summary of NAL unit types and their payload structures Table 1. Summary of NAL unit types and their payload structures
Type Packet Type name Section Type Packet Type name Section
--------------------------------------------------------- ---------------------------------------------------------
0 undefined - 0 undefined -
1-23 NAL unit Single NAL unit packet per H.264 5.6 1-23 NAL unit Single NAL unit packet per H.264 5.6
24 STAP-A Single-time aggregation packet 5.7.1 24 STAP-A Single-time aggregation packet 5.7.1
25 STAP-B Single-time aggregation packet 5.7.1 25 STAP-B Single-time aggregation packet 5.7.1
26 MTAP16 Multi-time aggregation packet 5.7.2 26 MTAP16 Multi-time aggregation packet 5.7.2
27 MTAP24 Multi-time aggregation packet 5.7.2 27 MTAP24 Multi-time aggregation packet 5.7.2
28 FU-A Fragmentation unit 5.8 28 FU-A Fragmentation unit 5.8
29 FU-B Fragmentation unit 5.8 29 FU-B Fragmentation unit 5.8
30-31 undefined - 30-31 undefined -
*/ */
const uint8_t *frame = (uint8_t *) rtppack->data() + rtppack->offset; const uint8_t *frame = (uint8_t *) rtppack->data() + rtppack->offset;
int length = rtppack->size() - rtppack->offset; int length = rtppack->size() - rtppack->offset;
NALU nal; NALU nal;
......
...@@ -34,36 +34,36 @@ bool getHEVCInfo(const char * vps, int vps_len,const char * sps,int sps_len,int ...@@ -34,36 +34,36 @@ bool getHEVCInfo(const char * vps, int vps_len,const char * sps,int sps_len,int
T_GetBitContext tGetBitBuf; T_GetBitContext tGetBitBuf;
T_HEVCSPS tH265SpsInfo; T_HEVCSPS tH265SpsInfo;
T_HEVCVPS tH265VpsInfo; T_HEVCVPS tH265VpsInfo;
if ( vps_len > 2 ){ if ( vps_len > 2 ){
memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); memset(&tGetBitBuf,0,sizeof(tGetBitBuf));
memset(&tH265VpsInfo,0,sizeof(tH265VpsInfo)); memset(&tH265VpsInfo,0,sizeof(tH265VpsInfo));
tGetBitBuf.pu8Buf = (uint8_t*)vps+2; tGetBitBuf.pu8Buf = (uint8_t*)vps+2;
tGetBitBuf.iBufSize = vps_len-2; tGetBitBuf.iBufSize = vps_len-2;
if(0 != h265DecVideoParameterSet((void *) &tGetBitBuf, &tH265VpsInfo)){ if(0 != h265DecVideoParameterSet((void *) &tGetBitBuf, &tH265VpsInfo)){
return false; return false;
} }
} }
if ( sps_len > 2 ){ if ( sps_len > 2 ){
memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); memset(&tGetBitBuf,0,sizeof(tGetBitBuf));
memset(&tH265SpsInfo,0,sizeof(tH265SpsInfo)); memset(&tH265SpsInfo,0,sizeof(tH265SpsInfo));
tGetBitBuf.pu8Buf = (uint8_t*)sps+2; tGetBitBuf.pu8Buf = (uint8_t*)sps+2;
tGetBitBuf.iBufSize = sps_len-2; tGetBitBuf.iBufSize = sps_len-2;
if(0 != h265DecSeqParameterSet((void *) &tGetBitBuf, &tH265SpsInfo)){ if(0 != h265DecSeqParameterSet((void *) &tGetBitBuf, &tH265SpsInfo)){
return false; return false;
} }
} }
else else
return false; return false;
h265GetWidthHeight(&tH265SpsInfo, &iVideoWidth, &iVideoHeight); h265GetWidthHeight(&tH265SpsInfo, &iVideoWidth, &iVideoHeight);
iVideoFps = 0; iVideoFps = 0;
h265GeFramerate(&tH265VpsInfo, &tH265SpsInfo, &iVideoFps); h265GeFramerate(&tH265VpsInfo, &tH265SpsInfo, &iVideoFps);
// ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps; // ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps;
return true; return true;
} }
bool getHEVCInfo(const string &strVps, const string &strSps, int &iVideoWidth, int &iVideoHeight, float &iVideoFps) { bool getHEVCInfo(const string &strVps, const string &strSps, int &iVideoWidth, int &iVideoHeight, float &iVideoFps) {
return getHEVCInfo(strVps.data(),strVps.size(),strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps); return getHEVCInfo(strVps.data(),strVps.size(),strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps);
} }
Sdp::Ptr H265Track::getSdp() { Sdp::Ptr H265Track::getSdp() {
......
...@@ -202,7 +202,7 @@ public: ...@@ -202,7 +202,7 @@ public:
_vps = vps.substr(vps_prefix_len); _vps = vps.substr(vps_prefix_len);
_sps = sps.substr(sps_prefix_len); _sps = sps.substr(sps_prefix_len);
_pps = pps.substr(pps_prefix_len); _pps = pps.substr(pps_prefix_len);
onReady(); onReady();
} }
/** /**
...@@ -267,10 +267,10 @@ public: ...@@ -267,10 +267,10 @@ public:
* @param frame 数据帧 * @param frame 数据帧
*/ */
void inputFrame(const Frame::Ptr &frame) override{ void inputFrame(const Frame::Ptr &frame) override{
int type = H265_TYPE(*((uint8_t *)frame->data() + frame->prefixSize())); int type = H265_TYPE(*((uint8_t *)frame->data() + frame->prefixSize()));
if(type == H265Frame::NAL_VPS){ if(type == H265Frame::NAL_VPS){
bool first_frame = true; bool first_frame = true;
splitH264(frame->data() + frame->prefixSize(), splitH264(frame->data() + frame->prefixSize(),
frame->size() - frame->prefixSize(), frame->size() - frame->prefixSize(),
[&](const char *ptr, int len){ [&](const char *ptr, int len){
if(first_frame){ if(first_frame){
...@@ -288,9 +288,9 @@ public: ...@@ -288,9 +288,9 @@ public:
inputFrame_l(sub_frame); inputFrame_l(sub_frame);
} }
}); });
}else{ }else{
inputFrame_l(frame); inputFrame_l(frame);
} }
} }
private: private:
...@@ -336,7 +336,7 @@ private: ...@@ -336,7 +336,7 @@ private:
} }
} }
/** /**
* 解析sps获取宽高fps * 解析sps获取宽高fps
*/ */
void onReady(){ void onReady(){
......
...@@ -434,7 +434,7 @@ typedef struct T_HEVCSPS { ...@@ -434,7 +434,7 @@ typedef struct T_HEVCSPS {
int iQpBdOffset; int iQpBdOffset;
int iVuiPresent; int iVuiPresent;
}T_HEVCSPS; }T_HEVCSPS;
......
...@@ -137,10 +137,10 @@ public: ...@@ -137,10 +137,10 @@ public:
virtual ~TrackSource(){} virtual ~TrackSource(){}
/** /**
* 获取全部的Track * 获取全部的Track
* @param trackReady 是否获取全部已经准备好的Track * @param trackReady 是否获取全部已经准备好的Track
* @return * @return
*/ */
virtual vector<Track::Ptr> getTracks(bool trackReady = true) const = 0; virtual vector<Track::Ptr> getTracks(bool trackReady = true) const = 0;
/** /**
......
...@@ -148,7 +148,7 @@ protected: ...@@ -148,7 +148,7 @@ protected:
* 接收http回复完毕, * 接收http回复完毕,
*/ */
virtual void onResponseCompleted(){ virtual void onResponseCompleted(){
DebugL; DebugL;
} }
/** /**
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
namespace mediakit { namespace mediakit {
void HttpClientImp::onConnect(const SockException &ex) { void HttpClientImp::onConnect(const SockException &ex) {
if(!_isHttps){ if(!_isHttps){
HttpClient::onConnect(ex); HttpClient::onConnect(ex);
} else { } else {
TcpClientWithSSL<HttpClient>::onConnect(ex); TcpClientWithSSL<HttpClient>::onConnect(ex);
} }
} }
......
...@@ -36,11 +36,11 @@ namespace mediakit { ...@@ -36,11 +36,11 @@ namespace mediakit {
class HttpClientImp: public TcpClientWithSSL<HttpClient> { class HttpClientImp: public TcpClientWithSSL<HttpClient> {
public: public:
typedef std::shared_ptr<HttpClientImp> Ptr; typedef std::shared_ptr<HttpClientImp> Ptr;
HttpClientImp() {} HttpClientImp() {}
virtual ~HttpClientImp() {} virtual ~HttpClientImp() {}
protected: protected:
void onConnect(const SockException &ex) override ; void onConnect(const SockException &ex) override ;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -36,75 +36,75 @@ HttpDownloader::HttpDownloader() { ...@@ -36,75 +36,75 @@ HttpDownloader::HttpDownloader() {
} }
HttpDownloader::~HttpDownloader() { HttpDownloader::~HttpDownloader() {
closeFile(); closeFile();
} }
void HttpDownloader::startDownload(const string& url, const string& filePath,bool bAppend,float timeOutSecond) { void HttpDownloader::startDownload(const string& url, const string& filePath,bool bAppend,float timeOutSecond) {
_filePath = filePath; _filePath = filePath;
if(_filePath.empty()){ if(_filePath.empty()){
_filePath = exeDir() + "HttpDownloader/" + MD5(url).hexdigest(); _filePath = exeDir() + "HttpDownloader/" + MD5(url).hexdigest();
} }
_saveFile = File::createfile_file(_filePath.data(),bAppend ? "ab" : "wb"); _saveFile = File::createfile_file(_filePath.data(),bAppend ? "ab" : "wb");
if(!_saveFile){ if(!_saveFile){
auto strErr = StrPrinter << "打开文件失败:" << filePath << endl; auto strErr = StrPrinter << "打开文件失败:" << filePath << endl;
throw std::runtime_error(strErr); throw std::runtime_error(strErr);
} }
_bDownloadSuccess = false; _bDownloadSuccess = false;
if(bAppend){ if(bAppend){
auto currentLen = ftell(_saveFile); auto currentLen = ftell(_saveFile);
if(currentLen){ if(currentLen){
//最少续传一个字节,怕遇到http 416的错误 //最少续传一个字节,怕遇到http 416的错误
currentLen -= 1; currentLen -= 1;
fseek(_saveFile,-1,SEEK_CUR); fseek(_saveFile,-1,SEEK_CUR);
} }
addHeader("Range", StrPrinter << "bytes=" << currentLen << "-" << endl); addHeader("Range", StrPrinter << "bytes=" << currentLen << "-" << endl);
} }
setMethod("GET"); setMethod("GET");
sendRequest(url,timeOutSecond); sendRequest(url,timeOutSecond);
} }
int64_t HttpDownloader::onResponseHeader(const string& status,const HttpHeader& headers) { int64_t HttpDownloader::onResponseHeader(const string& status,const HttpHeader& headers) {
if(status != "200" && status != "206"){ if(status != "200" && status != "206"){
//失败 //失败
shutdown(SockException(Err_shutdown,StrPrinter << "Http Status:" << status)); shutdown(SockException(Err_shutdown,StrPrinter << "Http Status:" << status));
} }
//后续全部是content //后续全部是content
return -1; return -1;
} }
void HttpDownloader::onResponseBody(const char* buf, int64_t size, int64_t recvedSize, int64_t totalSize) { void HttpDownloader::onResponseBody(const char* buf, int64_t size, int64_t recvedSize, int64_t totalSize) {
if(_saveFile){ if(_saveFile){
fwrite(buf,size,1,_saveFile); fwrite(buf,size,1,_saveFile);
} }
} }
void HttpDownloader::onResponseCompleted() { void HttpDownloader::onResponseCompleted() {
closeFile(); closeFile();
//InfoL << "md5Sum:" << getMd5Sum(_filePath); //InfoL << "md5Sum:" << getMd5Sum(_filePath);
_bDownloadSuccess = true; _bDownloadSuccess = true;
if(_onResult){ if(_onResult){
_onResult(Err_success,"success",_filePath); _onResult(Err_success,"success",_filePath);
_onResult = nullptr; _onResult = nullptr;
} }
} }
void HttpDownloader::onDisconnect(const SockException &ex) { void HttpDownloader::onDisconnect(const SockException &ex) {
closeFile(); closeFile();
if(!_bDownloadSuccess){ if(!_bDownloadSuccess){
File::delete_file(_filePath.data()); File::delete_file(_filePath.data());
} }
if(_onResult){ if(_onResult){
_onResult(ex.getErrCode(),ex.what(),_filePath); _onResult(ex.getErrCode(),ex.what(),_filePath);
_onResult = nullptr; _onResult = nullptr;
} }
} }
void HttpDownloader::closeFile() { void HttpDownloader::closeFile() {
if(_saveFile){ if(_saveFile){
fflush(_saveFile); fflush(_saveFile);
fclose(_saveFile); fclose(_saveFile);
_saveFile = nullptr; _saveFile = nullptr;
} }
} }
......
...@@ -33,30 +33,30 @@ namespace mediakit { ...@@ -33,30 +33,30 @@ namespace mediakit {
class HttpDownloader: public HttpClientImp { class HttpDownloader: public HttpClientImp {
public: public:
typedef std::shared_ptr<HttpDownloader> Ptr; typedef std::shared_ptr<HttpDownloader> Ptr;
typedef std::function<void(ErrCode code,const string &errMsg,const string &filePath)> onDownloadResult; typedef std::function<void(ErrCode code,const string &errMsg,const string &filePath)> onDownloadResult;
HttpDownloader(); HttpDownloader();
virtual ~HttpDownloader(); virtual ~HttpDownloader();
//开始下载文件,默认断点续传方式下载 //开始下载文件,默认断点续传方式下载
void startDownload(const string &url,const string &filePath = "",bool bAppend = false, float timeOutSecond = 10 ); void startDownload(const string &url,const string &filePath = "",bool bAppend = false, float timeOutSecond = 10 );
void startDownload(const string &url,const onDownloadResult &cb,float timeOutSecond = 10){ void startDownload(const string &url,const onDownloadResult &cb,float timeOutSecond = 10){
setOnResult(cb); setOnResult(cb);
startDownload(url,"",false,timeOutSecond); startDownload(url,"",false,timeOutSecond);
} }
void setOnResult(const onDownloadResult &cb){ void setOnResult(const onDownloadResult &cb){
_onResult = cb; _onResult = cb;
} }
private: private:
int64_t onResponseHeader(const string &status,const HttpHeader &headers) override; int64_t onResponseHeader(const string &status,const HttpHeader &headers) override;
void onResponseBody(const char *buf,int64_t size,int64_t recvedSize,int64_t totalSize) override; void onResponseBody(const char *buf,int64_t size,int64_t recvedSize,int64_t totalSize) override;
void onResponseCompleted() override; void onResponseCompleted() override;
void onDisconnect(const SockException &ex) override; void onDisconnect(const SockException &ex) override;
void closeFile(); void closeFile();
private: private:
FILE *_saveFile = nullptr; FILE *_saveFile = nullptr;
string _filePath; string _filePath;
onDownloadResult _onResult; onDownloadResult _onResult;
bool _bDownloadSuccess = false; bool _bDownloadSuccess = false;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -45,51 +45,51 @@ class HttpSession: public TcpSession, ...@@ -45,51 +45,51 @@ class HttpSession: public TcpSession,
public HttpRequestSplitter, public HttpRequestSplitter,
public WebSocketSplitter { public WebSocketSplitter {
public: public:
typedef StrCaseMap KeyValue; typedef StrCaseMap KeyValue;
typedef HttpResponseInvokerImp HttpResponseInvoker; typedef HttpResponseInvokerImp HttpResponseInvoker;
friend class AsyncSender; friend class AsyncSender;
/** /**
* @param errMsg 如果为空,则代表鉴权通过,否则为错误提示 * @param errMsg 如果为空,则代表鉴权通过,否则为错误提示
* @param accessPath 运行或禁止访问的根目录 * @param accessPath 运行或禁止访问的根目录
* @param cookieLifeSecond 鉴权cookie有效期 * @param cookieLifeSecond 鉴权cookie有效期
**/ **/
typedef std::function<void(const string &errMsg,const string &accessPath, int cookieLifeSecond)> HttpAccessPathInvoker; typedef std::function<void(const string &errMsg,const string &accessPath, int cookieLifeSecond)> HttpAccessPathInvoker;
HttpSession(const Socket::Ptr &pSock); HttpSession(const Socket::Ptr &pSock);
virtual ~HttpSession(); virtual ~HttpSession();
virtual void onRecv(const Buffer::Ptr &) override; virtual void onRecv(const Buffer::Ptr &) override;
virtual void onError(const SockException &err) override; virtual void onError(const SockException &err) override;
virtual void onManager() override; virtual void onManager() override;
static string urlDecode(const string &str); static string urlDecode(const string &str);
protected: protected:
//FlvMuxer override //FlvMuxer override
void onWrite(const Buffer::Ptr &data) override ; void onWrite(const Buffer::Ptr &data) override ;
void onDetach() override; void onDetach() override;
std::shared_ptr<FlvMuxer> getSharedPtr() override; std::shared_ptr<FlvMuxer> getSharedPtr() override;
//HttpRequestSplitter override //HttpRequestSplitter override
int64_t onRecvHeader(const char *data,uint64_t len) override; int64_t onRecvHeader(const char *data,uint64_t len) override;
void onRecvContent(const char *data,uint64_t len) override; void onRecvContent(const char *data,uint64_t len) override;
/** /**
* 重载之用于处理不定长度的content * 重载之用于处理不定长度的content
* 这个函数可用于处理大文件上传、http-flv推流 * 这个函数可用于处理大文件上传、http-flv推流
* @param header http请求头 * @param header http请求头
* @param data content分片数据 * @param data content分片数据
* @param len content分片数据大小 * @param len content分片数据大小
* @param totalSize content总大小,如果为0则是不限长度content * @param totalSize content总大小,如果为0则是不限长度content
* @param recvedSize 已收数据大小 * @param recvedSize 已收数据大小
*/ */
virtual void onRecvUnlimitedContent(const Parser &header, virtual void onRecvUnlimitedContent(const Parser &header,
const char *data, const char *data,
uint64_t len, uint64_t len,
uint64_t totalSize, uint64_t totalSize,
uint64_t recvedSize){ uint64_t recvedSize){
shutdown(SockException(Err_shutdown,"http post content is too huge,default closed")); shutdown(SockException(Err_shutdown,"http post content is too huge,default closed"));
} }
/** /**
* websocket客户端连接上事件 * websocket客户端连接上事件
* @param header http头 * @param header http头
* @return true代表允许websocket连接,否则拒绝 * @return true代表允许websocket连接,否则拒绝
...@@ -99,31 +99,31 @@ protected: ...@@ -99,31 +99,31 @@ protected:
return false; return false;
} }
//WebSocketSplitter override //WebSocketSplitter override
/** /**
* 发送数据进行websocket协议打包后回调 * 发送数据进行websocket协议打包后回调
* @param buffer websocket协议数据 * @param buffer websocket协议数据
*/ */
void onWebSocketEncodeData(const Buffer::Ptr &buffer) override; void onWebSocketEncodeData(const Buffer::Ptr &buffer) override;
private: private:
void Handle_Req_GET(int64_t &content_len); void Handle_Req_GET(int64_t &content_len);
void Handle_Req_GET_l(int64_t &content_len, bool sendBody); void Handle_Req_GET_l(int64_t &content_len, bool sendBody);
void Handle_Req_POST(int64_t &content_len); void Handle_Req_POST(int64_t &content_len);
void Handle_Req_HEAD(int64_t &content_len); void Handle_Req_HEAD(int64_t &content_len);
bool checkLiveFlvStream(const function<void()> &cb = nullptr); bool checkLiveFlvStream(const function<void()> &cb = nullptr);
bool checkWebSocket(); bool checkWebSocket();
bool emitHttpEvent(bool doInvoke); bool emitHttpEvent(bool doInvoke);
void urlDecode(Parser &parser); void urlDecode(Parser &parser);
void sendNotFound(bool bClose); void sendNotFound(bool bClose);
void sendResponse(const char *pcStatus, bool bClose, const char *pcContentType = nullptr, void sendResponse(const char *pcStatus, bool bClose, const char *pcContentType = nullptr,
const HttpSession::KeyValue &header = HttpSession::KeyValue(), const HttpSession::KeyValue &header = HttpSession::KeyValue(),
const HttpBody::Ptr &body = nullptr,bool is_http_flv = false); const HttpBody::Ptr &body = nullptr,bool is_http_flv = false);
//设置socket标志 //设置socket标志
void setSocketFlags(); void setSocketFlags();
private: private:
string _origin; string _origin;
Parser _parser; Parser _parser;
Ticker _ticker; Ticker _ticker;
//消耗的总流量 //消耗的总流量
...@@ -132,8 +132,8 @@ private: ...@@ -132,8 +132,8 @@ private:
MediaInfo _mediaInfo; MediaInfo _mediaInfo;
//处理content数据的callback //处理content数据的callback
function<bool (const char *data,uint64_t len) > _contentCallBack; function<bool (const char *data,uint64_t len) > _contentCallBack;
bool _flv_over_websocket = false; bool _flv_over_websocket = false;
bool _is_flv_stream = false; bool _is_flv_stream = false;
}; };
......
...@@ -36,76 +36,76 @@ namespace mediakit { ...@@ -36,76 +36,76 @@ namespace mediakit {
//////////////////////////通用/////////////////////// //////////////////////////通用///////////////////////
void UTF8ToUnicode(wchar_t* pOut, const char *pText) void UTF8ToUnicode(wchar_t* pOut, const char *pText)
{ {
char* uchar = (char *)pOut; char* uchar = (char *)pOut;
uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F); uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F); uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
return; return;
} }
void UnicodeToUTF8(char* pOut, const wchar_t* pText) void UnicodeToUTF8(char* pOut, const wchar_t* pText)
{ {
// 注意 WCHAR高低字的顺序,低字节在前,高字节在后 // 注意 WCHAR高低字的顺序,低字节在前,高字节在后
const char* pchar = (const char *)pText; const char* pchar = (const char *)pText;
pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4)); pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6); pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
pOut[2] = (0x80 | (pchar[0] & 0x3F)); pOut[2] = (0x80 | (pchar[0] & 0x3F));
return; return;
} }
char CharToInt(char ch) char CharToInt(char ch)
{ {
if (ch >= '0' && ch <= '9')return (char)(ch - '0'); if (ch >= '0' && ch <= '9')return (char)(ch - '0');
if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10); if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10); if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
return -1; return -1;
} }
char StrToBin(const char *str) char StrToBin(const char *str)
{ {
char tempWord[2]; char tempWord[2];
char chn; char chn;
tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011 tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011
tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000 tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000
chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000 chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000
return chn; return chn;
} }
string strCoding::UrlEncode(const string &str) { string strCoding::UrlEncode(const string &str) {
string out; string out;
size_t len = str.size(); size_t len = str.size();
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
char ch = str[i]; char ch = str[i];
if (isalnum((uint8_t)ch)) { if (isalnum((uint8_t)ch)) {
out.push_back(ch); out.push_back(ch);
}else { }else {
char buf[4]; char buf[4];
sprintf(buf, "%%%X%X", (uint8_t)ch >> 4,(uint8_t)ch & 0x0F); sprintf(buf, "%%%X%X", (uint8_t)ch >> 4,(uint8_t)ch & 0x0F);
out.append(buf); out.append(buf);
} }
} }
return out; return out;
} }
string strCoding::UrlDecode(const string &str) { string strCoding::UrlDecode(const string &str) {
string output = ""; string output = "";
char tmp[2]; char tmp[2];
int i = 0, len = str.length(); int i = 0, len = str.length();
while (i < len) { while (i < len) {
if (str[i] == '%') { if (str[i] == '%') {
if(i > len - 3){ if(i > len - 3){
//防止内存溢出 //防止内存溢出
break; break;
} }
tmp[0] = str[i + 1]; tmp[0] = str[i + 1];
tmp[1] = str[i + 2]; tmp[1] = str[i + 2];
output += StrToBin(tmp); output += StrToBin(tmp);
i = i + 3; i = i + 3;
} else if (str[i] == '+') { } else if (str[i] == '+') {
output += ' '; output += ' ';
i++; i++;
} else { } else {
output += str[i]; output += str[i];
i++; i++;
} }
} }
return output; return output;
} }
...@@ -113,73 +113,73 @@ string strCoding::UrlDecode(const string &str) { ...@@ -113,73 +113,73 @@ string strCoding::UrlDecode(const string &str) {
#if defined(_WIN32) #if defined(_WIN32)
void UnicodeToGB2312(char* pOut, wchar_t uData) void UnicodeToGB2312(char* pOut, wchar_t uData)
{ {
WideCharToMultiByte(CP_ACP, NULL, &uData, 1, pOut, sizeof(wchar_t), NULL, NULL); WideCharToMultiByte(CP_ACP, NULL, &uData, 1, pOut, sizeof(wchar_t), NULL, NULL);
} }
void Gb2312ToUnicode(wchar_t* pOut, const char *gbBuffer) void Gb2312ToUnicode(wchar_t* pOut, const char *gbBuffer)
{ {
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbBuffer, 2, pOut, 1); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbBuffer, 2, pOut, 1);
} }
string strCoding::UTF8ToGB2312(const string &str) { string strCoding::UTF8ToGB2312(const string &str) {
auto len = str.size(); auto len = str.size();
auto pText = str.data(); auto pText = str.data();
char Ctemp[4] = {0}; char Ctemp[4] = {0};
char *pOut = new char[len + 1]; char *pOut = new char[len + 1];
memset(pOut, 0, len + 1); memset(pOut, 0, len + 1);
int i = 0, j = 0; int i = 0, j = 0;
while (i < len) while (i < len)
{ {
if (pText[i] >= 0) if (pText[i] >= 0)
{ {
pOut[j++] = pText[i++]; pOut[j++] = pText[i++];
} }
else else
{ {
wchar_t Wtemp; wchar_t Wtemp;
UTF8ToUnicode(&Wtemp, pText + i); UTF8ToUnicode(&Wtemp, pText + i);
UnicodeToGB2312(Ctemp, Wtemp); UnicodeToGB2312(Ctemp, Wtemp);
pOut[j] = Ctemp[0]; pOut[j] = Ctemp[0];
pOut[j + 1] = Ctemp[1]; pOut[j + 1] = Ctemp[1];
i += 3; i += 3;
j += 2; j += 2;
} }
} }
string ret = pOut; string ret = pOut;
delete[] pOut; delete[] pOut;
return ret; return ret;
} }
string strCoding::GB2312ToUTF8(const string &str) { string strCoding::GB2312ToUTF8(const string &str) {
auto len = str.size(); auto len = str.size();
auto pText = str.data(); auto pText = str.data();
char buf[4] = { 0 }; char buf[4] = { 0 };
int nLength = len * 3; int nLength = len * 3;
char* pOut = new char[nLength]; char* pOut = new char[nLength];
memset(pOut, 0, nLength); memset(pOut, 0, nLength);
int i = 0, j = 0; int i = 0, j = 0;
while (i < len) while (i < len)
{ {
//如果是英文直接复制就可以 //如果是英文直接复制就可以
if (*(pText + i) >= 0) if (*(pText + i) >= 0)
{ {
pOut[j++] = pText[i++]; pOut[j++] = pText[i++];
} }
else else
{ {
wchar_t pbuffer; wchar_t pbuffer;
Gb2312ToUnicode(&pbuffer, pText + i); Gb2312ToUnicode(&pbuffer, pText + i);
UnicodeToUTF8(buf, &pbuffer); UnicodeToUTF8(buf, &pbuffer);
pOut[j] = buf[0]; pOut[j] = buf[0];
pOut[j + 1] = buf[1]; pOut[j + 1] = buf[1];
pOut[j + 2] = buf[2]; pOut[j + 2] = buf[2];
j += 3; j += 3;
i += 2; i += 2;
} }
} }
string ret = pOut; string ret = pOut;
delete[] pOut; delete[] pOut;
return ret; return ret;
} }
#endif//defined(_WIN32) #endif//defined(_WIN32)
......
...@@ -36,15 +36,15 @@ namespace mediakit { ...@@ -36,15 +36,15 @@ namespace mediakit {
class strCoding { class strCoding {
public: public:
static string UrlEncode(const string &str); //urlutf8 编码 static string UrlEncode(const string &str); //urlutf8 编码
static string UrlDecode(const string &str); //urlutf8解码 static string UrlDecode(const string &str); //urlutf8解码
#if defined(_WIN32) #if defined(_WIN32)
static string UTF8ToGB2312(const string &str);//utf_8转为gb2312 static string UTF8ToGB2312(const string &str);//utf_8转为gb2312
static string GB2312ToUTF8(const string &str); //gb2312 转utf_8 static string GB2312ToUTF8(const string &str); //gb2312 转utf_8
#endif//defined(_WIN32) #endif//defined(_WIN32)
private: private:
strCoding(void); strCoding(void);
virtual ~strCoding(void); virtual ~strCoding(void);
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -42,29 +42,29 @@ MediaPlayer::MediaPlayer(const EventPoller::Ptr &poller) { ...@@ -42,29 +42,29 @@ MediaPlayer::MediaPlayer(const EventPoller::Ptr &poller) {
MediaPlayer::~MediaPlayer() { MediaPlayer::~MediaPlayer() {
} }
void MediaPlayer::play(const string &strUrl) { void MediaPlayer::play(const string &strUrl) {
_delegate = PlayerBase::createPlayer(_poller,strUrl); _delegate = PlayerBase::createPlayer(_poller,strUrl);
_delegate->setOnShutdown(_shutdownCB); _delegate->setOnShutdown(_shutdownCB);
_delegate->setOnPlayResult(_playResultCB); _delegate->setOnPlayResult(_playResultCB);
_delegate->setOnResume(_resumeCB); _delegate->setOnResume(_resumeCB);
_delegate->setMediaSouce(_pMediaSrc); _delegate->setMediaSouce(_pMediaSrc);
_delegate->mINI::operator=(*this); _delegate->mINI::operator=(*this);
_delegate->play(strUrl); _delegate->play(strUrl);
} }
EventPoller::Ptr MediaPlayer::getPoller(){ EventPoller::Ptr MediaPlayer::getPoller(){
return _poller; return _poller;
} }
void MediaPlayer::pause(bool bPause) { void MediaPlayer::pause(bool bPause) {
if (_delegate) { if (_delegate) {
_delegate->pause(bPause); _delegate->pause(bPause);
} }
} }
void MediaPlayer::teardown() { void MediaPlayer::teardown() {
if (_delegate) { if (_delegate) {
_delegate->teardown(); _delegate->teardown();
} }
} }
......
...@@ -39,16 +39,16 @@ namespace mediakit { ...@@ -39,16 +39,16 @@ namespace mediakit {
class MediaPlayer : public PlayerImp<PlayerBase,PlayerBase> { class MediaPlayer : public PlayerImp<PlayerBase,PlayerBase> {
public: public:
typedef std::shared_ptr<MediaPlayer> Ptr; typedef std::shared_ptr<MediaPlayer> Ptr;
MediaPlayer(const EventPoller::Ptr &poller = nullptr); MediaPlayer(const EventPoller::Ptr &poller = nullptr);
virtual ~MediaPlayer(); virtual ~MediaPlayer();
void play(const string &strUrl) override; void play(const string &strUrl) override;
void pause(bool bPause) override; void pause(bool bPause) override;
void teardown() override; void teardown() override;
EventPoller::Ptr getPoller(); EventPoller::Ptr getPoller();
private: private:
EventPoller::Ptr _poller; EventPoller::Ptr _poller;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -33,92 +33,92 @@ using namespace toolkit; ...@@ -33,92 +33,92 @@ using namespace toolkit;
namespace mediakit { namespace mediakit {
PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const string &strUrl) { PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const string &strUrl) {
static auto releasePlayer = [](PlayerBase *ptr){ static auto releasePlayer = [](PlayerBase *ptr){
onceToken token(nullptr,[&](){ onceToken token(nullptr,[&](){
delete ptr; delete ptr;
}); });
ptr->teardown(); ptr->teardown();
}; };
string prefix = FindField(strUrl.data(), NULL, "://"); string prefix = FindField(strUrl.data(), NULL, "://");
if (strcasecmp("rtsps",prefix.data()) == 0) { if (strcasecmp("rtsps",prefix.data()) == 0) {
return PlayerBase::Ptr(new TcpClientWithSSL<RtspPlayerImp>(poller),releasePlayer); return PlayerBase::Ptr(new TcpClientWithSSL<RtspPlayerImp>(poller),releasePlayer);
} }
if (strcasecmp("rtsp",prefix.data()) == 0) { if (strcasecmp("rtsp",prefix.data()) == 0) {
return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer);
} }
if (strcasecmp("rtmps",prefix.data()) == 0) { if (strcasecmp("rtmps",prefix.data()) == 0) {
return PlayerBase::Ptr(new TcpClientWithSSL<RtmpPlayerImp>(poller),releasePlayer); return PlayerBase::Ptr(new TcpClientWithSSL<RtmpPlayerImp>(poller),releasePlayer);
} }
if (strcasecmp("rtmp",prefix.data()) == 0) { if (strcasecmp("rtmp",prefix.data()) == 0) {
return PlayerBase::Ptr(new RtmpPlayerImp(poller),releasePlayer); return PlayerBase::Ptr(new RtmpPlayerImp(poller),releasePlayer);
} }
return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer);
} }
PlayerBase::PlayerBase() { PlayerBase::PlayerBase() {
this->mINI::operator[](kTimeoutMS) = 10000; this->mINI::operator[](kTimeoutMS) = 10000;
this->mINI::operator[](kMediaTimeoutMS) = 5000; this->mINI::operator[](kMediaTimeoutMS) = 5000;
this->mINI::operator[](kBeatIntervalMS) = 5000; this->mINI::operator[](kBeatIntervalMS) = 5000;
this->mINI::operator[](kMaxAnalysisMS) = 5000; this->mINI::operator[](kMaxAnalysisMS) = 5000;
} }
///////////////////////////Demuxer////////////////////////////// ///////////////////////////Demuxer//////////////////////////////
bool Demuxer::isInited(int analysisMs) { bool Demuxer::isInited(int analysisMs) {
if(analysisMs && _ticker.createdTime() > analysisMs){ if(analysisMs && _ticker.createdTime() > analysisMs){
//analysisMs毫秒后强制初始化完毕 //analysisMs毫秒后强制初始化完毕
return true; return true;
} }
if (_videoTrack && !_videoTrack->ready()) { if (_videoTrack && !_videoTrack->ready()) {
//视频未准备好 //视频未准备好
return false; return false;
} }
if (_audioTrack && !_audioTrack->ready()) { if (_audioTrack && !_audioTrack->ready()) {
//音频未准备好 //音频未准备好
return false; return false;
} }
return true; return true;
} }
vector<Track::Ptr> Demuxer::getTracks(bool trackReady) const { vector<Track::Ptr> Demuxer::getTracks(bool trackReady) const {
vector<Track::Ptr> ret; vector<Track::Ptr> ret;
if(_videoTrack){ if(_videoTrack){
if(trackReady){ if(trackReady){
if(_videoTrack->ready()){ if(_videoTrack->ready()){
ret.emplace_back(_videoTrack); ret.emplace_back(_videoTrack);
} }
}else{ }else{
ret.emplace_back(_videoTrack); ret.emplace_back(_videoTrack);
} }
} }
if(_audioTrack){ if(_audioTrack){
if(trackReady){ if(trackReady){
if(_audioTrack->ready()){ if(_audioTrack->ready()){
ret.emplace_back(_audioTrack); ret.emplace_back(_audioTrack);
} }
}else{ }else{
ret.emplace_back(_audioTrack); ret.emplace_back(_audioTrack);
} }
} }
return std::move(ret); return std::move(ret);
} }
float Demuxer::getDuration() const { float Demuxer::getDuration() const {
return _fDuration; return _fDuration;
} }
void Demuxer::onAddTrack(const Track::Ptr &track){ void Demuxer::onAddTrack(const Track::Ptr &track){
if(_listener){ if(_listener){
_listener->onAddTrack(track); _listener->onAddTrack(track);
} }
} }
void Demuxer::setTrackListener(Demuxer::Listener *listener) { void Demuxer::setTrackListener(Demuxer::Listener *listener) {
_listener = listener; _listener = listener;
} }
} /* namespace mediakit */ } /* namespace mediakit */
...@@ -43,59 +43,59 @@ namespace mediakit { ...@@ -43,59 +43,59 @@ namespace mediakit {
class DemuxerBase : public TrackSource{ class DemuxerBase : public TrackSource{
public: public:
typedef std::shared_ptr<DemuxerBase> Ptr; typedef std::shared_ptr<DemuxerBase> Ptr;
/** /**
* 获取节目总时长,单位秒 * 获取节目总时长,单位秒
* @return * @return
*/ */
virtual float getDuration() const { return 0;} virtual float getDuration() const { return 0;}
/** /**
* 是否初始化完毕,完毕后方可调用getTrack方法 * 是否初始化完毕,完毕后方可调用getTrack方法
* @param analysisMs 数据流最大分析时间 单位毫秒 * @param analysisMs 数据流最大分析时间 单位毫秒
* @return * @return
*/ */
virtual bool isInited(int analysisMs) { return true; } virtual bool isInited(int analysisMs) { return true; }
}; };
class PlayerBase : public DemuxerBase, public mINI{ class PlayerBase : public DemuxerBase, public mINI{
public: public:
typedef std::shared_ptr<PlayerBase> Ptr; typedef std::shared_ptr<PlayerBase> Ptr;
static Ptr createPlayer(const EventPoller::Ptr &poller,const string &strUrl); static Ptr createPlayer(const EventPoller::Ptr &poller,const string &strUrl);
PlayerBase(); PlayerBase();
virtual ~PlayerBase(){} virtual ~PlayerBase(){}
/** /**
* 开始播放 * 开始播放
* @param strUrl 视频url,支持rtsp/rtmp * @param strUrl 视频url,支持rtsp/rtmp
*/ */
virtual void play(const string &strUrl) {} virtual void play(const string &strUrl) {}
/** /**
* 暂停或恢复 * 暂停或恢复
* @param bPause * @param bPause
*/ */
virtual void pause(bool bPause) {} virtual void pause(bool bPause) {}
/** /**
* 中断播放 * 中断播放
*/ */
virtual void teardown() {} virtual void teardown() {}
/** /**
* 设置异常中断回调 * 设置异常中断回调
* @param cb * @param cb
*/ */
virtual void setOnShutdown( const function<void(const SockException &)> &cb) {} virtual void setOnShutdown( const function<void(const SockException &)> &cb) {}
/** /**
* 设置播放结果回调 * 设置播放结果回调
* @param cb * @param cb
*/ */
virtual void setOnPlayResult( const function<void(const SockException &ex)> &cb) {} virtual void setOnPlayResult( const function<void(const SockException &ex)> &cb) {}
/** /**
* 设置播放恢复回调 * 设置播放恢复回调
...@@ -103,10 +103,10 @@ public: ...@@ -103,10 +103,10 @@ public:
*/ */
virtual void setOnResume( const function<void()> &cb) {} virtual void setOnResume( const function<void()> &cb) {}
/** /**
* 获取播放进度,取值 0.0 ~ 1.0 * 获取播放进度,取值 0.0 ~ 1.0
* @return * @return
*/ */
virtual float getProgress() const { return 0;} virtual float getProgress() const { return 0;}
/** /**
...@@ -126,7 +126,7 @@ public: ...@@ -126,7 +126,7 @@ public:
* @param trackType 音频或视频,TrackInvalid时为总丢包率 * @param trackType 音频或视频,TrackInvalid时为总丢包率
* @return * @return
*/ */
virtual float getPacketLossRate(TrackType trackType) const {return 0; } virtual float getPacketLossRate(TrackType trackType) const {return 0; }
/** /**
* 获取所有track * 获取所有track
...@@ -146,24 +146,24 @@ protected: ...@@ -146,24 +146,24 @@ protected:
template<typename Parent,typename Delegate> template<typename Parent,typename Delegate>
class PlayerImp : public Parent { class PlayerImp : public Parent {
public: 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);
} }
_playResultCB = cb; _playResultCB = cb;
} }
void setOnResume(const function<void()> &cb) override { void setOnResume(const function<void()> &cb) override {
if (_delegate) { if (_delegate) {
...@@ -178,12 +178,12 @@ public: ...@@ -178,12 +178,12 @@ public:
} }
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();
...@@ -198,95 +198,95 @@ public: ...@@ -198,95 +198,95 @@ public:
} }
void setMediaSouce(const MediaSource::Ptr & src) override { void setMediaSouce(const MediaSource::Ptr & src) override {
if (_delegate) { if (_delegate) {
_delegate->setMediaSouce(src); _delegate->setMediaSouce(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);
} }
protected: protected:
void onShutdown(const SockException &ex) override { void onShutdown(const SockException &ex) override {
if (_shutdownCB) { if (_shutdownCB) {
_shutdownCB(ex); _shutdownCB(ex);
_shutdownCB = nullptr; _shutdownCB = nullptr;
} }
} }
void onPlayResult(const SockException &ex) override { void onPlayResult(const SockException &ex) override {
if(_playResultCB) { if(_playResultCB) {
_playResultCB(ex); _playResultCB(ex);
_playResultCB = nullptr; _playResultCB = nullptr;
} }
} }
void onResume() override{ void onResume() override{
if(_resumeCB){ if(_resumeCB){
_resumeCB(); _resumeCB();
} }
} }
protected: protected:
function<void(const SockException &ex)> _shutdownCB; function<void(const SockException &ex)> _shutdownCB;
function<void(const SockException &ex)> _playResultCB; function<void(const SockException &ex)> _playResultCB;
function<void()> _resumeCB; function<void()> _resumeCB;
std::shared_ptr<Delegate> _delegate; std::shared_ptr<Delegate> _delegate;
MediaSource::Ptr _pMediaSrc; MediaSource::Ptr _pMediaSrc;
}; };
class Demuxer : public PlayerBase{ class Demuxer : public PlayerBase{
public: public:
class Listener{ class Listener{
public: public:
Listener() = default; Listener() = default;
virtual ~Listener() = default; virtual ~Listener() = default;
virtual void onAddTrack(const Track::Ptr &track) = 0; virtual void onAddTrack(const Track::Ptr &track) = 0;
}; };
Demuxer(){}; Demuxer(){};
virtual ~Demuxer(){}; virtual ~Demuxer(){};
/** /**
* 返回是否完成初始化完毕 * 返回是否完成初始化完毕
* 在构造RtspDemuxer对象时有些rtsp的sdp不包含sps pps信息 * 在构造RtspDemuxer对象时有些rtsp的sdp不包含sps pps信息
* 所以要等待接收到到sps的rtp包后才能完成 * 所以要等待接收到到sps的rtp包后才能完成
* *
* 在构造RtmpDemuxer对象时是无法获取sps pps aac_cfg等这些信息, * 在构造RtmpDemuxer对象时是无法获取sps pps aac_cfg等这些信息,
* 所以要调用inputRtmp后才会获取到这些信息,这时才初始化成功 * 所以要调用inputRtmp后才会获取到这些信息,这时才初始化成功
* @param analysisMs 数据流最大分析时间 单位毫秒 * @param analysisMs 数据流最大分析时间 单位毫秒
* @return * @return
*/ */
bool isInited(int analysisMs) override; bool isInited(int analysisMs) override;
/** /**
* 获取所有Track * 获取所有Track
* @return 所有Track * @return 所有Track
*/ */
vector<Track::Ptr> getTracks(bool trackReady = true) const override; vector<Track::Ptr> getTracks(bool trackReady = true) const override;
/** /**
* 获取节目总时长 * 获取节目总时长
* @return 节目总时长,单位秒 * @return 节目总时长,单位秒
*/ */
float getDuration() const override; float getDuration() const override;
/** /**
* 设置track监听器 * 设置track监听器
*/ */
void setTrackListener(Listener *listener); void setTrackListener(Listener *listener);
protected: protected:
void onAddTrack(const Track::Ptr &track); void onAddTrack(const Track::Ptr &track);
protected: protected:
Listener *_listener = nullptr; Listener *_listener = nullptr;
AudioTrack::Ptr _audioTrack; AudioTrack::Ptr _audioTrack;
VideoTrack::Ptr _videoTrack; VideoTrack::Ptr _videoTrack;
Ticker _ticker; Ticker _ticker;
float _fDuration = 0; float _fDuration = 0;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -39,24 +39,24 @@ using namespace toolkit; ...@@ -39,24 +39,24 @@ using namespace toolkit;
namespace mediakit { namespace mediakit {
class PlayerProxy :public MediaPlayer, class PlayerProxy :public MediaPlayer,
public std::enable_shared_from_this<PlayerProxy> , public std::enable_shared_from_this<PlayerProxy> ,
public MediaSourceEvent{ public MediaSourceEvent{
public: public:
typedef std::shared_ptr<PlayerProxy> Ptr; typedef std::shared_ptr<PlayerProxy> Ptr;
//如果iRetryCount<0,则一直重试播放;否则重试iRetryCount次数 //如果iRetryCount<0,则一直重试播放;否则重试iRetryCount次数
//默认一直重试 //默认一直重试
PlayerProxy(const string &strVhost, PlayerProxy(const string &strVhost,
const string &strApp, const string &strApp,
const string &strSrc, const string &strSrc,
bool bEnableRtsp = true, bool bEnableRtsp = true,
bool bEnableRtmp = true, bool bEnableRtmp = true,
bool bEnableHls = true, bool bEnableHls = true,
bool bEnableMp4 = false, bool bEnableMp4 = false,
int iRetryCount = -1, int iRetryCount = -1,
const EventPoller::Ptr &poller = nullptr); const EventPoller::Ptr &poller = nullptr);
virtual ~PlayerProxy(); virtual ~PlayerProxy();
/** /**
* 设置play结果回调,只触发一次;在play执行之前有效 * 设置play结果回调,只触发一次;在play执行之前有效
...@@ -81,19 +81,19 @@ public: ...@@ -81,19 +81,19 @@ public:
*/ */
int totalReaderCount() ; int totalReaderCount() ;
private: private:
//MediaSourceEvent override //MediaSourceEvent override
bool close(MediaSource &sender,bool force) override; bool close(MediaSource &sender,bool force) override;
void onNoneReader(MediaSource &sender) override; void onNoneReader(MediaSource &sender) override;
int totalReaderCount(MediaSource &sender) override; int totalReaderCount(MediaSource &sender) override;
void rePlay(const string &strUrl,int iFailedCnt); void rePlay(const string &strUrl,int iFailedCnt);
void onPlaySuccess(); void onPlaySuccess();
private: private:
bool _bEnableRtsp; bool _bEnableRtsp;
bool _bEnableRtmp; bool _bEnableRtmp;
bool _bEnableHls; bool _bEnableHls;
bool _bEnableMp4; bool _bEnableMp4;
int _iRetryCount; int _iRetryCount;
MultiMediaSourceMuxer::Ptr _mediaMuxer; MultiMediaSourceMuxer::Ptr _mediaMuxer;
string _strVhost; string _strVhost;
string _strApp; string _strApp;
string _strSrc; string _strSrc;
......
...@@ -44,16 +44,16 @@ public: ...@@ -44,16 +44,16 @@ public:
virtual ~HlsMediaSource() = default; virtual ~HlsMediaSource() = default;
/** /**
* 获取媒体源的环形缓冲 * 获取媒体源的环形缓冲
*/ */
const RingType::Ptr &getRing() const { const RingType::Ptr &getRing() const {
return _ring; return _ring;
} }
/** /**
* 获取播放器个数 * 获取播放器个数
* @return * @return
*/ */
int readerCount() override { int readerCount() override {
return _readerCount.load(); return _readerCount.load();
} }
......
...@@ -192,7 +192,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { ...@@ -192,7 +192,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) {
return; return;
} }
struct mpeg4_avc_t avc = {0}; struct mpeg4_avc_t avc = {0};
string sps_pps = string("\x00\x00\x00\x01", 4) + h264_track->getSps() + string sps_pps = string("\x00\x00\x00\x01", 4) + h264_track->getSps() +
string("\x00\x00\x00\x01", 4) + h264_track->getPps(); string("\x00\x00\x00\x01", 4) + h264_track->getPps();
h264_annexbtomp4(&avc, sps_pps.data(), sps_pps.size(), NULL, 0, NULL, NULL); h264_annexbtomp4(&avc, sps_pps.data(), sps_pps.size(), NULL, 0, NULL, NULL);
...@@ -230,7 +230,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { ...@@ -230,7 +230,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) {
return; return;
} }
struct mpeg4_hevc_t hevc = {0}; struct mpeg4_hevc_t hevc = {0};
string vps_sps_pps = string("\x00\x00\x00\x01", 4) + h265_track->getVps() + string vps_sps_pps = string("\x00\x00\x00\x01", 4) + h265_track->getVps() +
string("\x00\x00\x00\x01", 4) + h265_track->getSps() + string("\x00\x00\x00\x01", 4) + h265_track->getSps() +
string("\x00\x00\x00\x01", 4) + h265_track->getPps(); string("\x00\x00\x00\x01", 4) + h265_track->getPps();
......
...@@ -39,91 +39,91 @@ namespace mediakit { ...@@ -39,91 +39,91 @@ namespace mediakit {
class MP4Reader : public std::enable_shared_from_this<MP4Reader> ,public MediaSourceEvent{ class MP4Reader : public std::enable_shared_from_this<MP4Reader> ,public MediaSourceEvent{
public: public:
typedef std::shared_ptr<MP4Reader> Ptr; typedef std::shared_ptr<MP4Reader> Ptr;
virtual ~MP4Reader(); virtual ~MP4Reader();
/** /**
* 流化一个mp4文件,使之转换成RtspMediaSource和RtmpMediaSource * 流化一个mp4文件,使之转换成RtspMediaSource和RtmpMediaSource
* @param strVhost 虚拟主机 * @param strVhost 虚拟主机
* @param strApp 应用名 * @param strApp 应用名
* @param strId 流id * @param strId 流id
* @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 * @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件
*/ */
MP4Reader(const string &strVhost,const string &strApp, const string &strId,const string &filePath = ""); MP4Reader(const string &strVhost,const string &strApp, const string &strId,const string &filePath = "");
/** /**
* 开始流化MP4文件,需要指出的是,MP4Reader对象一经过调用startReadMP4方法,它的强引用会自持有, * 开始流化MP4文件,需要指出的是,MP4Reader对象一经过调用startReadMP4方法,它的强引用会自持有,
* 意思是在文件流化结束之前或中断之前,MP4Reader对象是不会被销毁的(不管有没有被外部对象持有) * 意思是在文件流化结束之前或中断之前,MP4Reader对象是不会被销毁的(不管有没有被外部对象持有)
*/ */
void startReadMP4(); void startReadMP4();
/** /**
* 自动生成MP4Reader对象然后查找相关的MediaSource对象 * 自动生成MP4Reader对象然后查找相关的MediaSource对象
* @param strSchema 协议名 * @param strSchema 协议名
* @param strVhost 虚拟主机 * @param strVhost 虚拟主机
* @param strApp 应用名 * @param strApp 应用名
* @param strId 流id * @param strId 流id
* @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 * @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件
* @param checkApp 是否检查app,防止服务器上文件被乱访问 * @param checkApp 是否检查app,防止服务器上文件被乱访问
* @return MediaSource * @return MediaSource
*/ */
static MediaSource::Ptr onMakeMediaSource(const string &strSchema, static MediaSource::Ptr onMakeMediaSource(const string &strSchema,
const string &strVhost, const string &strVhost,
const string &strApp, const string &strApp,
const string &strId, const string &strId,
const string &filePath = "", const string &filePath = "",
bool checkApp = true); bool checkApp = true);
private: private:
//MediaSourceEvent override //MediaSourceEvent override
bool seekTo(MediaSource &sender,uint32_t ui32Stamp) override; bool seekTo(MediaSource &sender,uint32_t ui32Stamp) override;
bool close(MediaSource &sender,bool force) override; bool close(MediaSource &sender,bool force) override;
void onNoneReader(MediaSource &sender) override; void onNoneReader(MediaSource &sender) override;
int totalReaderCount(MediaSource &sender) override; int totalReaderCount(MediaSource &sender) override;
#ifdef ENABLE_MP4V2 #ifdef ENABLE_MP4V2
void seek(uint32_t iSeekTime,bool bReStart = true); void seek(uint32_t iSeekTime,bool bReStart = true);
inline void setSeekTime(uint32_t iSeekTime); inline void setSeekTime(uint32_t iSeekTime);
inline uint32_t getVideoCurrentTime(); inline uint32_t getVideoCurrentTime();
inline MP4SampleId getVideoSampleId(int iTimeInc = 0); inline MP4SampleId getVideoSampleId(int iTimeInc = 0);
inline MP4SampleId getAudioSampleId(int iTimeInc = 0); inline MP4SampleId getAudioSampleId(int iTimeInc = 0);
bool readSample(int iTimeInc, bool justSeekSyncFrame); bool readSample(int iTimeInc, bool justSeekSyncFrame);
inline bool readVideoSample(int iTimeInc,bool justSeekSyncFrame); inline bool readVideoSample(int iTimeInc,bool justSeekSyncFrame);
inline bool readAudioSample(int iTimeInc,bool justSeekSyncFrame); inline bool readAudioSample(int iTimeInc,bool justSeekSyncFrame);
inline void writeH264(uint8_t *pucData,int iLen,uint32_t dts,uint32_t pts); inline void writeH264(uint8_t *pucData,int iLen,uint32_t dts,uint32_t pts);
inline void writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp); inline void writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp);
private: private:
MP4FileHandle _hMP4File = MP4_INVALID_FILE_HANDLE; MP4FileHandle _hMP4File = MP4_INVALID_FILE_HANDLE;
MP4TrackId _video_trId = MP4_INVALID_TRACK_ID; MP4TrackId _video_trId = MP4_INVALID_TRACK_ID;
uint32_t _video_ms = 0; uint32_t _video_ms = 0;
uint32_t _video_num_samples = 0; uint32_t _video_num_samples = 0;
uint32_t _video_sample_max_size = 0; uint32_t _video_sample_max_size = 0;
uint32_t _video_width = 0; uint32_t _video_width = 0;
uint32_t _video_height = 0; uint32_t _video_height = 0;
uint32_t _video_framerate = 0; uint32_t _video_framerate = 0;
string _strPps; string _strPps;
string _strSps; string _strSps;
bool _bSyncSample = false; bool _bSyncSample = false;
MP4TrackId _audio_trId = MP4_INVALID_TRACK_ID; MP4TrackId _audio_trId = MP4_INVALID_TRACK_ID;
uint32_t _audio_ms = 0; uint32_t _audio_ms = 0;
uint32_t _audio_num_samples = 0; uint32_t _audio_num_samples = 0;
uint32_t _audio_sample_max_size = 0; uint32_t _audio_sample_max_size = 0;
uint32_t _audio_sample_rate = 0; uint32_t _audio_sample_rate = 0;
uint32_t _audio_num_channels = 0; uint32_t _audio_num_channels = 0;
string _strAacCfg; string _strAacCfg;
AACFrame _adts; AACFrame _adts;
int _iDuration = 0; int _iDuration = 0;
MultiMediaSourceMuxer::Ptr _mediaMuxer; MultiMediaSourceMuxer::Ptr _mediaMuxer;
MP4SampleId _video_current = 0; MP4SampleId _video_current = 0;
MP4SampleId _audio_current = 0; MP4SampleId _audio_current = 0;
std::shared_ptr<uint8_t> _pcVideoSample; std::shared_ptr<uint8_t> _pcVideoSample;
int _iSeekTime = 0 ; int _iSeekTime = 0 ;
Ticker _ticker; Ticker _ticker;
Ticker _alive; Ticker _alive;
recursive_mutex _mtx; recursive_mutex _mtx;
Timer::Ptr _timer; Timer::Ptr _timer;
EventPoller::Ptr _poller; EventPoller::Ptr _poller;
#endif //ENABLE_MP4V2 #endif //ENABLE_MP4V2
}; };
......
...@@ -36,31 +36,31 @@ using namespace toolkit; ...@@ -36,31 +36,31 @@ using namespace toolkit;
namespace mediakit { namespace mediakit {
MP4Recorder::MP4Recorder(const string& strPath, MP4Recorder::MP4Recorder(const string& strPath,
const string &strVhost, const string &strVhost,
const string &strApp, const string &strApp,
const string &strStreamId) { const string &strStreamId) {
_strPath = strPath; _strPath = strPath;
/////record 业务逻辑////// /////record 业务逻辑//////
_info.strAppName = strApp; _info.strAppName = strApp;
_info.strStreamId = strStreamId; _info.strStreamId = strStreamId;
_info.strVhost = strVhost; _info.strVhost = strVhost;
_info.strFolder = strPath; _info.strFolder = strPath;
} }
MP4Recorder::~MP4Recorder() { MP4Recorder::~MP4Recorder() {
closeFile(); closeFile();
} }
void MP4Recorder::createFile() { void MP4Recorder::createFile() {
closeFile(); closeFile();
auto strDate = getTimeStr("%Y-%m-%d"); auto strDate = getTimeStr("%Y-%m-%d");
auto strTime = getTimeStr("%H-%M-%S"); auto strTime = getTimeStr("%H-%M-%S");
auto strFileTmp = _strPath + strDate + "/." + strTime + ".mp4"; auto strFileTmp = _strPath + strDate + "/." + strTime + ".mp4";
auto strFile = _strPath + strDate + "/" + strTime + ".mp4"; auto strFile = _strPath + strDate + "/" + strTime + ".mp4";
/////record 业务逻辑////// /////record 业务逻辑//////
_info.ui64StartedTime = ::time(NULL); _info.ui64StartedTime = ::time(NULL);
_info.strFileName = strTime + ".mp4"; _info.strFileName = strTime + ".mp4";
_info.strFilePath = strFile; _info.strFilePath = strFile;
GET_CONFIG(string,appName,Record::kAppName); GET_CONFIG(string,appName,Record::kAppName);
_info.strUrl = appName + "/" _info.strUrl = appName + "/"
+ _info.strAppName + "/" + _info.strAppName + "/"
...@@ -68,78 +68,78 @@ void MP4Recorder::createFile() { ...@@ -68,78 +68,78 @@ void MP4Recorder::createFile() {
+ strDate + "/" + strDate + "/"
+ strTime + ".mp4"; + strTime + ".mp4";
try { try {
_muxer = std::make_shared<MP4MuxerFile>(strFileTmp.data()); _muxer = std::make_shared<MP4MuxerFile>(strFileTmp.data());
for(auto &track :_tracks){ for(auto &track :_tracks){
//添加track //添加track
_muxer->addTrack(track); _muxer->addTrack(track);
} }
_strFileTmp = strFileTmp; _strFileTmp = strFileTmp;
_strFile = strFile; _strFile = strFile;
_createFileTicker.resetTime(); _createFileTicker.resetTime();
}catch(std::exception &ex) { }catch(std::exception &ex) {
WarnL << ex.what(); WarnL << ex.what();
} }
} }
void MP4Recorder::asyncClose() { void MP4Recorder::asyncClose() {
auto muxer = _muxer; auto muxer = _muxer;
auto strFileTmp = _strFileTmp; auto strFileTmp = _strFileTmp;
auto strFile = _strFile; auto strFile = _strFile;
auto info = _info; auto info = _info;
WorkThreadPool::Instance().getExecutor()->async([muxer,strFileTmp,strFile,info]() { WorkThreadPool::Instance().getExecutor()->async([muxer,strFileTmp,strFile,info]() {
//获取文件录制时间,放在关闭mp4之前是为了忽略关闭mp4执行时间 //获取文件录制时间,放在关闭mp4之前是为了忽略关闭mp4执行时间
const_cast<MP4Info&>(info).ui64TimeLen = ::time(NULL) - info.ui64StartedTime; const_cast<MP4Info&>(info).ui64TimeLen = ::time(NULL) - info.ui64StartedTime;
//关闭mp4非常耗时,所以要放在后台线程执行 //关闭mp4非常耗时,所以要放在后台线程执行
const_cast<MP4MuxerFile::Ptr &>(muxer).reset(); const_cast<MP4MuxerFile::Ptr &>(muxer).reset();
//临时文件名改成正式文件名,防止mp4未完成时被访问 //临时文件名改成正式文件名,防止mp4未完成时被访问
rename(strFileTmp.data(),strFile.data()); rename(strFileTmp.data(),strFile.data());
//获取文件大小 //获取文件大小
struct stat fileData; struct stat fileData;
stat(strFile.data(), &fileData); stat(strFile.data(), &fileData);
const_cast<MP4Info&>(info).ui64FileSize = fileData.st_size; const_cast<MP4Info&>(info).ui64FileSize = fileData.st_size;
/////record 业务逻辑////// /////record 业务逻辑//////
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastRecordMP4,info); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastRecordMP4,info);
}); });
} }
void MP4Recorder::closeFile() { void MP4Recorder::closeFile() {
if (_muxer) { if (_muxer) {
asyncClose(); asyncClose();
_muxer = nullptr; _muxer = nullptr;
} }
} }
void MP4Recorder::inputFrame(const Frame::Ptr &frame) { void MP4Recorder::inputFrame(const Frame::Ptr &frame) {
GET_CONFIG(uint32_t,recordSec,Record::kFileSecond); GET_CONFIG(uint32_t,recordSec,Record::kFileSecond);
if(!_muxer || ((_createFileTicker.elapsedTime() > recordSec * 1000) && if(!_muxer || ((_createFileTicker.elapsedTime() > recordSec * 1000) &&
(!_haveVideo || (_haveVideo && frame->keyFrame()))) ){ (!_haveVideo || (_haveVideo && frame->keyFrame()))) ){
//成立条件 //成立条件
//1、_muxer为空 //1、_muxer为空
//2、到了切片时间,并且只有音频 //2、到了切片时间,并且只有音频
//3、到了切片时间,有视频并且遇到视频的关键帧 //3、到了切片时间,有视频并且遇到视频的关键帧
createFile(); createFile();
} }
if(_muxer){ if(_muxer){
//生成mp4文件 //生成mp4文件
_muxer->inputFrame(frame); _muxer->inputFrame(frame);
} }
} }
void MP4Recorder::addTrack(const Track::Ptr & track){ void MP4Recorder::addTrack(const Track::Ptr & track){
//保存所有的track,为创建MP4MuxerFile做准备 //保存所有的track,为创建MP4MuxerFile做准备
_tracks.emplace_back(track); _tracks.emplace_back(track);
if(track->getTrackType() == TrackVideo){ if(track->getTrackType() == TrackVideo){
_haveVideo = true; _haveVideo = true;
} }
} }
void MP4Recorder::resetTracks() { void MP4Recorder::resetTracks() {
closeFile(); closeFile();
_tracks.clear(); _tracks.clear();
_haveVideo = false; _haveVideo = false;
_createFileTicker.resetTime(); _createFileTicker.resetTime();
} }
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -42,38 +42,38 @@ namespace mediakit { ...@@ -42,38 +42,38 @@ namespace mediakit {
class MP4Info { class MP4Info {
public: public:
time_t ui64StartedTime; //GMT标准时间,单位秒 time_t ui64StartedTime; //GMT标准时间,单位秒
time_t ui64TimeLen;//录像长度,单位秒 time_t ui64TimeLen;//录像长度,单位秒
off_t ui64FileSize;//文件大小,单位BYTE off_t ui64FileSize;//文件大小,单位BYTE
string strFilePath;//文件路径 string strFilePath;//文件路径
string strFileName;//文件名称 string strFileName;//文件名称
string strFolder;//文件夹路径 string strFolder;//文件夹路径
string strUrl;//播放路径 string strUrl;//播放路径
string strAppName;//应用名称 string strAppName;//应用名称
string strStreamId;//流ID string strStreamId;//流ID
string strVhost;//vhost string strVhost;//vhost
}; };
#ifdef ENABLE_MP4RECORD #ifdef ENABLE_MP4RECORD
class MP4Recorder : public MediaSinkInterface{ class MP4Recorder : public MediaSinkInterface{
public: public:
typedef std::shared_ptr<MP4Recorder> Ptr; typedef std::shared_ptr<MP4Recorder> Ptr;
MP4Recorder(const string &strPath, MP4Recorder(const string &strPath,
const string &strVhost, const string &strVhost,
const string &strApp, const string &strApp,
const string &strStreamId); const string &strStreamId);
virtual ~MP4Recorder(); virtual ~MP4Recorder();
/** /**
* 重置所有Track * 重置所有Track
*/ */
void resetTracks() override; void resetTracks() override;
/** /**
* 输入frame * 输入frame
*/ */
void inputFrame(const Frame::Ptr &frame) override; void inputFrame(const Frame::Ptr &frame) override;
/** /**
* 添加ready状态的track * 添加ready状态的track
...@@ -84,14 +84,14 @@ private: ...@@ -84,14 +84,14 @@ private:
void closeFile(); void closeFile();
void asyncClose(); void asyncClose();
private: private:
string _strPath; string _strPath;
string _strFile; string _strFile;
string _strFileTmp; string _strFileTmp;
Ticker _createFileTicker; Ticker _createFileTicker;
MP4Info _info; MP4Info _info;
bool _haveVideo = false; bool _haveVideo = false;
MP4MuxerFile::Ptr _muxer; MP4MuxerFile::Ptr _muxer;
list<Track::Ptr> _tracks; list<Track::Ptr> _tracks;
}; };
#endif ///ENABLE_MP4RECORD #endif ///ENABLE_MP4RECORD
......
...@@ -37,32 +37,32 @@ class MediaSinkInterface; ...@@ -37,32 +37,32 @@ class MediaSinkInterface;
class Recorder{ class Recorder{
public: public:
typedef enum { typedef enum {
// 未录制 // 未录制
status_not_record = 0, status_not_record = 0,
// 等待MediaSource注册,注册成功后立即开始录制 // 等待MediaSource注册,注册成功后立即开始录制
status_wait_record = 1, status_wait_record = 1,
// MediaSource已注册,并且正在录制 // MediaSource已注册,并且正在录制
status_recording = 2, status_recording = 2,
} status; } status;
typedef enum { typedef enum {
// 录制hls // 录制hls
type_hls = 0, type_hls = 0,
// 录制MP4 // 录制MP4
type_mp4 = 1 type_mp4 = 1
} type; } type;
/** /**
* 获取录制文件绝对路径 * 获取录制文件绝对路径
* @param type hls还是MP4录制 * @param type hls还是MP4录制
* @param vhost 虚拟主机 * @param vhost 虚拟主机
* @param app 应用名 * @param app 应用名
* @param stream_id 流id * @param stream_id 流id
* @param customized_path 录像文件保存自定义目录,默认为空则自动生成 * @param customized_path 录像文件保存自定义目录,默认为空则自动生成
* @return 录制文件绝对路径 * @return 录制文件绝对路径
*/ */
static string getRecordPath(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path = ""); static string getRecordPath(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path = "");
/** /**
* 获取录制状态 * 获取录制状态
...@@ -72,57 +72,57 @@ public: ...@@ -72,57 +72,57 @@ public:
* @param stream_id 流id * @param stream_id 流id
* @return 录制状态 * @return 录制状态
*/ */
static status getRecordStatus(type type, const string &vhost, const string &app, const string &stream_id); static status getRecordStatus(type type, const string &vhost, const string &app, const string &stream_id);
/** /**
* 开始录制 * 开始录制
* @param type hls还是MP4录制 * @param type hls还是MP4录制
* @param vhost 虚拟主机 * @param vhost 虚拟主机
* @param app 应用名 * @param app 应用名
* @param stream_id 流id * @param stream_id 流id
* @param customized_path 录像文件保存自定义目录,默认为空则自动生成 * @param customized_path 录像文件保存自定义目录,默认为空则自动生成
* @param waitForRecord 是否等待流注册后再录制,未注册时,置false将返回失败 * @param waitForRecord 是否等待流注册后再录制,未注册时,置false将返回失败
* @param continueRecord 流注销时是否继续等待录制还是立即停止录制 * @param continueRecord 流注销时是否继续等待录制还是立即停止录制
* @return 0代表成功,负数代表失败 * @return 0代表成功,负数代表失败
*/ */
static int startRecord(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path,bool waitForRecord, bool continueRecord); static int startRecord(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path,bool waitForRecord, bool continueRecord);
/** /**
* 停止录制 * 停止录制
* @param type hls还是MP4录制 * @param type hls还是MP4录制
* @param vhost 虚拟主机 * @param vhost 虚拟主机
* @param app 应用名 * @param app 应用名
* @param stream_id 流id * @param stream_id 流id
*/ */
static bool stopRecord(type type, const string &vhost, const string &app, const string &stream_id); static bool stopRecord(type type, const string &vhost, const string &app, const string &stream_id);
/** /**
* 停止所有录制,一般程序退出时调用 * 停止所有录制,一般程序退出时调用
*/ */
static void stopAll(); static void stopAll();
/** /**
* 获取录制对象 * 获取录制对象
* @param type hls还是MP4录制 * @param type hls还是MP4录制
* @param vhost 虚拟主机 * @param vhost 虚拟主机
* @param app 应用名 * @param app 应用名
* @param stream_id 流id * @param stream_id 流id
*/ */
static std::shared_ptr<MediaSinkInterface> getRecorder(type type, const string &vhost, const string &app, const string &stream_id); static std::shared_ptr<MediaSinkInterface> getRecorder(type type, const string &vhost, const string &app, const string &stream_id);
/** /**
* 创建录制器对象 * 创建录制器对象
* @param type hls还是MP4录制 * @param type hls还是MP4录制
* @param vhost 虚拟主机 * @param vhost 虚拟主机
* @param app 应用名 * @param app 应用名
* @param stream_id 流id * @param stream_id 流id
* @param customized_path 录像文件保存自定义目录,默认为空则自动生成 * @param customized_path 录像文件保存自定义目录,默认为空则自动生成
* @return 对象指针,可能为nullptr * @return 对象指针,可能为nullptr
*/ */
static std::shared_ptr<MediaSinkInterface> createRecorder(type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path); static std::shared_ptr<MediaSinkInterface> createRecorder(type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path);
private: private:
Recorder() = delete; Recorder() = delete;
~Recorder() = delete; ~Recorder() = delete;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -41,27 +41,27 @@ namespace mediakit { ...@@ -41,27 +41,27 @@ namespace mediakit {
class RtmpDemuxer : public Demuxer{ class RtmpDemuxer : public Demuxer{
public: public:
typedef std::shared_ptr<RtmpDemuxer> Ptr; typedef std::shared_ptr<RtmpDemuxer> Ptr;
RtmpDemuxer() = default; RtmpDemuxer() = default;
virtual ~RtmpDemuxer() = default; virtual ~RtmpDemuxer() = default;
void loadMetaData(const AMFValue &metadata); void loadMetaData(const AMFValue &metadata);
/** /**
* 开始解复用 * 开始解复用
* @param pkt rtmp包 * @param pkt rtmp包
* @return true 代表是i帧 * @return true 代表是i帧
*/ */
bool inputRtmp(const RtmpPacket::Ptr &pkt); bool inputRtmp(const RtmpPacket::Ptr &pkt);
private: private:
void makeVideoTrack(const AMFValue &val); void makeVideoTrack(const AMFValue &val);
void makeAudioTrack(const AMFValue &val); void makeAudioTrack(const AMFValue &val);
private: private:
bool _tryedGetVideoTrack = false; bool _tryedGetVideoTrack = false;
bool _tryedGetAudioTrack = false; bool _tryedGetAudioTrack = false;
RtmpCodec::Ptr _audioRtmpDecoder; RtmpCodec::Ptr _audioRtmpDecoder;
RtmpCodec::Ptr _videoRtmpDecoder; RtmpCodec::Ptr _videoRtmpDecoder;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -58,163 +58,163 @@ namespace mediakit { ...@@ -58,163 +58,163 @@ namespace mediakit {
*/ */
class RtmpMediaSource : public MediaSource, public RingDelegate<RtmpPacket::Ptr> { class RtmpMediaSource : public MediaSource, public RingDelegate<RtmpPacket::Ptr> {
public: public:
typedef std::shared_ptr<RtmpMediaSource> Ptr; typedef std::shared_ptr<RtmpMediaSource> Ptr;
typedef RingBuffer<RtmpPacket::Ptr> RingType; typedef RingBuffer<RtmpPacket::Ptr> RingType;
/** /**
* 构造函数 * 构造函数
* @param vhost 虚拟主机名 * @param vhost 虚拟主机名
* @param app 应用名 * @param app 应用名
* @param stream_id 流id * @param stream_id 流id
* @param ring_size 可以设置固定的环形缓冲大小,0则自适应 * @param ring_size 可以设置固定的环形缓冲大小,0则自适应
*/ */
RtmpMediaSource(const string &vhost, RtmpMediaSource(const string &vhost,
const string &app, const string &app,
const string &stream_id, const string &stream_id,
int ring_size = RTMP_GOP_SIZE) : int ring_size = RTMP_GOP_SIZE) :
MediaSource(RTMP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) { MediaSource(RTMP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {
} }
virtual ~RtmpMediaSource() {} virtual ~RtmpMediaSource() {}
/** /**
* 获取媒体源的环形缓冲 * 获取媒体源的环形缓冲
*/ */
const RingType::Ptr &getRing() const { const RingType::Ptr &getRing() const {
return _ring; return _ring;
} }
/** /**
* 获取播放器个数 * 获取播放器个数
* @return * @return
*/ */
int readerCount() override { int readerCount() override {
return _ring ? _ring->readerCount() : 0; return _ring ? _ring->readerCount() : 0;
} }
/** /**
* 获取metadata * 获取metadata
*/ */
const AMFValue &getMetaData() const { const AMFValue &getMetaData() const {
lock_guard<recursive_mutex> lock(_mtx); lock_guard<recursive_mutex> lock(_mtx);
return _metadata; return _metadata;
} }
/** /**
* 获取所有的config帧 * 获取所有的config帧
*/ */
template<typename FUNC> template<typename FUNC>
void getConfigFrame(const FUNC &f) { void getConfigFrame(const FUNC &f) {
lock_guard<recursive_mutex> lock(_mtx); lock_guard<recursive_mutex> lock(_mtx);
for (auto &pr : _config_frame_map) { for (auto &pr : _config_frame_map) {
f(pr.second); f(pr.second);
} }
} }
/** /**
* 设置metadata * 设置metadata
*/ */
virtual void setMetaData(const AMFValue &metadata) { virtual void setMetaData(const AMFValue &metadata) {
lock_guard<recursive_mutex> lock(_mtx); lock_guard<recursive_mutex> lock(_mtx);
_metadata = metadata; _metadata = metadata;
if(_ring){ if(_ring){
regist(); regist();
} }
} }
/** /**
* 输入rtmp包 * 输入rtmp包
* @param pkt rtmp包 * @param pkt rtmp包
* @param key 是否为关键帧 * @param key 是否为关键帧
*/ */
void onWrite(const RtmpPacket::Ptr &pkt, bool key = true) override { void onWrite(const RtmpPacket::Ptr &pkt, bool key = true) override {
lock_guard<recursive_mutex> lock(_mtx); lock_guard<recursive_mutex> lock(_mtx);
if(pkt->typeId == MSG_VIDEO){ if(pkt->typeId == MSG_VIDEO){
//有视频,那么启用GOP缓存 //有视频,那么启用GOP缓存
_have_video = true; _have_video = true;
} }
if (pkt->isCfgFrame()) { if (pkt->isCfgFrame()) {
_config_frame_map[pkt->typeId] = pkt; _config_frame_map[pkt->typeId] = pkt;
return; return;
} }
if (!_ring) { if (!_ring) {
weak_ptr<RtmpMediaSource> weakSelf = dynamic_pointer_cast<RtmpMediaSource>(shared_from_this()); weak_ptr<RtmpMediaSource> weakSelf = dynamic_pointer_cast<RtmpMediaSource>(shared_from_this());
auto lam = [weakSelf](const EventPoller::Ptr &, int size, bool) { auto lam = [weakSelf](const EventPoller::Ptr &, int size, bool) {
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
if (!strongSelf) { if (!strongSelf) {
return; return;
} }
strongSelf->onReaderChanged(size); strongSelf->onReaderChanged(size);
}; };
//rtmp包缓存最大允许512个,如果是纯视频(25fps)大概为20秒数据 //rtmp包缓存最大允许512个,如果是纯视频(25fps)大概为20秒数据
//但是这个是GOP缓存的上限值,真实的GOP缓存大小等于两个I帧之间的包数的两倍 //但是这个是GOP缓存的上限值,真实的GOP缓存大小等于两个I帧之间的包数的两倍
//而且每次遇到I帧,则会清空GOP缓存,所以真实的GOP缓存远小于此值 //而且每次遇到I帧,则会清空GOP缓存,所以真实的GOP缓存远小于此值
_ring = std::make_shared<RingType>(_ring_size,std::move(lam)); _ring = std::make_shared<RingType>(_ring_size,std::move(lam));
onReaderChanged(0); onReaderChanged(0);
if(_metadata){ if(_metadata){
regist(); regist();
} }
} }
_track_stamps_map[pkt->typeId] = pkt->timeStamp; _track_stamps_map[pkt->typeId] = pkt->timeStamp;
//不存在视频,为了减少缓存延时,那么关闭GOP缓存 //不存在视频,为了减少缓存延时,那么关闭GOP缓存
_ring->write(pkt, _have_video ? pkt->isVideoKeyFrame() : true); _ring->write(pkt, _have_video ? pkt->isVideoKeyFrame() : true);
checkNoneReader(); checkNoneReader();
} }
/** /**
* 获取当前时间戳 * 获取当前时间戳
*/ */
uint32_t getTimeStamp(TrackType trackType) override { uint32_t getTimeStamp(TrackType trackType) override {
lock_guard<recursive_mutex> lock(_mtx); lock_guard<recursive_mutex> lock(_mtx);
switch (trackType) { switch (trackType) {
case TrackVideo: case TrackVideo:
return _track_stamps_map[MSG_VIDEO]; return _track_stamps_map[MSG_VIDEO];
case TrackAudio: case TrackAudio:
return _track_stamps_map[MSG_AUDIO]; return _track_stamps_map[MSG_AUDIO];
default: default:
return MAX(_track_stamps_map[MSG_VIDEO], _track_stamps_map[MSG_AUDIO]); return MAX(_track_stamps_map[MSG_VIDEO], _track_stamps_map[MSG_AUDIO]);
} }
} }
private: private:
/** /**
* 每次增减消费者都会触发该函数 * 每次增减消费者都会触发该函数
*/ */
void onReaderChanged(int size) { void onReaderChanged(int size) {
//我们记录最后一次活动时间 //我们记录最后一次活动时间
_reader_changed_ticker.resetTime(); _reader_changed_ticker.resetTime();
if (size != 0 || totalReaderCount() != 0) { if (size != 0 || totalReaderCount() != 0) {
//还有消费者正在观看该流 //还有消费者正在观看该流
_async_emit_none_reader = false; _async_emit_none_reader = false;
return; return;
} }
_async_emit_none_reader = true; _async_emit_none_reader = true;
} }
/** /**
* 检查是否无人消费该流, * 检查是否无人消费该流,
* 如果无人消费且超过一定时间会触发onNoneReader事件 * 如果无人消费且超过一定时间会触发onNoneReader事件
*/ */
void checkNoneReader() { void checkNoneReader() {
GET_CONFIG(int, stream_none_reader_delay, General::kStreamNoneReaderDelayMS); GET_CONFIG(int, stream_none_reader_delay, General::kStreamNoneReaderDelayMS);
if (_async_emit_none_reader && _reader_changed_ticker.elapsedTime() > stream_none_reader_delay) { if (_async_emit_none_reader && _reader_changed_ticker.elapsedTime() > stream_none_reader_delay) {
_async_emit_none_reader = false; _async_emit_none_reader = false;
onNoneReader(); onNoneReader();
} }
} }
protected: protected:
int _ring_size; int _ring_size;
bool _async_emit_none_reader = false; bool _async_emit_none_reader = false;
bool _have_video = false; bool _have_video = false;
mutable recursive_mutex _mtx; mutable recursive_mutex _mtx;
Ticker _reader_changed_ticker; Ticker _reader_changed_ticker;
AMFValue _metadata; AMFValue _metadata;
RingBuffer<RtmpPacket::Ptr>::Ptr _ring; RingBuffer<RtmpPacket::Ptr>::Ptr _ring;
unordered_map<int, uint32_t> _track_stamps_map; unordered_map<int, uint32_t> _track_stamps_map;
unordered_map<int, RtmpPacket::Ptr> _config_frame_map; unordered_map<int, RtmpPacket::Ptr> _config_frame_map;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -45,46 +45,46 @@ using namespace toolkit; ...@@ -45,46 +45,46 @@ using namespace toolkit;
namespace mediakit { namespace mediakit {
class RtmpMediaSourceImp: public RtmpMediaSource, public Demuxer::Listener , public MultiMediaSourceMuxer::Listener { class RtmpMediaSourceImp: public RtmpMediaSource, public Demuxer::Listener , public MultiMediaSourceMuxer::Listener {
public: public:
typedef std::shared_ptr<RtmpMediaSourceImp> Ptr; typedef std::shared_ptr<RtmpMediaSourceImp> Ptr;
/** /**
* 构造函数 * 构造函数
* @param vhost 虚拟主机 * @param vhost 虚拟主机
* @param app 应用名 * @param app 应用名
* @param id 流id * @param id 流id
* @param ringSize 环形缓存大小 * @param ringSize 环形缓存大小
*/ */
RtmpMediaSourceImp(const string &vhost, const string &app, const string &id, int ringSize = RTMP_GOP_SIZE) : RtmpMediaSource(vhost, app, id, ringSize) { RtmpMediaSourceImp(const string &vhost, const string &app, const string &id, int ringSize = RTMP_GOP_SIZE) : RtmpMediaSource(vhost, app, id, ringSize) {
_demuxer = std::make_shared<RtmpDemuxer>(); _demuxer = std::make_shared<RtmpDemuxer>();
_demuxer->setTrackListener(this); _demuxer->setTrackListener(this);
} }
~RtmpMediaSourceImp() = default; ~RtmpMediaSourceImp() = default;
/** /**
* 设置metadata * 设置metadata
*/ */
void setMetaData(const AMFValue &metadata) override{ void setMetaData(const AMFValue &metadata) override{
_demuxer->loadMetaData(metadata); _demuxer->loadMetaData(metadata);
RtmpMediaSource::setMetaData(metadata); RtmpMediaSource::setMetaData(metadata);
} }
/** /**
* 输入rtmp并解析 * 输入rtmp并解析
*/ */
void onWrite(const RtmpPacket::Ptr &pkt,bool key_pos = true) override { void onWrite(const RtmpPacket::Ptr &pkt,bool key_pos = true) override {
key_pos = _demuxer->inputRtmp(pkt); key_pos = _demuxer->inputRtmp(pkt);
RtmpMediaSource::onWrite(pkt,key_pos); RtmpMediaSource::onWrite(pkt,key_pos);
} }
/** /**
* 设置监听器 * 设置监听器
* @param listener * @param listener
*/ */
void setListener(const std::weak_ptr<MediaSourceEvent> &listener) override { void setListener(const std::weak_ptr<MediaSourceEvent> &listener) override {
RtmpMediaSource::setListener(listener); RtmpMediaSource::setListener(listener);
if(_muxer){ if(_muxer){
_muxer->setListener(listener); _muxer->setListener(listener);
} }
} }
...@@ -95,42 +95,42 @@ public: ...@@ -95,42 +95,42 @@ public:
return readerCount() + (_muxer ? _muxer->totalReaderCount() : 0); return readerCount() + (_muxer ? _muxer->totalReaderCount() : 0);
} }
/** /**
* 设置协议转换 * 设置协议转换
* @param enableRtsp 是否转换成rtsp * @param enableRtsp 是否转换成rtsp
* @param enableHls 是否转换成hls * @param enableHls 是否转换成hls
* @param enableMP4 是否mp4录制 * @param enableMP4 是否mp4录制
*/ */
void setProtocolTranslation(bool enableRtsp, bool enableHls, bool enableMP4) { void setProtocolTranslation(bool enableRtsp, bool enableHls, bool enableMP4) {
//不重复生成rtmp //不重复生成rtmp
_muxer = std::make_shared<MultiMediaSourceMuxer>(getVhost(), getApp(), getId(), _demuxer->getDuration(), enableRtsp, false, enableHls, enableMP4); _muxer = std::make_shared<MultiMediaSourceMuxer>(getVhost(), getApp(), getId(), _demuxer->getDuration(), enableRtsp, false, enableHls, enableMP4);
_muxer->setListener(getListener()); _muxer->setListener(getListener());
_muxer->setTrackListener(this); _muxer->setTrackListener(this);
for(auto &track : _demuxer->getTracks(false)){ for(auto &track : _demuxer->getTracks(false)){
_muxer->addTrack(track); _muxer->addTrack(track);
track->addDelegate(_muxer); track->addDelegate(_muxer);
} }
} }
/** /**
* _demuxer触发的添加Track事件 * _demuxer触发的添加Track事件
*/ */
void onAddTrack(const Track::Ptr &track) override { void onAddTrack(const Track::Ptr &track) override {
if(_muxer){ if(_muxer){
_muxer->addTrack(track); _muxer->addTrack(track);
track->addDelegate(_muxer); track->addDelegate(_muxer);
} }
} }
/** /**
* _muxer触发的所有Track就绪的事件 * _muxer触发的所有Track就绪的事件
*/ */
void onAllTrackReady() override{ void onAllTrackReady() override{
setTrackSource(_muxer); setTrackSource(_muxer);
} }
private: private:
RtmpDemuxer::Ptr _demuxer; RtmpDemuxer::Ptr _demuxer;
MultiMediaSourceMuxer::Ptr _muxer; MultiMediaSourceMuxer::Ptr _muxer;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -47,77 +47,77 @@ namespace mediakit { ...@@ -47,77 +47,77 @@ namespace mediakit {
//实现了rtmp播放器协议部分的功能,及数据接收功能 //实现了rtmp播放器协议部分的功能,及数据接收功能
class RtmpPlayer:public PlayerBase, public TcpClient, public RtmpProtocol{ class RtmpPlayer:public PlayerBase, public TcpClient, public RtmpProtocol{
public: public:
typedef std::shared_ptr<RtmpPlayer> Ptr; typedef std::shared_ptr<RtmpPlayer> Ptr;
RtmpPlayer(const EventPoller::Ptr &poller); RtmpPlayer(const EventPoller::Ptr &poller);
virtual ~RtmpPlayer(); virtual ~RtmpPlayer();
void play(const string &strUrl) override; void play(const string &strUrl) override;
void pause(bool bPause) override; void pause(bool bPause) override;
void teardown() override; void teardown() override;
protected: protected:
virtual bool onCheckMeta(const AMFValue &val) =0; virtual bool onCheckMeta(const AMFValue &val) =0;
virtual void onMediaData(const RtmpPacket::Ptr &chunkData) =0; virtual void onMediaData(const RtmpPacket::Ptr &chunkData) =0;
uint32_t getProgressMilliSecond() const; uint32_t getProgressMilliSecond() const;
void seekToMilliSecond(uint32_t ms); void seekToMilliSecond(uint32_t ms);
protected: protected:
void onMediaData_l(const RtmpPacket::Ptr &chunkData); void onMediaData_l(const RtmpPacket::Ptr &chunkData);
//在获取config帧后才触发onPlayResult_l(而不是收到play命令回复),所以此时所有track都初始化完毕了 //在获取config帧后才触发onPlayResult_l(而不是收到play命令回复),所以此时所有track都初始化完毕了
void onPlayResult_l(const SockException &ex, bool handshakeCompleted); void onPlayResult_l(const SockException &ex, bool handshakeCompleted);
//form Tcpclient //form Tcpclient
void onRecv(const Buffer::Ptr &pBuf) override; void onRecv(const Buffer::Ptr &pBuf) override;
void onConnect(const SockException &err) override; void onConnect(const SockException &err) override;
void onErr(const SockException &ex) override; void onErr(const SockException &ex) override;
//from RtmpProtocol //from RtmpProtocol
void onRtmpChunk(RtmpPacket &chunkData) override; void onRtmpChunk(RtmpPacket &chunkData) override;
void onStreamDry(uint32_t ui32StreamId) override; void onStreamDry(uint32_t ui32StreamId) override;
void onSendRawData(const Buffer::Ptr &buffer) override{ void onSendRawData(const Buffer::Ptr &buffer) override{
send(buffer); send(buffer);
} }
template<typename FUN> template<typename FUN>
inline void addOnResultCB(const FUN &fun) { inline void addOnResultCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(_mtxOnResultCB); lock_guard<recursive_mutex> lck(_mtxOnResultCB);
_mapOnResultCB.emplace(_iReqID, fun); _mapOnResultCB.emplace(_iReqID, fun);
} }
template<typename FUN> template<typename FUN>
inline void addOnStatusCB(const FUN &fun) { inline void addOnStatusCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(_mtxOnStatusCB); lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
_dqOnStatusCB.emplace_back(fun); _dqOnStatusCB.emplace_back(fun);
} }
void onCmd_result(AMFDecoder &dec); void onCmd_result(AMFDecoder &dec);
void onCmd_onStatus(AMFDecoder &dec); void onCmd_onStatus(AMFDecoder &dec);
void onCmd_onMetaData(AMFDecoder &dec); void onCmd_onMetaData(AMFDecoder &dec);
inline void send_connect(); inline void send_connect();
inline void send_createStream(); inline void send_createStream();
inline void send_play(); inline void send_play();
inline void send_pause(bool bPause); inline void send_pause(bool bPause);
private: private:
string _strApp; string _strApp;
string _strStream; string _strStream;
string _strTcUrl; string _strTcUrl;
bool _bPaused = false; bool _bPaused = false;
unordered_map<int, function<void(AMFDecoder &dec)> > _mapOnResultCB; unordered_map<int, function<void(AMFDecoder &dec)> > _mapOnResultCB;
recursive_mutex _mtxOnResultCB; recursive_mutex _mtxOnResultCB;
deque<function<void(AMFValue &dec)> > _dqOnStatusCB; deque<function<void(AMFValue &dec)> > _dqOnStatusCB;
recursive_mutex _mtxOnStatusCB; recursive_mutex _mtxOnStatusCB;
//超时功能实现 //超时功能实现
Ticker _mediaTicker; Ticker _mediaTicker;
std::shared_ptr<Timer> _pMediaTimer; std::shared_ptr<Timer> _pMediaTimer;
std::shared_ptr<Timer> _pPlayTimer; std::shared_ptr<Timer> _pPlayTimer;
//心跳定时器 //心跳定时器
std::shared_ptr<Timer> _pBeatTimer; std::shared_ptr<Timer> _pBeatTimer;
//播放进度控制 //播放进度控制
uint32_t _iSeekTo = 0; uint32_t _iSeekTo = 0;
uint32_t _aiFistStamp[2] = { 0, 0 }; uint32_t _aiFistStamp[2] = { 0, 0 };
uint32_t _aiNowStamp[2] = { 0, 0 }; uint32_t _aiNowStamp[2] = { 0, 0 };
Ticker _aNowStampTicker[2]; Ticker _aNowStampTicker[2];
bool _metadata_got = false; bool _metadata_got = false;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -73,7 +73,7 @@ private: ...@@ -73,7 +73,7 @@ private:
return true; return true;
} }
void onMediaData(const RtmpPacket::Ptr &chunkData) override { void onMediaData(const RtmpPacket::Ptr &chunkData) override {
if(_pRtmpMediaSrc){ if(_pRtmpMediaSrc){
if(!_set_meta_data && !chunkData->isCfgFrame()){ if(!_set_meta_data && !chunkData->isCfgFrame()){
_set_meta_data = true; _set_meta_data = true;
_pRtmpMediaSrc->setMetaData(TitleMeta().getMetadata()); _pRtmpMediaSrc->setMetaData(TitleMeta().getMetadata());
...@@ -81,7 +81,7 @@ private: ...@@ -81,7 +81,7 @@ private:
_pRtmpMediaSrc->onWrite(chunkData); _pRtmpMediaSrc->onWrite(chunkData);
} }
if(!_delegate){ if(!_delegate){
//这个流没有metadata //这个流没有metadata
_delegate.reset(new RtmpDemuxer()); _delegate.reset(new RtmpDemuxer());
} }
_delegate->inputRtmp(chunkData); _delegate->inputRtmp(chunkData);
......
...@@ -45,77 +45,77 @@ namespace mediakit { ...@@ -45,77 +45,77 @@ namespace mediakit {
class RtmpProtocol { class RtmpProtocol {
public: public:
RtmpProtocol(); RtmpProtocol();
virtual ~RtmpProtocol(); virtual ~RtmpProtocol();
//作为客户端发送c0c1,等待s0s1s2并且回调 //作为客户端发送c0c1,等待s0s1s2并且回调
void startClientSession(const function<void()> &cb); void startClientSession(const function<void()> &cb);
void onParseRtmp(const char *pcRawData,int iSize); void onParseRtmp(const char *pcRawData,int iSize);
void reset(); void reset();
protected: protected:
virtual void onSendRawData(const Buffer::Ptr &buffer) = 0; virtual void onSendRawData(const Buffer::Ptr &buffer) = 0;
virtual void onRtmpChunk(RtmpPacket &chunkData) = 0; virtual void onRtmpChunk(RtmpPacket &chunkData) = 0;
virtual void onStreamBegin(uint32_t ui32StreamId){ virtual void onStreamBegin(uint32_t ui32StreamId){
_ui32StreamId = ui32StreamId; _ui32StreamId = ui32StreamId;
} }
virtual void onStreamEof(uint32_t ui32StreamId){}; virtual void onStreamEof(uint32_t ui32StreamId){};
virtual void onStreamDry(uint32_t ui32StreamId){}; virtual void onStreamDry(uint32_t ui32StreamId){};
protected: protected:
void sendAcknowledgement(uint32_t ui32Size); void sendAcknowledgement(uint32_t ui32Size);
void sendAcknowledgementSize(uint32_t ui32Size); void sendAcknowledgementSize(uint32_t ui32Size);
void sendPeerBandwidth(uint32_t ui32Size); void sendPeerBandwidth(uint32_t ui32Size);
void sendChunkSize(uint32_t ui32Size); void sendChunkSize(uint32_t ui32Size);
void sendPingRequest(uint32_t ui32TimeStamp = ::time(NULL)); void sendPingRequest(uint32_t ui32TimeStamp = ::time(NULL));
void sendPingResponse(uint32_t ui32TimeStamp = ::time(NULL)); void sendPingResponse(uint32_t ui32TimeStamp = ::time(NULL));
void sendSetBufferLength(uint32_t ui32StreamId, uint32_t ui32Length); void sendSetBufferLength(uint32_t ui32StreamId, uint32_t ui32Length);
void sendUserControl(uint16_t ui16EventType, uint32_t ui32EventData); void sendUserControl(uint16_t ui16EventType, uint32_t ui32EventData);
void sendUserControl(uint16_t ui16EventType, const string &strEventData); void sendUserControl(uint16_t ui16EventType, const string &strEventData);
void sendInvoke(const string &strCmd, const AMFValue &val); void sendInvoke(const string &strCmd, const AMFValue &val);
void sendRequest(int iCmd, const string &str); void sendRequest(int iCmd, const string &str);
void sendResponse(int iType, const string &str); void sendResponse(int iType, const string &str);
void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const std::string &strBuf, uint32_t ui32TimeStamp, int iChunkID); void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const std::string &strBuf, uint32_t ui32TimeStamp, int iChunkID);
void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const Buffer::Ptr &buffer, uint32_t ui32TimeStamp, int iChunkID); void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const Buffer::Ptr &buffer, uint32_t ui32TimeStamp, int iChunkID);
protected: protected:
int _iReqID = 0; int _iReqID = 0;
uint32_t _ui32StreamId = STREAM_CONTROL; uint32_t _ui32StreamId = STREAM_CONTROL;
int _iNowStreamID = 0; int _iNowStreamID = 0;
int _iNowChunkID = 0; int _iNowChunkID = 0;
bool _bDataStarted = false; bool _bDataStarted = false;
inline BufferRaw::Ptr obtainBuffer(); inline BufferRaw::Ptr obtainBuffer();
inline BufferRaw::Ptr obtainBuffer(const void *data, int len); inline BufferRaw::Ptr obtainBuffer(const void *data, int len);
//ResourcePool<BufferRaw,MAX_SEND_PKT> _bufferPool; //ResourcePool<BufferRaw,MAX_SEND_PKT> _bufferPool;
private: private:
void handle_S0S1S2(const function<void()> &cb); void handle_S0S1S2(const function<void()> &cb);
void handle_C0C1(); void handle_C0C1();
void handle_C1_simple(); void handle_C1_simple();
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
void handle_C1_complex(); void handle_C1_complex();
string get_C1_digest(const uint8_t *ptr,char **digestPos); string get_C1_digest(const uint8_t *ptr,char **digestPos);
string get_C1_key(const uint8_t *ptr); string get_C1_key(const uint8_t *ptr);
void check_C1_Digest(const string &digest,const string &data); void check_C1_Digest(const string &digest,const string &data);
void send_complex_S0S1S2(int schemeType,const string &digest); void send_complex_S0S1S2(int schemeType,const string &digest);
#endif //ENABLE_OPENSSL #endif //ENABLE_OPENSSL
void handle_C2(); void handle_C2();
void handle_rtmp(); void handle_rtmp();
void handle_rtmpChunk(RtmpPacket &chunkData); void handle_rtmpChunk(RtmpPacket &chunkData);
private: private:
////////////ChunkSize//////////// ////////////ChunkSize////////////
size_t _iChunkLenIn = DEFAULT_CHUNK_LEN; size_t _iChunkLenIn = DEFAULT_CHUNK_LEN;
size_t _iChunkLenOut = DEFAULT_CHUNK_LEN; size_t _iChunkLenOut = DEFAULT_CHUNK_LEN;
////////////Acknowledgement//////////// ////////////Acknowledgement////////////
uint32_t _ui32ByteSent = 0; uint32_t _ui32ByteSent = 0;
uint32_t _ui32LastSent = 0; uint32_t _ui32LastSent = 0;
uint32_t _ui32WinSize = 0; uint32_t _ui32WinSize = 0;
///////////PeerBandwidth/////////// ///////////PeerBandwidth///////////
uint32_t _ui32Bandwidth = 2500000; uint32_t _ui32Bandwidth = 2500000;
uint8_t _ui8LimitType = 2; uint8_t _ui8LimitType = 2;
////////////Chunk//////////// ////////////Chunk////////////
unordered_map<int, RtmpPacket> _mapChunkData; unordered_map<int, RtmpPacket> _mapChunkData;
//////////Rtmp parser////////// //////////Rtmp parser//////////
string _strRcvBuf; string _strRcvBuf;
function<void()> _nextHandle; function<void()> _nextHandle;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -36,66 +36,66 @@ namespace mediakit { ...@@ -36,66 +36,66 @@ namespace mediakit {
class RtmpPusher: public RtmpProtocol , public TcpClient , public PusherBase{ class RtmpPusher: public RtmpProtocol , public TcpClient , public PusherBase{
public: public:
typedef std::shared_ptr<RtmpPusher> Ptr; typedef std::shared_ptr<RtmpPusher> Ptr;
RtmpPusher(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &src); RtmpPusher(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &src);
virtual ~RtmpPusher(); virtual ~RtmpPusher();
void publish(const string &strUrl) override ; void publish(const string &strUrl) override ;
void teardown() override; void teardown() override;
void setOnPublished(const Event &cb) override { void setOnPublished(const Event &cb) override {
_onPublished = cb; _onPublished = cb;
} }
void setOnShutdown(const Event &cb) override{ void setOnShutdown(const Event &cb) override{
_onShutdown = cb; _onShutdown = cb;
} }
protected: protected:
//for Tcpclient override //for Tcpclient override
void onRecv(const Buffer::Ptr &pBuf) override; void onRecv(const Buffer::Ptr &pBuf) override;
void onConnect(const SockException &err) override; void onConnect(const SockException &err) override;
void onErr(const SockException &ex) override; void onErr(const SockException &ex) override;
//for RtmpProtocol override //for RtmpProtocol override
void onRtmpChunk(RtmpPacket &chunkData) override; void onRtmpChunk(RtmpPacket &chunkData) override;
void onSendRawData(const Buffer::Ptr &buffer) override{ void onSendRawData(const Buffer::Ptr &buffer) override{
send(buffer); send(buffer);
} }
private: private:
void onPublishResult(const SockException &ex,bool handshakeCompleted); void onPublishResult(const SockException &ex,bool handshakeCompleted);
template<typename FUN> template<typename FUN>
inline void addOnResultCB(const FUN &fun) { inline void addOnResultCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(_mtxOnResultCB); lock_guard<recursive_mutex> lck(_mtxOnResultCB);
_mapOnResultCB.emplace(_iReqID, fun); _mapOnResultCB.emplace(_iReqID, fun);
} }
template<typename FUN> template<typename FUN>
inline void addOnStatusCB(const FUN &fun) { inline void addOnStatusCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(_mtxOnStatusCB); lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
_dqOnStatusCB.emplace_back(fun); _dqOnStatusCB.emplace_back(fun);
} }
void onCmd_result(AMFDecoder &dec); void onCmd_result(AMFDecoder &dec);
void onCmd_onStatus(AMFDecoder &dec); void onCmd_onStatus(AMFDecoder &dec);
void onCmd_onMetaData(AMFDecoder &dec); void onCmd_onMetaData(AMFDecoder &dec);
inline void send_connect(); inline void send_connect();
inline void send_createStream(); inline void send_createStream();
inline void send_publish(); inline void send_publish();
inline void send_metaData(); inline void send_metaData();
void setSocketFlags(); void setSocketFlags();
private: private:
string _strApp; string _strApp;
string _strStream; string _strStream;
string _strTcUrl; string _strTcUrl;
unordered_map<int, function<void(AMFDecoder &dec)> > _mapOnResultCB; unordered_map<int, function<void(AMFDecoder &dec)> > _mapOnResultCB;
recursive_mutex _mtxOnResultCB; recursive_mutex _mtxOnResultCB;
deque<function<void(AMFValue &dec)> > _dqOnStatusCB; deque<function<void(AMFValue &dec)> > _dqOnStatusCB;
recursive_mutex _mtxOnStatusCB; recursive_mutex _mtxOnStatusCB;
//超时功能实现 //超时功能实现
std::shared_ptr<Timer> _pPublishTimer; std::shared_ptr<Timer> _pPublishTimer;
//源 //源
std::weak_ptr<RtmpMediaSource> _pMediaSrc; std::weak_ptr<RtmpMediaSource> _pMediaSrc;
RtmpMediaSource::RingType::RingReader::Ptr _pRtmpReader; RtmpMediaSource::RingType::RingReader::Ptr _pRtmpReader;
......
...@@ -45,65 +45,65 @@ namespace mediakit { ...@@ -45,65 +45,65 @@ namespace mediakit {
class RtmpSession: public TcpSession ,public RtmpProtocol , public MediaSourceEvent{ class RtmpSession: public TcpSession ,public RtmpProtocol , public MediaSourceEvent{
public: public:
typedef std::shared_ptr<RtmpSession> Ptr; typedef std::shared_ptr<RtmpSession> Ptr;
RtmpSession(const Socket::Ptr &_sock); RtmpSession(const Socket::Ptr &_sock);
virtual ~RtmpSession(); virtual ~RtmpSession();
void onRecv(const Buffer::Ptr &pBuf) override; void onRecv(const Buffer::Ptr &pBuf) override;
void onError(const SockException &err) override; void onError(const SockException &err) override;
void onManager() override; void onManager() override;
private: private:
void onProcessCmd(AMFDecoder &dec); void onProcessCmd(AMFDecoder &dec);
void onCmd_connect(AMFDecoder &dec); void onCmd_connect(AMFDecoder &dec);
void onCmd_createStream(AMFDecoder &dec); void onCmd_createStream(AMFDecoder &dec);
void onCmd_publish(AMFDecoder &dec); void onCmd_publish(AMFDecoder &dec);
void onCmd_deleteStream(AMFDecoder &dec); void onCmd_deleteStream(AMFDecoder &dec);
void onCmd_play(AMFDecoder &dec); void onCmd_play(AMFDecoder &dec);
void onCmd_play2(AMFDecoder &dec); void onCmd_play2(AMFDecoder &dec);
void doPlay(AMFDecoder &dec); void doPlay(AMFDecoder &dec);
void doPlayResponse(const string &err,const std::function<void(bool)> &cb); void doPlayResponse(const string &err,const std::function<void(bool)> &cb);
void sendPlayResponse(const string &err,const RtmpMediaSource::Ptr &src); void sendPlayResponse(const string &err,const RtmpMediaSource::Ptr &src);
void onCmd_seek(AMFDecoder &dec); void onCmd_seek(AMFDecoder &dec);
void onCmd_pause(AMFDecoder &dec); void onCmd_pause(AMFDecoder &dec);
void setMetaData(AMFDecoder &dec); void setMetaData(AMFDecoder &dec);
void onSendMedia(const RtmpPacket::Ptr &pkt); void onSendMedia(const RtmpPacket::Ptr &pkt);
void onSendRawData(const Buffer::Ptr &buffer) override{ void onSendRawData(const Buffer::Ptr &buffer) override{
_ui64TotalBytes += buffer->size(); _ui64TotalBytes += buffer->size();
send(buffer); send(buffer);
} }
void onRtmpChunk(RtmpPacket &chunkData) override; void onRtmpChunk(RtmpPacket &chunkData) override;
template<typename first, typename second> template<typename first, typename second>
inline void sendReply(const char *str, const first &reply, const second &status) { inline void sendReply(const char *str, const first &reply, const second &status) {
AMFEncoder invoke; AMFEncoder invoke;
invoke << str << _dNowReqID << reply << status; invoke << str << _dNowReqID << reply << status;
sendResponse(MSG_CMD, invoke.data()); sendResponse(MSG_CMD, invoke.data());
} }
//MediaSourceEvent override //MediaSourceEvent override
bool close(MediaSource &sender,bool force) override ; bool close(MediaSource &sender,bool force) override ;
void onNoneReader(MediaSource &sender) override; void onNoneReader(MediaSource &sender) override;
int totalReaderCount(MediaSource &sender) override; int totalReaderCount(MediaSource &sender) override;
void setSocketFlags(); void setSocketFlags();
string getStreamId(const string &str); string getStreamId(const string &str);
void dumpMetadata(const AMFValue &metadata); void dumpMetadata(const AMFValue &metadata);
private: private:
std::string _strTcUrl; std::string _strTcUrl;
MediaInfo _mediaInfo; MediaInfo _mediaInfo;
double _dNowReqID = 0; double _dNowReqID = 0;
bool _set_meta_data = false; bool _set_meta_data = false;
Ticker _ticker;//数据接收时间 Ticker _ticker;//数据接收时间
RingBuffer<RtmpPacket::Ptr>::RingReader::Ptr _pRingReader; RingBuffer<RtmpPacket::Ptr>::RingReader::Ptr _pRingReader;
std::shared_ptr<RtmpMediaSourceImp> _pPublisherSrc; std::shared_ptr<RtmpMediaSourceImp> _pPublisherSrc;
std::weak_ptr<RtmpMediaSource> _pPlayerSrc; std::weak_ptr<RtmpMediaSource> _pPlayerSrc;
//时间戳修整器 //时间戳修整器
Stamp _stamp[2]; Stamp _stamp[2];
//消耗的总流量 //消耗的总流量
uint64_t _ui64TotalBytes = 0; uint64_t _ui64TotalBytes = 0;
}; };
......
...@@ -36,15 +36,15 @@ ...@@ -36,15 +36,15 @@
using namespace std; using namespace std;
enum AMFType { enum AMFType {
AMF_NUMBER, AMF_NUMBER,
AMF_INTEGER, AMF_INTEGER,
AMF_BOOLEAN, AMF_BOOLEAN,
AMF_STRING, AMF_STRING,
AMF_OBJECT, AMF_OBJECT,
AMF_NULL, AMF_NULL,
AMF_UNDEFINED, AMF_UNDEFINED,
AMF_ECMA_ARRAY, AMF_ECMA_ARRAY,
AMF_STRICT_ARRAY, AMF_STRICT_ARRAY,
}; };
class AMFValue; class AMFValue;
...@@ -55,79 +55,79 @@ public: ...@@ -55,79 +55,79 @@ public:
typedef std::map<std::string, AMFValue> mapType; typedef std::map<std::string, AMFValue> mapType;
typedef std::vector<AMFValue> arrayType; typedef std::vector<AMFValue> arrayType;
AMFValue(AMFType type = AMF_NULL); AMFValue(AMFType type = AMF_NULL);
AMFValue(const char *s); AMFValue(const char *s);
AMFValue(const std::string &s); AMFValue(const std::string &s);
AMFValue(double n); AMFValue(double n);
AMFValue(int i); AMFValue(int i);
AMFValue(bool b); AMFValue(bool b);
AMFValue(const AMFValue &from); AMFValue(const AMFValue &from);
AMFValue(AMFValue &&from); AMFValue(AMFValue &&from);
AMFValue &operator =(const AMFValue &from); AMFValue &operator =(const AMFValue &from);
AMFValue &operator =(AMFValue &&from); AMFValue &operator =(AMFValue &&from);
~AMFValue(); ~AMFValue();
void clear(); void clear();
AMFType type() const ; AMFType type() const ;
const std::string &as_string() const; const std::string &as_string() const;
double as_number() const; double as_number() const;
int as_integer() const; int as_integer() const;
bool as_boolean() const; bool as_boolean() const;
string to_string() const; string to_string() const;
const AMFValue &operator[](const char *str) const; const AMFValue &operator[](const char *str) const;
void object_for_each(const function<void(const string &key, const AMFValue &val)> &fun) const ; void object_for_each(const function<void(const string &key, const AMFValue &val)> &fun) const ;
operator bool() const; operator bool() const;
void set(const std::string &s, const AMFValue &val); void set(const std::string &s, const AMFValue &val);
void add(const AMFValue &val); void add(const AMFValue &val);
private: private:
const mapType &getMap() const; const mapType &getMap() const;
const arrayType &getArr() const; const arrayType &getArr() const;
void destroy(); void destroy();
void init(); void init();
private: private:
AMFType _type; AMFType _type;
union { union {
std::string *string; std::string *string;
double number; double number;
int integer; int integer;
bool boolean; bool boolean;
mapType *object; mapType *object;
arrayType *array; arrayType *array;
} _value; } _value;
}; };
class AMFDecoder { class AMFDecoder {
public: public:
AMFDecoder(const std::string &buf, size_t pos, int version = 0); AMFDecoder(const std::string &buf, size_t pos, int version = 0);
template<typename TP> template<typename TP>
TP load(); TP load();
private: private:
std::string load_key(); std::string load_key();
AMFValue load_object(); AMFValue load_object();
AMFValue load_ecma(); AMFValue load_ecma();
AMFValue load_arr(); AMFValue load_arr();
uint8_t front(); uint8_t front();
uint8_t pop_front(); uint8_t pop_front();
private: private:
const std::string &buf; const std::string &buf;
size_t pos; size_t pos;
int version; int version;
}; };
class AMFEncoder { class AMFEncoder {
public: public:
AMFEncoder & operator <<(const char *s); AMFEncoder & operator <<(const char *s);
AMFEncoder & operator <<(const std::string &s); AMFEncoder & operator <<(const std::string &s);
AMFEncoder & operator <<(std::nullptr_t); AMFEncoder & operator <<(std::nullptr_t);
AMFEncoder & operator <<(const int n); AMFEncoder & operator <<(const int n);
AMFEncoder & operator <<(const double n); AMFEncoder & operator <<(const double n);
AMFEncoder & operator <<(const bool b); AMFEncoder & operator <<(const bool b);
AMFEncoder & operator <<(const AMFValue &value); AMFEncoder & operator <<(const AMFValue &value);
const std::string& data() const ; const std::string& data() const ;
void clear() ; void clear() ;
private: private:
void write_key(const std::string &s); void write_key(const std::string &s);
AMFEncoder &write_undefined(); AMFEncoder &write_undefined();
private: private:
std::string buf; std::string buf;
}; };
......
...@@ -38,54 +38,54 @@ using namespace toolkit; ...@@ -38,54 +38,54 @@ using namespace toolkit;
*/ */
uint32_t load_be32(const void *p) uint32_t load_be32(const void *p)
{ {
uint32_t val; uint32_t val;
memcpy(&val, p, sizeof val); memcpy(&val, p, sizeof val);
return ntohl(val); return ntohl(val);
} }
uint16_t load_be16(const void *p) uint16_t load_be16(const void *p)
{ {
uint16_t val; uint16_t val;
memcpy(&val, p, sizeof val); memcpy(&val, p, sizeof val);
return ntohs(val); return ntohs(val);
} }
uint32_t load_le32(const void *p) uint32_t load_le32(const void *p)
{ {
const uint8_t *data = (const uint8_t *) p; const uint8_t *data = (const uint8_t *) p;
return data[0] | ((uint32_t) data[1] << 8) | return data[0] | ((uint32_t) data[1] << 8) |
((uint32_t) data[2] << 16) | ((uint32_t) data[3] << 24); ((uint32_t) data[2] << 16) | ((uint32_t) data[3] << 24);
} }
uint32_t load_be24(const void *p) uint32_t load_be24(const void *p)
{ {
const uint8_t *data = (const uint8_t *) p; const uint8_t *data = (const uint8_t *) p;
return data[2] | ((uint32_t) data[1] << 8) | ((uint32_t) data[0] << 16); return data[2] | ((uint32_t) data[1] << 8) | ((uint32_t) data[0] << 16);
} }
void set_be24(void *p, uint32_t val) void set_be24(void *p, uint32_t val)
{ {
uint8_t *data = (uint8_t *) p; uint8_t *data = (uint8_t *) p;
data[0] = val >> 16; data[0] = val >> 16;
data[1] = val >> 8; data[1] = val >> 8;
data[2] = val; data[2] = val;
} }
void set_le32(void *p, uint32_t val) void set_le32(void *p, uint32_t val)
{ {
uint8_t *data = (uint8_t *) p; uint8_t *data = (uint8_t *) p;
data[0] = val; data[0] = val;
data[1] = val >> 8; data[1] = val >> 8;
data[2] = val >> 16; data[2] = val >> 16;
data[3] = val >> 24; data[3] = val >> 24;
} }
void set_be32(void *p, uint32_t val) void set_be32(void *p, uint32_t val)
{ {
uint8_t *data = (uint8_t *) p; uint8_t *data = (uint8_t *) p;
data[3] = val; data[3] = val;
data[2] = val >> 8; data[2] = val >> 8;
data[1] = val >> 16; data[1] = val >> 16;
data[0] = val >> 24; data[0] = val >> 24;
} }
...@@ -37,47 +37,47 @@ using namespace toolkit; ...@@ -37,47 +37,47 @@ using namespace toolkit;
namespace mediakit{ namespace mediakit{
MultiCastAddressMaker &MultiCastAddressMaker::Instance() { MultiCastAddressMaker &MultiCastAddressMaker::Instance() {
static MultiCastAddressMaker instance; static MultiCastAddressMaker instance;
return instance; return instance;
} }
static uint32_t addressToInt(const string &ip){ static uint32_t addressToInt(const string &ip){
struct in_addr addr; struct in_addr addr;
bzero(&addr,sizeof(addr)); bzero(&addr,sizeof(addr));
addr.s_addr = inet_addr(ip.data()); addr.s_addr = inet_addr(ip.data());
return (uint32_t)ntohl((uint32_t &)addr.s_addr); return (uint32_t)ntohl((uint32_t &)addr.s_addr);
} }
std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) { std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
lock_guard<recursive_mutex> lck(_mtx); lock_guard<recursive_mutex> lck(_mtx);
GET_CONFIG(string,addrMinStr,MultiCast::kAddrMin); GET_CONFIG(string,addrMinStr,MultiCast::kAddrMin);
GET_CONFIG(string,addrMaxStr,MultiCast::kAddrMax); GET_CONFIG(string,addrMaxStr,MultiCast::kAddrMax);
uint32_t addrMin = addressToInt(addrMinStr); uint32_t addrMin = addressToInt(addrMinStr);
uint32_t addrMax = addressToInt(addrMaxStr); uint32_t addrMax = addressToInt(addrMaxStr);
if(_iAddr > addrMax || _iAddr == 0){ if(_iAddr > addrMax || _iAddr == 0){
_iAddr = addrMin; _iAddr = addrMin;
} }
auto iGotAddr = _iAddr++; auto iGotAddr = _iAddr++;
if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){ if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){
//已经分配过了 //已经分配过了
if(iTry){ if(iTry){
return obtain(--iTry); return obtain(--iTry);
} }
//分配完了,应该不可能到这里 //分配完了,应该不可能到这里
ErrorL; ErrorL;
return nullptr; return nullptr;
} }
_setBadAddr.emplace(iGotAddr); _setBadAddr.emplace(iGotAddr);
std::shared_ptr<uint32_t> ret(new uint32_t(iGotAddr),[](uint32_t *ptr){ std::shared_ptr<uint32_t> ret(new uint32_t(iGotAddr),[](uint32_t *ptr){
MultiCastAddressMaker::Instance().release(*ptr); MultiCastAddressMaker::Instance().release(*ptr);
delete ptr; delete ptr;
}); });
return ret; return ret;
} }
void MultiCastAddressMaker::release(uint32_t iAddr){ void MultiCastAddressMaker::release(uint32_t iAddr){
lock_guard<recursive_mutex> lck(_mtx); lock_guard<recursive_mutex> lck(_mtx);
_setBadAddr.erase(iAddr); _setBadAddr.erase(iAddr);
} }
...@@ -85,106 +85,106 @@ recursive_mutex RtpMultiCaster::g_mtx; ...@@ -85,106 +85,106 @@ recursive_mutex RtpMultiCaster::g_mtx;
unordered_map<string, weak_ptr<RtpMultiCaster> > RtpMultiCaster::g_mapBroadCaster; unordered_map<string, weak_ptr<RtpMultiCaster> > RtpMultiCaster::g_mapBroadCaster;
void RtpMultiCaster::setDetachCB(void* listener, const onDetach& cb) { void RtpMultiCaster::setDetachCB(void* listener, const onDetach& cb) {
lock_guard<recursive_mutex> lck(_mtx); lock_guard<recursive_mutex> lck(_mtx);
if(cb){ if(cb){
_mapDetach.emplace(listener,cb); _mapDetach.emplace(listener,cb);
}else{ }else{
_mapDetach.erase(listener); _mapDetach.erase(listener);
} }
} }
RtpMultiCaster::~RtpMultiCaster() { RtpMultiCaster::~RtpMultiCaster() {
_pReader->setReadCB(nullptr); _pReader->setReadCB(nullptr);
_pReader->setDetachCB(nullptr); _pReader->setDetachCB(nullptr);
DebugL; DebugL;
} }
RtpMultiCaster::RtpMultiCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) { RtpMultiCaster::RtpMultiCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
auto src = dynamic_pointer_cast<RtspMediaSource>(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream)); auto src = dynamic_pointer_cast<RtspMediaSource>(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream));
if(!src){ if(!src){
auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl; auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl;
throw std::runtime_error(strErr); throw std::runtime_error(strErr);
} }
_multiAddr = MultiCastAddressMaker::Instance().obtain(); _multiAddr = MultiCastAddressMaker::Instance().obtain();
for(auto i = 0; i < 2; i++){ for(auto i = 0; i < 2; i++){
_apUdpSock[i].reset(new Socket(poller)); _apUdpSock[i].reset(new Socket(poller));
if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){ if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){
auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl; auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl;
throw std::runtime_error(strErr); throw std::runtime_error(strErr);
} }
auto fd = _apUdpSock[i]->rawFD(); auto fd = _apUdpSock[i]->rawFD();
GET_CONFIG(uint32_t,udpTTL,MultiCast::kUdpTTL); GET_CONFIG(uint32_t,udpTTL,MultiCast::kUdpTTL);
SockUtil::setMultiTTL(fd, udpTTL); SockUtil::setMultiTTL(fd, udpTTL);
SockUtil::setMultiLOOP(fd, false); SockUtil::setMultiLOOP(fd, false);
SockUtil::setMultiIF(fd, strLocalIp.data()); SockUtil::setMultiIF(fd, strLocalIp.data());
struct sockaddr_in &peerAddr = _aPeerUdpAddr[i]; struct sockaddr_in &peerAddr = _aPeerUdpAddr[i];
peerAddr.sin_family = AF_INET; peerAddr.sin_family = AF_INET;
peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port()); peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port());
peerAddr.sin_addr.s_addr = htonl(*_multiAddr); peerAddr.sin_addr.s_addr = htonl(*_multiAddr);
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero); bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
_apUdpSock[i]->setSendPeerAddr((struct sockaddr *)&peerAddr); _apUdpSock[i]->setSendPeerAddr((struct sockaddr *)&peerAddr);
} }
_pReader = src->getRing()->attach(poller); _pReader = src->getRing()->attach(poller);
_pReader->setReadCB([this](const RtpPacket::Ptr &pkt){ _pReader->setReadCB([this](const RtpPacket::Ptr &pkt){
int i = (int)(pkt->type); int i = (int)(pkt->type);
auto &pSock = _apUdpSock[i]; auto &pSock = _apUdpSock[i];
auto &peerAddr = _aPeerUdpAddr[i]; auto &peerAddr = _aPeerUdpAddr[i];
BufferRtp::Ptr buffer(new BufferRtp(pkt,4)); BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
pSock->send(buffer); pSock->send(buffer);
}); });
_pReader->setDetachCB([this](){ _pReader->setDetachCB([this](){
unordered_map<void * , onDetach > _mapDetach_copy; unordered_map<void * , onDetach > _mapDetach_copy;
{ {
lock_guard<recursive_mutex> lck(_mtx); lock_guard<recursive_mutex> lck(_mtx);
_mapDetach_copy = std::move(_mapDetach); _mapDetach_copy = std::move(_mapDetach);
} }
for(auto &pr : _mapDetach_copy){ for(auto &pr : _mapDetach_copy){
pr.second(); pr.second();
} }
}); });
DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " " DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " "
<< _apUdpSock[0]->get_local_port() << " " << _apUdpSock[0]->get_local_port() << " "
<< _apUdpSock[1]->get_local_port() << " " << _apUdpSock[1]->get_local_port() << " "
<< strVhost << " " << strVhost << " "
<< strApp << " " << strStream; << strApp << " " << strStream;
} }
uint16_t RtpMultiCaster::getPort(TrackType trackType){ uint16_t RtpMultiCaster::getPort(TrackType trackType){
return _apUdpSock[trackType]->get_local_port(); return _apUdpSock[trackType]->get_local_port();
} }
string RtpMultiCaster::getIP(){ string RtpMultiCaster::getIP(){
return inet_ntoa(_aPeerUdpAddr[0].sin_addr); return inet_ntoa(_aPeerUdpAddr[0].sin_addr);
} }
RtpMultiCaster::Ptr RtpMultiCaster::make(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream){ RtpMultiCaster::Ptr RtpMultiCaster::make(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream){
try{ try{
auto ret = Ptr(new RtpMultiCaster(poller,strLocalIp,strVhost,strApp,strStream),[poller](RtpMultiCaster *ptr){ auto ret = Ptr(new RtpMultiCaster(poller,strLocalIp,strVhost,strApp,strStream),[poller](RtpMultiCaster *ptr){
poller->async([ptr]() { poller->async([ptr]() {
delete ptr; delete ptr;
}); });
}); });
lock_guard<recursive_mutex> lck(g_mtx); lock_guard<recursive_mutex> lck(g_mtx);
string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl; string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl;
weak_ptr<RtpMultiCaster> weakPtr = ret; weak_ptr<RtpMultiCaster> weakPtr = ret;
g_mapBroadCaster.emplace(strKey,weakPtr); g_mapBroadCaster.emplace(strKey,weakPtr);
return ret; return ret;
}catch (std::exception &ex) { }catch (std::exception &ex) {
WarnL << ex.what(); WarnL << ex.what();
return nullptr; return nullptr;
} }
} }
RtpMultiCaster::Ptr RtpMultiCaster::get(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) { RtpMultiCaster::Ptr RtpMultiCaster::get(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl; string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl;
lock_guard<recursive_mutex> lck(g_mtx); lock_guard<recursive_mutex> lck(g_mtx);
auto it = g_mapBroadCaster.find(strKey); auto it = g_mapBroadCaster.find(strKey);
if (it == g_mapBroadCaster.end()) { if (it == g_mapBroadCaster.end()) {
return make(poller,strLocalIp,strVhost,strApp, strStream); return make(poller,strLocalIp,strVhost,strApp, strStream);
} }
auto ret = it->second.lock(); auto ret = it->second.lock();
if (!ret) { if (!ret) {
g_mapBroadCaster.erase(it); g_mapBroadCaster.erase(it);
return make(poller,strLocalIp,strVhost,strApp, strStream); return make(poller,strLocalIp,strVhost,strApp, strStream);
} }
return ret; return ret;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论