diff --git a/3rdpart/ZLToolKit b/3rdpart/ZLToolKit index 34b42499..d985d49f 160000 --- a/3rdpart/ZLToolKit +++ b/3rdpart/ZLToolKit @@ -1 +1 @@ -Subproject commit 34b42499ce9ee055b5c7cac9a270239984d0e839 +Subproject commit d985d49f28b441216bf50020b7c6587edb5f43dc diff --git a/api/include/mk_common.h b/api/include/mk_common.h index 08100f69..3706b712 100755 --- a/api/include/mk_common.h +++ b/api/include/mk_common.h @@ -31,12 +31,12 @@ #if defined(_WIN32) #if defined(MediaKitApi_EXPORTS) - #define API_EXPORT __declspec(dllexport) - #else - #define API_EXPORT __declspec(dllimport) - #endif + #define API_EXPORT __declspec(dllexport) + #else + #define API_EXPORT __declspec(dllimport) + #endif - #define API_CALL __cdecl + #define API_CALL __cdecl #else #define API_EXPORT #define API_CALL diff --git a/api/source/mk_player.cpp b/api/source/mk_player.cpp index 75c556ac..e3f664ac 100755 --- a/api/source/mk_player.cpp +++ b/api/source/mk_player.cpp @@ -32,41 +32,41 @@ using namespace toolkit; using namespace mediakit; API_EXPORT mk_player API_CALL mk_player_create() { - MediaPlayer::Ptr *obj = new MediaPlayer::Ptr(new MediaPlayer()); - return obj; + MediaPlayer::Ptr *obj = new MediaPlayer::Ptr(new MediaPlayer()); + return obj; } API_EXPORT void API_CALL mk_player_release(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr *obj = (MediaPlayer::Ptr *)ctx; - delete obj; + assert(ctx); + MediaPlayer::Ptr *obj = (MediaPlayer::Ptr *)ctx; + delete obj; } API_EXPORT void API_CALL mk_player_set_option(mk_player ctx,const char* key,const char *val){ - assert(ctx && key && val); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - string key_str(key), val_str(val); - player->getPoller()->async([key_str,val_str,player](){ - //切换线程后再操作 - (*player)[key_str] = val_str; - }); + assert(ctx && key && val); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + string key_str(key), val_str(val); + player->getPoller()->async([key_str,val_str,player](){ + //切换线程后再操作 + (*player)[key_str] = val_str; + }); } API_EXPORT void API_CALL mk_player_play(mk_player ctx, const char *url) { - assert(ctx && url); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - string url_str(url); - player->getPoller()->async([url_str,player](){ - //切换线程后再操作 - player->play(url_str); - }); + assert(ctx && url); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + string url_str(url); + player->getPoller()->async([url_str,player](){ + //切换线程后再操作 + player->play(url_str); + }); } API_EXPORT void API_CALL mk_player_pause(mk_player ctx, int pause) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - player->getPoller()->async([pause,player](){ - //切换线程后再操作 - player->pause(pause); - }); + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + player->getPoller()->async([pause,player](){ + //切换线程后再操作 + player->pause(pause); + }); } 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) { - assert(ctx && cb); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - player->getPoller()->async([cb,user_data,type,player](){ - //切换线程后再操作 - if(type == 0){ - player->setOnPlayResult([cb,user_data](const SockException &ex){ - cb(user_data,ex.getErrCode(),ex.what()); - }); - }else{ - player->setOnShutdown([cb,user_data](const SockException &ex){ - cb(user_data,ex.getErrCode(),ex.what()); - }); - } - }); + assert(ctx && cb); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + player->getPoller()->async([cb,user_data,type,player](){ + //切换线程后再操作 + if(type == 0){ + player->setOnPlayResult([cb,user_data](const SockException &ex){ + cb(user_data,ex.getErrCode(),ex.what()); + }); + }else{ + player->setOnShutdown([cb,user_data](const SockException &ex){ + 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) { - 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) { - 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) { - assert(ctx && cb); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - player->getPoller()->async([player,cb,user_data](){ - //切换线程后再操作 - auto delegate = std::make_shared([cb,user_data](const Frame::Ptr &frame){ - cb(user_data,frame->getTrackType(),frame->getCodecId(),frame->data(),frame->size(),frame->dts(),frame->pts()); - }); - for(auto &track : player->getTracks()){ - track->addDelegate(delegate); - } - }); + assert(ctx && cb); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + player->getPoller()->async([player,cb,user_data](){ + //切换线程后再操作 + auto delegate = std::make_shared([cb,user_data](const Frame::Ptr &frame){ + cb(user_data,frame->getTrackType(),frame->getCodecId(),frame->data(),frame->size(),frame->dts(),frame->pts()); + }); + for(auto &track : player->getTracks()){ + track->addDelegate(delegate); + } + }); } API_EXPORT int API_CALL mk_player_video_width(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - auto track = dynamic_pointer_cast(player->getTrack(TrackVideo)); - return track ? track->getVideoWidth() : 0; + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + auto track = dynamic_pointer_cast(player->getTrack(TrackVideo)); + return track ? track->getVideoWidth() : 0; } API_EXPORT int API_CALL mk_player_video_height(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - auto track = dynamic_pointer_cast(player->getTrack(TrackVideo)); - return track ? track->getVideoHeight() : 0; + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + auto track = dynamic_pointer_cast(player->getTrack(TrackVideo)); + return track ? track->getVideoHeight() : 0; } API_EXPORT int API_CALL mk_player_video_fps(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - auto track = dynamic_pointer_cast(player->getTrack(TrackVideo)); - return track ? track->getVideoFps() : 0; + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + auto track = dynamic_pointer_cast(player->getTrack(TrackVideo)); + return track ? track->getVideoFps() : 0; } API_EXPORT int API_CALL mk_player_audio_samplerate(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - auto track = dynamic_pointer_cast(player->getTrack(TrackAudio)); - return track ? track->getAudioSampleRate() : 0; + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + auto track = dynamic_pointer_cast(player->getTrack(TrackAudio)); + return track ? track->getAudioSampleRate() : 0; } API_EXPORT int API_CALL mk_player_audio_bit(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - auto track = dynamic_pointer_cast(player->getTrack(TrackAudio)); - return track ? track->getAudioSampleBit() : 0; + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + auto track = dynamic_pointer_cast(player->getTrack(TrackAudio)); + return track ? track->getAudioSampleBit() : 0; } API_EXPORT int API_CALL mk_player_audio_channel(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - auto track = dynamic_pointer_cast(player->getTrack(TrackAudio)); - return track ? track->getAudioChannel() : 0; + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + auto track = dynamic_pointer_cast(player->getTrack(TrackAudio)); + return track ? track->getAudioChannel() : 0; } API_EXPORT float API_CALL mk_player_duration(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - return player->getDuration(); + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + return player->getDuration(); } API_EXPORT float API_CALL mk_player_progress(mk_player ctx) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - return player->getProgress(); + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + return player->getProgress(); } API_EXPORT float API_CALL mk_player_loss_rate(mk_player ctx, int track_type) { - assert(ctx); - MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); - return player->getPacketLossRate((TrackType)track_type); + assert(ctx); + MediaPlayer::Ptr &player = *((MediaPlayer::Ptr *)ctx); + return player->getPacketLossRate((TrackType)track_type); } diff --git a/server/FFmpegSource.cpp b/server/FFmpegSource.cpp index d8a821c6..e0e210d2 100644 --- a/server/FFmpegSource.cpp +++ b/server/FFmpegSource.cpp @@ -42,7 +42,7 @@ onceToken token([]() { //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 "; #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 "; #endif //默认ffmpeg命令路径为环境变量中路径 diff --git a/server/Process.cpp b/server/Process.cpp index eb8eac4d..1c5e91ee 100644 --- a/server/Process.cpp +++ b/server/Process.cpp @@ -46,92 +46,92 @@ using namespace toolkit; void Process::run(const string &cmd, const string &log_file_tmp) { - kill(2000); + kill(2000); #ifdef _WIN32 - STARTUPINFO si; - PROCESS_INFORMATION pi; - ZeroMemory(&si, sizeof(si)); //结构体初始化; - ZeroMemory(&pi, sizeof(pi)); + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory(&si, sizeof(si)); //结构体初始化; + ZeroMemory(&pi, sizeof(pi)); - LPTSTR lpDir = const_cast(cmd.data()); + LPTSTR lpDir = const_cast(cmd.data()); - if (CreateProcess(NULL, lpDir, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ - //下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程 - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + if (CreateProcess(NULL, lpDir, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){ + //下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程 + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); - _pid = pi.dwProcessId; - InfoL << "start child proces " << _pid; - } else { - WarnL << "start child proces fail: " << GetLastError(); - } + _pid = pi.dwProcessId; + InfoL << "start child proces " << _pid; + } else { + WarnL << "start child proces fail: " << GetLastError(); + } #else - _pid = fork(); - if (_pid < 0) { - throw std::runtime_error(StrPrinter << "fork child process falied,err:" << get_uv_errmsg()); - } - if (_pid == 0) { - //子进程关闭core文件生成 - struct rlimit rlim = { 0,0 }; - setrlimit(RLIMIT_CORE, &rlim); + _pid = fork(); + if (_pid < 0) { + throw std::runtime_error(StrPrinter << "fork child process falied,err:" << get_uv_errmsg()); + } + if (_pid == 0) { + //子进程关闭core文件生成 + struct rlimit rlim = { 0,0 }; + setrlimit(RLIMIT_CORE, &rlim); - //在启动子进程时,暂时禁用SIGINT、SIGTERM信号 - // ignore the SIGINT and SIGTERM - signal(SIGINT, SIG_IGN); - signal(SIGTERM, SIG_IGN); + //在启动子进程时,暂时禁用SIGINT、SIGTERM信号 + // ignore the SIGINT and SIGTERM + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); - string log_file; - if (log_file_tmp.empty()) { - log_file = "/dev/null"; - } - else { - log_file = StrPrinter << log_file_tmp << "." << getpid(); - } + string log_file; + if (log_file_tmp.empty()) { + log_file = "/dev/null"; + } + else { + log_file = StrPrinter << log_file_tmp << "." << getpid(); + } - int log_fd = -1; - 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; - File::createfile_path(log_file.data(), mode); - 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)); - } - else { - // dup to stdout and stderr. - if (dup2(log_fd, STDOUT_FILENO) < 0) { - fprintf(stderr, "dup2 stdout file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno)); - } - if (dup2(log_fd, STDERR_FILENO) < 0) { - fprintf(stderr, "dup2 stderr file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno)); - } - // close log fd - ::close(log_fd); - } - fprintf(stderr, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", getpid(), cmd.data()); + int log_fd = -1; + 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; + File::createfile_path(log_file.data(), mode); + 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)); + } + else { + // dup to stdout and stderr. + if (dup2(log_fd, STDOUT_FILENO) < 0) { + fprintf(stderr, "dup2 stdout file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno)); + } + if (dup2(log_fd, STDERR_FILENO) < 0) { + fprintf(stderr, "dup2 stderr file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno)); + } + // close log fd + ::close(log_fd); + } + fprintf(stderr, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", getpid(), cmd.data()); - // close other fds - // TODO: do in right way. - for (int i = 3; i < 1024; i++) { - ::close(i); - } + // close other fds + // TODO: do in right way. + for (int i = 3; i < 1024; i++) { + ::close(i); + } - auto params = split(cmd, " "); - // memory leak in child process, it's ok. - char **charpv_params = new char *[params.size() + 1]; - for (int i = 0; i < (int)params.size(); i++) { - std::string &p = params[i]; - charpv_params[i] = (char *)p.data(); - } - // EOF: NULL - charpv_params[params.size()] = NULL; + auto params = split(cmd, " "); + // memory leak in child process, it's ok. + char **charpv_params = new char *[params.size() + 1]; + for (int i = 0; i < (int)params.size(); i++) { + std::string &p = params[i]; + charpv_params[i] = (char *)p.data(); + } + // EOF: NULL + charpv_params[params.size()] = NULL; - // TODO: execv or execvp - auto ret = execv(params[0].c_str(), charpv_params); - if (ret < 0) { - fprintf(stderr, "fork process failed, errno=%d(%s)\r\n", errno, strerror(errno)); - } - exit(ret); - } - InfoL << "start child proces " << _pid; + // TODO: execv or execvp + auto ret = execv(params[0].c_str(), charpv_params); + if (ret < 0) { + fprintf(stderr, "fork process failed, errno=%d(%s)\r\n", errno, strerror(errno)); + } + exit(ret); + } + InfoL << "start child proces " << _pid; #endif // _WIN32 } @@ -148,27 +148,27 @@ static bool s_wait(pid_t pid,int *exit_code_ptr,bool block) { } int status = 0; #ifdef _WIN32 - HANDLE hProcess = NULL; - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程 - if (hProcess == NULL) { - return false; - } + HANDLE hProcess = NULL; + hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程 + if (hProcess == NULL) { + return false; + } - CloseHandle(hProcess); + CloseHandle(hProcess); #else - pid_t p = waitpid(pid, &status, block ? 0 : WNOHANG); - int exit_code = (status & 0xFF00) >> 8; - if (exit_code_ptr) { - *exit_code_ptr = (status & 0xFF00) >> 8; - } - if (p < 0) { - WarnL << "waitpid failed, pid=" << pid << ", err=" << get_uv_errmsg(); - return false; - } - if (p > 0) { - InfoL << "process terminated, pid=" << pid << ", exit code=" << exit_code; - return false; - } + pid_t p = waitpid(pid, &status, block ? 0 : WNOHANG); + int exit_code = (status & 0xFF00) >> 8; + if (exit_code_ptr) { + *exit_code_ptr = (status & 0xFF00) >> 8; + } + if (p < 0) { + WarnL << "waitpid failed, pid=" << pid << ", err=" << get_uv_errmsg(); + return false; + } + if (p > 0) { + InfoL << "process terminated, pid=" << pid << ", exit code=" << exit_code; + return false; + } #endif // _WIN32 return true; @@ -180,22 +180,22 @@ static void s_kill(pid_t pid,int max_delay,bool force){ return; } #ifdef _WIN32 - HANDLE hProcess = NULL; - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程 - if (hProcess == NULL) { - WarnL << "\nOpen Process fAiled: " << GetLastError(); - return; - } - DWORD ret = TerminateProcess(hProcess, 0); //结束目标进程 - if (ret == 0) { - WarnL << GetLastError; - } + HANDLE hProcess = NULL; + hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程 + if (hProcess == NULL) { + WarnL << "\nOpen Process fAiled: " << GetLastError(); + return; + } + DWORD ret = TerminateProcess(hProcess, 0); //结束目标进程 + if (ret == 0) { + WarnL << GetLastError; + } #else - if (::kill(pid, force ? SIGKILL : SIGTERM) == -1) { - //进程可能已经退出了 - WarnL << "kill process " << pid << " failed:" << get_uv_errmsg(); - return; - } + if (::kill(pid, force ? SIGKILL : SIGTERM) == -1) { + //进程可能已经退出了 + WarnL << "kill process " << pid << " failed:" << get_uv_errmsg(); + return; + } #endif // _WIN32 diff --git a/server/WebApi.cpp b/server/WebApi.cpp index e72d36ec..abd0d57f 100644 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -774,9 +774,9 @@ void installWebApi() { val["status"] = (int)status; }); - //获取录像文件夹列表或mp4文件列表 - //http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01 - api_regist1("/index/api/getMp4RecordFile", [](API_ARGS1){ + //获取录像文件夹列表或mp4文件列表 + //http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01 + api_regist1("/index/api/getMp4RecordFile", [](API_ARGS1){ CHECK_SECRET(); CHECK_ARGS("vhost", "app", "stream"); auto record_path = Recorder::getRecordPath(Recorder::type_mp4, allArgs["vhost"], allArgs["app"],allArgs["stream"]); @@ -809,7 +809,7 @@ void installWebApi() { val["data"]["rootPath"] = record_path; val["data"]["paths"] = paths; - }); + }); ////////////以下是注册的Hook API//////////// api_regist1("/index/hook/on_publish",[](API_ARGS1){ diff --git a/server/main.cpp b/server/main.cpp index 6d26bbe9..dc993d4a 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -359,7 +359,7 @@ int start_main(int argc,char *argv[]) { InfoL << "程序退出中,请等待..."; sleep(1); InfoL << "程序退出完毕!"; - return 0; + return 0; } #ifndef DISABLE_MAIN diff --git a/src/Codec/AACEncoder.cpp b/src/Codec/AACEncoder.cpp index e2241f30..d91c940b 100644 --- a/src/Codec/AACEncoder.cpp +++ b/src/Codec/AACEncoder.cpp @@ -47,73 +47,73 @@ AACEncoder::AACEncoder() { } AACEncoder::~AACEncoder() { - if (_hEncoder != nullptr) { - faacEncClose(_hEncoder); - _hEncoder = nullptr; - } - if (_pucAacBuf != nullptr) { - delete[] _pucAacBuf; - _pucAacBuf = nullptr; - } - if (_pucPcmBuf != nullptr) { - delete[] _pucPcmBuf; - _pucPcmBuf = nullptr; - } + if (_hEncoder != nullptr) { + faacEncClose(_hEncoder); + _hEncoder = nullptr; + } + if (_pucAacBuf != nullptr) { + delete[] _pucAacBuf; + _pucAacBuf = nullptr; + } + if (_pucPcmBuf != nullptr) { + delete[] _pucPcmBuf; + _pucPcmBuf = nullptr; + } } bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) { - if (iSampleBit != 16) { - return false; - } - // (1) Open FAAC engine - _hEncoder = faacEncOpen(iSampleRate, iChannels, &_ulInputSamples, - &_ulMaxOutputBytes); - if (_hEncoder == NULL) { - return false; - } - _pucAacBuf = new unsigned char[_ulMaxOutputBytes]; - _ulMaxInputBytes = _ulInputSamples * iSampleBit / 8; - _pucPcmBuf = new unsigned char[_ulMaxInputBytes * 4]; + if (iSampleBit != 16) { + return false; + } + // (1) Open FAAC engine + _hEncoder = faacEncOpen(iSampleRate, iChannels, &_ulInputSamples, + &_ulMaxOutputBytes); + if (_hEncoder == NULL) { + return false; + } + _pucAacBuf = new unsigned char[_ulMaxOutputBytes]; + _ulMaxInputBytes = _ulInputSamples * iSampleBit / 8; + _pucPcmBuf = new unsigned char[_ulMaxInputBytes * 4]; - // (2.1) Get current encoding configuration - faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(_hEncoder); - if (pConfiguration == NULL) { - faacEncClose(_hEncoder); - return false; - } - pConfiguration->aacObjectType =LOW; - pConfiguration->mpegVersion = 4; - pConfiguration->useTns = 1; - pConfiguration->shortctl = SHORTCTL_NORMAL; - pConfiguration->useLfe = 1; - pConfiguration->allowMidside = 1; - pConfiguration->bitRate = 0; - pConfiguration->bandWidth = 0; - pConfiguration->quantqual = 50; - pConfiguration->outputFormat = 1; - pConfiguration->inputFormat = FAAC_INPUT_16BIT; + // (2.1) Get current encoding configuration + faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(_hEncoder); + if (pConfiguration == NULL) { + faacEncClose(_hEncoder); + return false; + } + pConfiguration->aacObjectType =LOW; + pConfiguration->mpegVersion = 4; + pConfiguration->useTns = 1; + pConfiguration->shortctl = SHORTCTL_NORMAL; + pConfiguration->useLfe = 1; + pConfiguration->allowMidside = 1; + pConfiguration->bitRate = 0; + pConfiguration->bandWidth = 0; + pConfiguration->quantqual = 50; + pConfiguration->outputFormat = 1; + pConfiguration->inputFormat = FAAC_INPUT_16BIT; - // (2.2) Set encoding configuration - if(!faacEncSetConfiguration(_hEncoder, pConfiguration)){ - ErrorL << "faacEncSetConfiguration failed"; - faacEncClose(_hEncoder); - return false; - } - return true; + // (2.2) Set encoding configuration + if(!faacEncSetConfiguration(_hEncoder, pConfiguration)){ + ErrorL << "faacEncSetConfiguration failed"; + faacEncClose(_hEncoder); + return false; + } + return true; } int AACEncoder::inputData(char *pcPcmBufr, int iLen, unsigned char **ppucOutBuffer) { - memcpy(_pucPcmBuf + _uiPcmLen, pcPcmBufr, iLen); - _uiPcmLen += iLen; - if (_uiPcmLen < _ulMaxInputBytes) { - return 0; - } + memcpy(_pucPcmBuf + _uiPcmLen, pcPcmBufr, iLen); + _uiPcmLen += iLen; + if (_uiPcmLen < _ulMaxInputBytes) { + return 0; + } - int nRet = faacEncEncode(_hEncoder, (int32_t *) (_pucPcmBuf), _ulInputSamples, _pucAacBuf, _ulMaxOutputBytes); - _uiPcmLen -= _ulMaxInputBytes; - memmove(_pucPcmBuf, _pucPcmBuf + _ulMaxInputBytes, _uiPcmLen); - *ppucOutBuffer = _pucAacBuf; - return nRet; + int nRet = faacEncEncode(_hEncoder, (int32_t *) (_pucPcmBuf), _ulInputSamples, _pucAacBuf, _ulMaxOutputBytes); + _uiPcmLen -= _ulMaxInputBytes; + memmove(_pucPcmBuf, _pucPcmBuf + _ulMaxInputBytes, _uiPcmLen); + *ppucOutBuffer = _pucAacBuf; + return nRet; } } /* namespace mediakit */ diff --git a/src/Codec/AACEncoder.h b/src/Codec/AACEncoder.h index be194816..3ea5f56a 100644 --- a/src/Codec/AACEncoder.h +++ b/src/Codec/AACEncoder.h @@ -32,21 +32,21 @@ namespace mediakit { class AACEncoder { public: - AACEncoder(void); - virtual ~AACEncoder(void); - bool init(int iSampleRate, int iAudioChannel, int iAudioSampleBit); - int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer); + AACEncoder(void); + virtual ~AACEncoder(void); + bool init(int iSampleRate, int iAudioChannel, int iAudioSampleBit); + int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer); private: - unsigned char *_pucPcmBuf = nullptr; - unsigned int _uiPcmLen = 0; + unsigned char *_pucPcmBuf = nullptr; + unsigned int _uiPcmLen = 0; - unsigned char *_pucAacBuf = nullptr; - void *_hEncoder = nullptr; + unsigned char *_pucAacBuf = nullptr; + void *_hEncoder = nullptr; - unsigned long _ulInputSamples = 0; - unsigned long _ulMaxInputBytes = 0; - unsigned long _ulMaxOutputBytes = 0; + unsigned long _ulInputSamples = 0; + unsigned long _ulMaxInputBytes = 0; + unsigned long _ulMaxOutputBytes = 0; }; diff --git a/src/Codec/H264Encoder.cpp b/src/Codec/H264Encoder.cpp index 94b25f60..fe8c293f 100644 --- a/src/Codec/H264Encoder.cpp +++ b/src/Codec/H264Encoder.cpp @@ -38,21 +38,21 @@ H264Encoder::H264Encoder() { } H264Encoder::~H264Encoder() { - //* 清除图像区域 - if (_pPicIn) { - delete _pPicIn; - _pPicIn = nullptr; - } - if (_pPicOut) { - delete _pPicOut; - _pPicOut = nullptr; - } + //* 清除图像区域 + if (_pPicIn) { + delete _pPicIn; + _pPicIn = nullptr; + } + if (_pPicOut) { + delete _pPicOut; + _pPicOut = nullptr; + } - //* 关闭编码器句柄 - if (_pX264Handle) { - x264_encoder_close(_pX264Handle); - _pX264Handle = nullptr; - } + //* 关闭编码器句柄 + if (_pX264Handle) { + x264_encoder_close(_pX264Handle); + _pX264Handle = nullptr; + } } @@ -229,122 +229,122 @@ Value的值就是fps。 } x264_param_t;*/ bool H264Encoder::init(int iWidth, int iHeight, int iFps) { - if (_pX264Handle) { - return true; - } - x264_param_t X264Param, *pX264Param = &X264Param; - //* 配置参数 - //* 使用默认参数 - x264_param_default_preset(pX264Param, "ultrafast", "zerolatency"); + if (_pX264Handle) { + return true; + } + x264_param_t X264Param, *pX264Param = &X264Param; + //* 配置参数 + //* 使用默认参数 + x264_param_default_preset(pX264Param, "ultrafast", "zerolatency"); - //* cpuFlags - pX264Param->i_threads = X264_SYNC_LOOKAHEAD_AUTO; //* 取空缓冲区继续使用不死锁的保证. - //* video Properties - pX264Param->i_width = iWidth; //* 宽度. - pX264Param->i_height = iHeight; //* 高度 - pX264Param->i_frame_total = 0; //* 编码总帧数.不知道用0. - pX264Param->i_keyint_max = iFps * 3; //ffmpeg:gop_size 关键帧最大间隔 - pX264Param->i_keyint_min = iFps * 1; //ffmpeg:keyint_min 关键帧最小间隔 - //* Rate control Parameters - pX264Param->rc.i_bitrate = 5000; //* 码率(比特率,单位Kbps) - pX264Param->rc.i_qp_step = 1; //最大的在帧与帧之间进行切变的量化因子的变化量。ffmpeg:max_qdiff - pX264Param->rc.i_qp_min = 10; //ffmpeg:qmin;最小的量化因子。取值范围1-51。建议在10-30之间。 - pX264Param->rc.i_qp_max = 41; //ffmpeg:qmax;最大的量化因子。取值范围1-51。建议在10-30之间。 - pX264Param->rc.f_qcompress = 0.6;//ffmpeg:qcompress 量化器压缩比率0-1.越小则比特率越区域固定,但是越高越使量化器参数越固定 - pX264Param->analyse.i_me_range = 16; //ffmpeg:me_range 运动侦测的半径 - pX264Param->i_frame_reference = 3; //ffmpeg:refsB和P帧向前预测参考的帧数。取值范围1-16。 - //该值不影响解码的速度,但是越大解码 - //所需的内存越大。这个值在一般情况下 - //越大效果越好,但是超过6以后效果就 - //不明显了。 + //* cpuFlags + pX264Param->i_threads = X264_SYNC_LOOKAHEAD_AUTO; //* 取空缓冲区继续使用不死锁的保证. + //* video Properties + pX264Param->i_width = iWidth; //* 宽度. + pX264Param->i_height = iHeight; //* 高度 + pX264Param->i_frame_total = 0; //* 编码总帧数.不知道用0. + pX264Param->i_keyint_max = iFps * 3; //ffmpeg:gop_size 关键帧最大间隔 + pX264Param->i_keyint_min = iFps * 1; //ffmpeg:keyint_min 关键帧最小间隔 + //* Rate control Parameters + pX264Param->rc.i_bitrate = 5000; //* 码率(比特率,单位Kbps) + pX264Param->rc.i_qp_step = 1; //最大的在帧与帧之间进行切变的量化因子的变化量。ffmpeg:max_qdiff + pX264Param->rc.i_qp_min = 10; //ffmpeg:qmin;最小的量化因子。取值范围1-51。建议在10-30之间。 + pX264Param->rc.i_qp_max = 41; //ffmpeg:qmax;最大的量化因子。取值范围1-51。建议在10-30之间。 + pX264Param->rc.f_qcompress = 0.6;//ffmpeg:qcompress 量化器压缩比率0-1.越小则比特率越区域固定,但是越高越使量化器参数越固定 + pX264Param->analyse.i_me_range = 16; //ffmpeg:me_range 运动侦测的半径 + pX264Param->i_frame_reference = 3; //ffmpeg:refsB和P帧向前预测参考的帧数。取值范围1-16。 + //该值不影响解码的速度,但是越大解码 + //所需的内存越大。这个值在一般情况下 + //越大效果越好,但是超过6以后效果就 + //不明显了。 - pX264Param->analyse.i_trellis = 1; //ffmpeg:trellis - //pX264Param->analyse.i_me_method=X264_ME_DIA;//ffmpeg:me_method ME_ZERO 运动侦测的方式 - pX264Param->rc.f_qblur = 0.5; //ffmpeg:qblur + pX264Param->analyse.i_trellis = 1; //ffmpeg:trellis + //pX264Param->analyse.i_me_method=X264_ME_DIA;//ffmpeg:me_method ME_ZERO 运动侦测的方式 + pX264Param->rc.f_qblur = 0.5; //ffmpeg:qblur - //* bitstream parameters - /*open-GOP - 码流里面包含B帧的时候才会出现open-GOP。 - 一个GOP里面的某一帧在解码时要依赖于前一个GOP的某些帧, - 这个GOP就称为open-GOP。 - 有些解码器不能完全支持open-GOP码流, - 例如蓝光解码器,因此在x264里面open-GOP是默认关闭的。 - 对于解码端,接收到的码流如果如下:I0 B0 B1 P0 B2 B3...这就是一个open-GOP码流(I帧后面紧跟B帧)。 - 因此B0 B1的解码需要用到I0前面一个GOP的数据,B0 B1的dts是小于I0的。 - 如果码流如下: I0 P0 B0 B1 P1 B2 B3...这就是一个close-GOP码流, - I0后面所有帧的解码不依赖于I0前面的帧,I0后面所有帧的dts都比I0的大。 - 如果码流是IDR0 B0 B1 P0 B2 B3...那个这个GOP是close-GOP,B0,B1虽然dst比IDR0小, - 但编解码端都刷新了参考缓冲,B0,B1参考不到前向GOP帧。 - 对于编码端,如果编码帧类型决定如下: ...P0 B1 B2 P3 B4 B5 I6这就会输出open-Gop码流 (P0 P3 B1 B2 I6 B4 B5...), - B4 B5的解码依赖P3。 - 如果编码帧类型决定如下...P0 B1 B2 P3 B4 P5 I6这样就不会输出open-GOP码流(P0 P3 B1 B2 P5 B4 I6...)。 - 两者区别在于I6前面的第5帧是设置为B帧还是P帧, - 如果一个GOP的最后一帧(上例中是第5帧)设置为B帧, - 这个码流就是open-GOP,设置为P帧就是close-GOP。 - 由于B帧压缩性能好于P帧,因此open-GOP在编码性能上稍微优于close-GOP, - 但为了兼容性和少一些麻烦,还是把opne-GOP关闭的好。*/ - pX264Param->b_open_gop = 0; - pX264Param->i_bframe = 0; //最大B帧数. - pX264Param->i_bframe_pyramid = 0; - pX264Param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS; - //* Log - pX264Param->i_log_level = X264_LOG_ERROR; + //* bitstream parameters + /*open-GOP + 码流里面包含B帧的时候才会出现open-GOP。 + 一个GOP里面的某一帧在解码时要依赖于前一个GOP的某些帧, + 这个GOP就称为open-GOP。 + 有些解码器不能完全支持open-GOP码流, + 例如蓝光解码器,因此在x264里面open-GOP是默认关闭的。 + 对于解码端,接收到的码流如果如下:I0 B0 B1 P0 B2 B3...这就是一个open-GOP码流(I帧后面紧跟B帧)。 + 因此B0 B1的解码需要用到I0前面一个GOP的数据,B0 B1的dts是小于I0的。 + 如果码流如下: I0 P0 B0 B1 P1 B2 B3...这就是一个close-GOP码流, + I0后面所有帧的解码不依赖于I0前面的帧,I0后面所有帧的dts都比I0的大。 + 如果码流是IDR0 B0 B1 P0 B2 B3...那个这个GOP是close-GOP,B0,B1虽然dst比IDR0小, + 但编解码端都刷新了参考缓冲,B0,B1参考不到前向GOP帧。 + 对于编码端,如果编码帧类型决定如下: ...P0 B1 B2 P3 B4 B5 I6这就会输出open-Gop码流 (P0 P3 B1 B2 I6 B4 B5...), + B4 B5的解码依赖P3。 + 如果编码帧类型决定如下...P0 B1 B2 P3 B4 P5 I6这样就不会输出open-GOP码流(P0 P3 B1 B2 P5 B4 I6...)。 + 两者区别在于I6前面的第5帧是设置为B帧还是P帧, + 如果一个GOP的最后一帧(上例中是第5帧)设置为B帧, + 这个码流就是open-GOP,设置为P帧就是close-GOP。 + 由于B帧压缩性能好于P帧,因此open-GOP在编码性能上稍微优于close-GOP, + 但为了兼容性和少一些麻烦,还是把opne-GOP关闭的好。*/ + pX264Param->b_open_gop = 0; + pX264Param->i_bframe = 0; //最大B帧数. + pX264Param->i_bframe_pyramid = 0; + pX264Param->i_bframe_adaptive = X264_B_ADAPT_TRELLIS; + //* Log + pX264Param->i_log_level = X264_LOG_ERROR; - //* muxing parameters - pX264Param->i_fps_den = 1; //* 帧率分母 - pX264Param->i_fps_num = iFps; //* 帧率分子 - pX264Param->i_timebase_den = pX264Param->i_fps_num; - pX264Param->i_timebase_num = pX264Param->i_fps_den; + //* muxing parameters + pX264Param->i_fps_den = 1; //* 帧率分母 + pX264Param->i_fps_num = iFps; //* 帧率分子 + pX264Param->i_timebase_den = pX264Param->i_fps_num; + pX264Param->i_timebase_num = pX264Param->i_fps_den; - pX264Param->analyse.i_subpel_refine = 1; //这个参数控制在运动估算过程中质量和速度的权衡。Subq=5可以压缩>10%于subq=1。1-7 - pX264Param->analyse.b_fast_pskip = 1; //在P帧内执行早期快速跳跃探测。这个经常在没有任何损失的前提下提高了速度。 + pX264Param->analyse.i_subpel_refine = 1; //这个参数控制在运动估算过程中质量和速度的权衡。Subq=5可以压缩>10%于subq=1。1-7 + pX264Param->analyse.b_fast_pskip = 1; //在P帧内执行早期快速跳跃探测。这个经常在没有任何损失的前提下提高了速度。 - pX264Param->b_annexb = 1; //1前面为0x00000001,0为nal长度 - pX264Param->b_repeat_headers = 1; //关键帧前面是否放sps跟pps帧,0 否 1,放 + pX264Param->b_annexb = 1; //1前面为0x00000001,0为nal长度 + pX264Param->b_repeat_headers = 1; //关键帧前面是否放sps跟pps帧,0 否 1,放 - //* 设置Profile.使用baseline - x264_param_apply_profile(pX264Param, "high"); + //* 设置Profile.使用baseline + x264_param_apply_profile(pX264Param, "high"); - //* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264 - //* 的参数.通过x264_encoder_reconfig更新X264的参数 - _pX264Handle = x264_encoder_open(pX264Param); - if (!_pX264Handle) { - return false; - } - _pPicIn = new x264_picture_t; - _pPicOut = new x264_picture_t; - x264_picture_init(_pPicIn); - x264_picture_init(_pPicOut); - _pPicIn->img.i_csp = X264_CSP_I420; - _pPicIn->img.i_plane = 3; - return true; + //* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264 + //* 的参数.通过x264_encoder_reconfig更新X264的参数 + _pX264Handle = x264_encoder_open(pX264Param); + if (!_pX264Handle) { + return false; + } + _pPicIn = new x264_picture_t; + _pPicOut = new x264_picture_t; + x264_picture_init(_pPicIn); + x264_picture_init(_pPicOut); + _pPicIn->img.i_csp = X264_CSP_I420; + _pPicIn->img.i_plane = 3; + return true; } int H264Encoder::inputData(char* apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame** ppFrame) { - //TimeTicker1(5); - _pPicIn->img.i_stride[0] = aiYuvLen[0]; - _pPicIn->img.i_stride[1] = aiYuvLen[1]; - _pPicIn->img.i_stride[2] = aiYuvLen[2]; - _pPicIn->img.plane[0] = (uint8_t *) apcYuv[0]; - _pPicIn->img.plane[1] = (uint8_t *) apcYuv[1]; - _pPicIn->img.plane[2] = (uint8_t *) apcYuv[2]; - _pPicIn->i_pts = i64Pts; - int iNal; - x264_nal_t* pNals; + //TimeTicker1(5); + _pPicIn->img.i_stride[0] = aiYuvLen[0]; + _pPicIn->img.i_stride[1] = aiYuvLen[1]; + _pPicIn->img.i_stride[2] = aiYuvLen[2]; + _pPicIn->img.plane[0] = (uint8_t *) apcYuv[0]; + _pPicIn->img.plane[1] = (uint8_t *) apcYuv[1]; + _pPicIn->img.plane[2] = (uint8_t *) apcYuv[2]; + _pPicIn->i_pts = i64Pts; + int iNal; + x264_nal_t* pNals; - int iResult = x264_encoder_encode(_pX264Handle, &pNals, &iNal, _pPicIn, - _pPicOut); - if (iResult <= 0) { - return 0; - } - for (int i = 0; i < iNal; i++) { - x264_nal_t pNal = pNals[i]; - _aFrames[i].iType = pNal.i_type; - _aFrames[i].iLength = pNal.i_payload; - _aFrames[i].pucData = pNal.p_payload; - } - *ppFrame = _aFrames; - return iNal; + int iResult = x264_encoder_encode(_pX264Handle, &pNals, &iNal, _pPicIn, + _pPicOut); + if (iResult <= 0) { + return 0; + } + for (int i = 0; i < iNal; i++) { + x264_nal_t pNal = pNals[i]; + _aFrames[i].iType = pNal.i_type; + _aFrames[i].iLength = pNal.i_payload; + _aFrames[i].pucData = pNal.p_payload; + } + *ppFrame = _aFrames; + return iNal; } } /* namespace mediakit */ diff --git a/src/Codec/H264Encoder.h b/src/Codec/H264Encoder.h index 3dd8b323..a395c460 100644 --- a/src/Codec/H264Encoder.h +++ b/src/Codec/H264Encoder.h @@ -42,21 +42,21 @@ namespace mediakit { class H264Encoder { public: - typedef struct { - int iType; - int iLength; - uint8_t *pucData; - } H264Frame; + typedef struct { + int iType; + int iLength; + uint8_t *pucData; + } H264Frame; - H264Encoder(void); - virtual ~H264Encoder(void); - bool init(int iWidth, int iHeight, int iFps); - int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame); + H264Encoder(void); + virtual ~H264Encoder(void); + bool init(int iWidth, int iHeight, int iFps); + int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame); private: - x264_t* _pX264Handle = nullptr; - x264_picture_t* _pPicIn = nullptr; - x264_picture_t* _pPicOut = nullptr; - H264Frame _aFrames[10]; + x264_t* _pX264Handle = nullptr; + x264_picture_t* _pPicIn = nullptr; + x264_picture_t* _pPicOut = nullptr; + H264Frame _aFrames[10]; }; } /* namespace mediakit */ diff --git a/src/Common/Device.cpp b/src/Common/Device.cpp index 58fd53cb..2c8653c3 100644 --- a/src/Common/Device.cpp +++ b/src/Common/Device.cpp @@ -42,8 +42,8 @@ DevChannel::DevChannel(const string &strVhost, const string &strApp, const string &strId, float fDuration, - bool bEanbleRtsp, - bool bEanbleRtmp, + bool bEanbleRtsp, + bool bEanbleRtmp, bool bEanbleHls, bool bEnableMp4) : MultiMediaSourceMuxer(strVhost, strApp, strId, fDuration, bEanbleRtsp, bEanbleRtmp, bEanbleHls, bEnableMp4) {} @@ -52,50 +52,50 @@ DevChannel::~DevChannel() {} #ifdef ENABLE_X264 void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) { - //TimeTicker1(50); - if (!_pH264Enc) { - _pH264Enc.reset(new H264Encoder()); - if (!_pH264Enc->init(_video->iWidth, _video->iHeight, _video->iFrameRate)) { - _pH264Enc.reset(); - WarnL << "H264Encoder init failed!"; - } - } - if (_pH264Enc) { - H264Encoder::H264Frame *pOut; - int iFrames = _pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut); - for (int i = 0; i < iFrames; i++) { - inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp); - } - } + //TimeTicker1(50); + if (!_pH264Enc) { + _pH264Enc.reset(new H264Encoder()); + if (!_pH264Enc->init(_video->iWidth, _video->iHeight, _video->iFrameRate)) { + _pH264Enc.reset(); + WarnL << "H264Encoder init failed!"; + } + } + if (_pH264Enc) { + H264Encoder::H264Frame *pOut; + int iFrames = _pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut); + for (int i = 0; i < iFrames; i++) { + inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp); + } + } } #endif //ENABLE_X264 #ifdef ENABLE_FAAC void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) { - if (!_pAacEnc) { - _pAacEnc.reset(new AACEncoder()); - if (!_pAacEnc->init(_audio->iSampleRate, _audio->iChannel, _audio->iSampleBit)) { - _pAacEnc.reset(); - WarnL << "AACEncoder init failed!"; - } - } - if (_pAacEnc) { - unsigned char *pucOut; - int iRet = _pAacEnc->inputData(pcData, iDataLen, &pucOut); - if (iRet > 0) { - inputAAC((char *) pucOut, iRet, uiStamp); - } - } + if (!_pAacEnc) { + _pAacEnc.reset(new AACEncoder()); + if (!_pAacEnc->init(_audio->iSampleRate, _audio->iChannel, _audio->iSampleBit)) { + _pAacEnc.reset(); + WarnL << "AACEncoder init failed!"; + } + } + if (_pAacEnc) { + unsigned char *pucOut; + int iRet = _pAacEnc->inputData(pcData, iDataLen, &pucOut); + if (iRet > 0) { + inputAAC((char *) pucOut, iRet, uiStamp); + } + } } #endif //ENABLE_FAAC void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32_t pts) { 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; if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) { prefixeSize = 4; @@ -105,46 +105,46 @@ void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t dts,uint32 prefixeSize = 0; } - H264Frame::Ptr frame = std::make_shared(); - frame->_dts = dts; - frame->_pts = pts; - frame->_buffer.assign("\x00\x00\x00\x01",4); - frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); - frame->_prefix_size = 4; + H264Frame::Ptr frame = std::make_shared(); + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01",4); + frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); + frame->_prefix_size = 4; inputFrame(frame); } void DevChannel::inputH265(const char* pcData, int iDataLen, uint32_t dts,uint32_t pts) { - if(dts == 0){ - dts = (uint32_t)_aTicker[0].elapsedTime(); - } - if(pts == 0){ - pts = dts; - } - int prefixeSize; - if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) { - prefixeSize = 4; - } else if (memcmp("\x00\x00\x01", pcData, 3) == 0) { - prefixeSize = 3; - } else { - prefixeSize = 0; - } + if(dts == 0){ + dts = (uint32_t)_aTicker[0].elapsedTime(); + } + if(pts == 0){ + pts = dts; + } + int prefixeSize; + if (memcmp("\x00\x00\x00\x01", pcData, 4) == 0) { + prefixeSize = 4; + } else if (memcmp("\x00\x00\x01", pcData, 3) == 0) { + prefixeSize = 3; + } else { + prefixeSize = 0; + } - H265Frame::Ptr frame = std::make_shared(); - frame->_dts = dts; - frame->_pts = pts; - frame->_buffer.assign("\x00\x00\x00\x01",4); - frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); - frame->_prefix_size = 4; - inputFrame(frame); + H265Frame::Ptr frame = std::make_shared(); + frame->_dts = dts; + frame->_pts = pts; + frame->_buffer.assign("\x00\x00\x00\x01",4); + frame->_buffer.append(pcData + prefixeSize, iDataLen - prefixeSize); + frame->_prefix_size = 4; + inputFrame(frame); } void DevChannel::inputAAC(const char* pcData, int iDataLen, uint32_t uiStamp,bool withAdtsHeader) { - if(withAdtsHeader){ - inputAAC(pcData+7,iDataLen-7,uiStamp,pcData); - } else if(_audio) { - inputAAC(pcData,iDataLen,uiStamp,(char *)_adtsHeader); - } + if(withAdtsHeader){ + inputAAC(pcData+7,iDataLen-7,uiStamp,pcData); + } else if(_audio) { + inputAAC(pcData,iDataLen,uiStamp,(char *)_adtsHeader); + } } 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 uiStamp = (uint32_t)_aTicker[1].elapsedTime(); } if(pcAdtsHeader + 7 == pcDataWithoutAdts){ - inputFrame(std::make_shared((char *)pcDataWithoutAdts - 7,iDataLen + 7,uiStamp,7)); - } else { - char *dataWithAdts = new char[iDataLen + 7]; - memcpy(dataWithAdts,pcAdtsHeader,7); - memcpy(dataWithAdts + 7 , pcDataWithoutAdts , iDataLen); - inputFrame(std::make_shared(dataWithAdts,iDataLen + 7,uiStamp,7)); - delete [] dataWithAdts; - } + inputFrame(std::make_shared((char *)pcDataWithoutAdts - 7,iDataLen + 7,uiStamp,7)); + } else { + char *dataWithAdts = new char[iDataLen + 7]; + memcpy(dataWithAdts,pcAdtsHeader,7); + memcpy(dataWithAdts + 7 , pcDataWithoutAdts , iDataLen); + inputFrame(std::make_shared(dataWithAdts,iDataLen + 7,uiStamp,7)); + delete [] dataWithAdts; + } } void DevChannel::initVideo(const VideoInfo& info) { - _video = std::make_shared(info); - addTrack(std::make_shared()); + _video = std::make_shared(info); + addTrack(std::make_shared()); } void DevChannel::initH265Video(const VideoInfo &info){ - _video = std::make_shared(info); - addTrack(std::make_shared()); + _video = std::make_shared(info); + addTrack(std::make_shared()); } void DevChannel::initAudio(const AudioInfo& info) { - _audio = std::make_shared(info); - addTrack(std::make_shared()); + _audio = std::make_shared(info); + addTrack(std::make_shared()); - AACFrame adtsHeader; - adtsHeader.syncword = 0x0FFF; - adtsHeader.id = 0; - adtsHeader.layer = 0; - adtsHeader.protection_absent = 1; - adtsHeader.profile = info.iProfile;//audioObjectType - 1; - int i = 0; - for(auto rate : samplingFrequencyTable){ - if(rate == info.iSampleRate){ - adtsHeader.sf_index = i; - }; - ++i; - } - adtsHeader.private_bit = 0; - adtsHeader.channel_configuration = info.iChannel; - adtsHeader.original = 0; - adtsHeader.home = 0; - adtsHeader.copyright_identification_bit = 0; - adtsHeader.copyright_identification_start = 0; - adtsHeader.aac_frame_length = 7; - adtsHeader.adts_buffer_fullness = 2047; - adtsHeader.no_raw_data_blocks_in_frame = 0; - writeAdtsHeader(adtsHeader,_adtsHeader); + AACFrame adtsHeader; + adtsHeader.syncword = 0x0FFF; + adtsHeader.id = 0; + adtsHeader.layer = 0; + adtsHeader.protection_absent = 1; + adtsHeader.profile = info.iProfile;//audioObjectType - 1; + int i = 0; + for(auto rate : samplingFrequencyTable){ + if(rate == info.iSampleRate){ + adtsHeader.sf_index = i; + }; + ++i; + } + adtsHeader.private_bit = 0; + adtsHeader.channel_configuration = info.iChannel; + adtsHeader.original = 0; + adtsHeader.home = 0; + adtsHeader.copyright_identification_bit = 0; + adtsHeader.copyright_identification_start = 0; + adtsHeader.aac_frame_length = 7; + adtsHeader.adts_buffer_fullness = 2047; + adtsHeader.no_raw_data_blocks_in_frame = 0; + writeAdtsHeader(adtsHeader,_adtsHeader); } } /* namespace mediakit */ diff --git a/src/Common/Device.h b/src/Common/Device.h index a8c63daf..e24ccf26 100644 --- a/src/Common/Device.h +++ b/src/Common/Device.h @@ -51,16 +51,16 @@ namespace mediakit { class VideoInfo { public: - int iWidth; - int iHeight; - float iFrameRate; + int iWidth; + int iHeight; + float iFrameRate; }; class AudioInfo { public: - int iChannel; - int iSampleBit; - int iSampleRate; - int iProfile; + int iChannel; + int iSampleBit; + int iSampleRate; + int iProfile; }; /** @@ -68,82 +68,82 @@ public: */ class DevChannel : public MultiMediaSourceMuxer{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; //fDuration<=0为直播,否则为点播 DevChannel(const string &strVhost, const string &strApp, const string &strId, float fDuration = 0, - bool bEanbleRtsp = true, - bool bEanbleRtmp = true, + bool bEanbleRtsp = true, + bool bEanbleRtmp = true, bool bEanbleHls = true, bool bEnableMp4 = false); - virtual ~DevChannel(); + virtual ~DevChannel(); - /** - * 初始化h264视频Track - * 相当于MultiMediaSourceMuxer::addTrack(H264Track::Ptr ); - * @param info - */ + /** + * 初始化h264视频Track + * 相当于MultiMediaSourceMuxer::addTrack(H264Track::Ptr ); + * @param info + */ void initVideo(const VideoInfo &info); - /** - * 初始化h265视频Track - * @param info - */ - void initH265Video(const VideoInfo &info); + /** + * 初始化h265视频Track + * @param info + */ + void initH265Video(const VideoInfo &info); /** * 初始化aac音频Track * 相当于MultiMediaSourceMuxer::addTrack(AACTrack::Ptr ); * @param info */ - void initAudio(const AudioInfo &info); + void initAudio(const AudioInfo &info); - /** - * 输入264帧 - * @param pcData 264单帧数据指针 - * @param iDataLen 数据指针长度 - * @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳 - * @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts - */ - void inputH264(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0); + /** + * 输入264帧 + * @param pcData 264单帧数据指针 + * @param iDataLen 数据指针长度 + * @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳 + * @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts + */ + void inputH264(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0); - /** - * 输入265帧 - * @param pcData 265单帧数据指针 - * @param iDataLen 数据指针长度 - * @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳 - * @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts - */ - void inputH265(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0); + /** + * 输入265帧 + * @param pcData 265单帧数据指针 + * @param iDataLen 数据指针长度 + * @param dts 解码时间戳,单位毫秒;等于0时内部会自动生成时间戳 + * @param pts 播放时间戳,单位毫秒;等于0时内部会赋值为dts + */ + void inputH265(const char *pcData, int iDataLen, uint32_t dts,uint32_t pts = 0); - /** - * 输入可能带adts头的aac帧 - * @param pcDataWithAdts 可能带adts头的aac帧 - * @param iDataLen 帧数据长度 - * @param uiStamp 时间戳,单位毫秒,等于0时内部会自动生成时间戳 - * @param withAdtsHeader 是否带adts头 - */ - void inputAAC(const char *pcDataWithAdts, int iDataLen, uint32_t uiStamp, bool withAdtsHeader = true); + /** + * 输入可能带adts头的aac帧 + * @param pcDataWithAdts 可能带adts头的aac帧 + * @param iDataLen 帧数据长度 + * @param uiStamp 时间戳,单位毫秒,等于0时内部会自动生成时间戳 + * @param withAdtsHeader 是否带adts头 + */ + void inputAAC(const char *pcDataWithAdts, int iDataLen, uint32_t uiStamp, bool withAdtsHeader = true); - /** - * 输入不带adts头的aac帧 - * @param pcDataWithoutAdts 不带adts头的aac帧 - * @param iDataLen 帧数据长度 - * @param uiStamp 时间戳,单位毫秒 - * @param pcAdtsHeader adts头 - */ - void inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader); + /** + * 输入不带adts头的aac帧 + * @param pcDataWithoutAdts 不带adts头的aac帧 + * @param iDataLen 帧数据长度 + * @param uiStamp 时间戳,单位毫秒 + * @param pcAdtsHeader adts头 + */ + void inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader); #ifdef ENABLE_X264 - /** - * 输入yuv420p视频帧,内部会完成编码并调用inputH264方法 - * @param apcYuv - * @param aiYuvLen - * @param uiStamp - */ + /** + * 输入yuv420p视频帧,内部会完成编码并调用inputH264方法 + * @param apcYuv + * @param aiYuvLen + * @param uiStamp + */ void inputYUV(char *apcYuv[3], int aiYuvLen[3], uint32_t uiStamp); #endif //ENABLE_X264 @@ -160,11 +160,11 @@ public: private: #ifdef ENABLE_X264 - std::shared_ptr _pH264Enc; + std::shared_ptr _pH264Enc; #endif //ENABLE_X264 #ifdef ENABLE_FAAC - std::shared_ptr _pAacEnc; + std::shared_ptr _pAacEnc; #endif //ENABLE_FAAC std::shared_ptr _video; std::shared_ptr _audio; diff --git a/src/Common/config.cpp b/src/Common/config.cpp index ded712dc..eaa4ca1a 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -42,15 +42,15 @@ bool loadIniConfig(const char *ini_path){ }else{ ini = exePath() + ".ini"; } - try{ + try{ mINI::Instance().parseFile(ini); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig); return true; - }catch (std::exception &ex) { - InfoL << "dump ini file to:" << ini; + }catch (std::exception &ex) { + InfoL << "dump ini file to:" << ini; mINI::Instance().dumpFile(ini); return false; - } + } } ////////////广播名称/////////// namespace Broadcast { @@ -90,12 +90,12 @@ onceToken token([](){ mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000; mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000; mINI::Instance()[kEnableVhost] = 0; - mINI::Instance()[kUltraLowDelay] = 1; - mINI::Instance()[kAddMuteAudio] = 1; - mINI::Instance()[kResetWhenRePlay] = 1; - mINI::Instance()[kPublishToRtxp] = 1; - mINI::Instance()[kPublishToHls] = 1; - mINI::Instance()[kPublishToMP4] = 0; + mINI::Instance()[kUltraLowDelay] = 1; + mINI::Instance()[kAddMuteAudio] = 1; + mINI::Instance()[kResetWhenRePlay] = 1; + mINI::Instance()[kPublishToRtxp] = 1; + mINI::Instance()[kPublishToHls] = 1; + mINI::Instance()[kPublishToMP4] = 0; },nullptr); }//namespace General @@ -117,26 +117,26 @@ const string kRootPath = HTTP_FIELD"rootPath"; const string kNotFound = HTTP_FIELD"notFound"; onceToken token([](){ - mINI::Instance()[kSendBufSize] = 64 * 1024; - mINI::Instance()[kMaxReqSize] = 4*1024; - mINI::Instance()[kKeepAliveSecond] = 15; + mINI::Instance()[kSendBufSize] = 64 * 1024; + mINI::Instance()[kMaxReqSize] = 4*1024; + mINI::Instance()[kKeepAliveSecond] = 15; #if defined(_WIN32) - mINI::Instance()[kCharSet] = "gb2312"; + mINI::Instance()[kCharSet] = "gb2312"; #else - mINI::Instance()[kCharSet] ="utf-8"; + mINI::Instance()[kCharSet] ="utf-8"; #endif - mINI::Instance()[kRootPath] = "./www"; - mINI::Instance()[kNotFound] = - "" - "404 Not Found" - "" - "

您访问的资源不存在!

" - "
" - SERVER_NAME - "
" - "" - ""; + mINI::Instance()[kRootPath] = "./www"; + mINI::Instance()[kNotFound] = + "" + "404 Not Found" + "" + "

您访问的资源不存在!

" + "
" + SERVER_NAME + "
" + "" + ""; },nullptr); }//namespace Http @@ -147,7 +147,7 @@ namespace Shell { const string kMaxReqSize = SHELL_FIELD"maxReqSize"; onceToken token([](){ - mINI::Instance()[kMaxReqSize] = 1024; + mINI::Instance()[kMaxReqSize] = 1024; },nullptr); } //namespace Shell @@ -160,11 +160,11 @@ const string kKeepAliveSecond = RTSP_FIELD"keepAliveSecond"; const string kDirectProxy = RTSP_FIELD"directProxy"; onceToken token([](){ - //默认Md5方式认证 - mINI::Instance()[kAuthBasic] = 0; + //默认Md5方式认证 + mINI::Instance()[kAuthBasic] = 0; mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15; - mINI::Instance()[kDirectProxy] = 1; + mINI::Instance()[kDirectProxy] = 1; },nullptr); } //namespace Rtsp @@ -176,7 +176,7 @@ const string kHandshakeSecond = RTMP_FIELD"handshakeSecond"; const string kKeepAliveSecond = RTMP_FIELD"keepAliveSecond"; onceToken token([](){ - mINI::Instance()[kModifyStamp] = false; + mINI::Instance()[kModifyStamp] = false; mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15; },nullptr); @@ -197,11 +197,11 @@ const string kClearCount = RTP_FIELD"clearCount"; const string kCycleMS = RTP_FIELD"cycleMS"; onceToken token([](){ - mINI::Instance()[kVideoMtuSize] = 1400; - mINI::Instance()[kAudioMtuSize] = 600; - mINI::Instance()[kMaxRtpCount] = 50; - mINI::Instance()[kClearCount] = 10; - mINI::Instance()[kCycleMS] = 13*60*60*1000; + mINI::Instance()[kVideoMtuSize] = 1400; + mINI::Instance()[kAudioMtuSize] = 600; + mINI::Instance()[kMaxRtpCount] = 50; + mINI::Instance()[kClearCount] = 10; + mINI::Instance()[kCycleMS] = 13*60*60*1000; },nullptr); } //namespace Rtsp @@ -216,9 +216,9 @@ const string kAddrMax = MULTI_FIELD"addrMax"; const string kUdpTTL = MULTI_FIELD"udpTTL"; onceToken token([](){ - mINI::Instance()[kAddrMin] = "239.0.0.0"; - mINI::Instance()[kAddrMax] = "239.255.255.255"; - mINI::Instance()[kUdpTTL] = 64; + mINI::Instance()[kAddrMin] = "239.0.0.0"; + mINI::Instance()[kAddrMax] = "239.255.255.255"; + mINI::Instance()[kUdpTTL] = 64; },nullptr); } //namespace MultiCast @@ -241,13 +241,13 @@ const string kFastStart = RECORD_FIELD"fastStart"; const string kFileRepeat = RECORD_FIELD"fileRepeat"; onceToken token([](){ - mINI::Instance()[kAppName] = "record"; - mINI::Instance()[kSampleMS] = 500; - mINI::Instance()[kFileSecond] = 60*60; - mINI::Instance()[kFilePath] = "./www"; - mINI::Instance()[kFileBufSize] = 64 * 1024; - mINI::Instance()[kFastStart] = false; - mINI::Instance()[kFileRepeat] = false; + mINI::Instance()[kAppName] = "record"; + mINI::Instance()[kSampleMS] = 500; + mINI::Instance()[kFileSecond] = 60*60; + mINI::Instance()[kFilePath] = "./www"; + mINI::Instance()[kFileBufSize] = 64 * 1024; + mINI::Instance()[kFastStart] = false; + mINI::Instance()[kFileRepeat] = false; },nullptr); } //namespace Record @@ -266,11 +266,11 @@ const string kFileBufSize = HLS_FIELD"fileBufSize"; const string kFilePath = HLS_FIELD"filePath"; onceToken token([](){ - mINI::Instance()[kSegmentDuration] = 2; - mINI::Instance()[kSegmentNum] = 3; - mINI::Instance()[kSegmentRetain] = 5; - mINI::Instance()[kFileBufSize] = 64 * 1024; - mINI::Instance()[kFilePath] = "./www"; + mINI::Instance()[kSegmentDuration] = 2; + mINI::Instance()[kSegmentNum] = 3; + mINI::Instance()[kSegmentRetain] = 5; + mINI::Instance()[kFileBufSize] = 64 * 1024; + mINI::Instance()[kFilePath] = "./www"; },nullptr); } //namespace Hls @@ -286,9 +286,9 @@ const string kCheckSource = RTP_PROXY_FIELD"checkSource"; const string kTimeoutSec = RTP_PROXY_FIELD"timeoutSec"; onceToken token([](){ - mINI::Instance()[kDumpDir] = ""; - mINI::Instance()[kCheckSource] = 1; - mINI::Instance()[kTimeoutSec] = 15; + mINI::Instance()[kDumpDir] = ""; + mINI::Instance()[kCheckSource] = 1; + mINI::Instance()[kTimeoutSec] = 15; },nullptr); } //namespace RtpProxy diff --git a/src/Extension/H264Rtp.cpp b/src/Extension/H264Rtp.cpp index 5df37767..5d70e778 100644 --- a/src/Extension/H264Rtp.cpp +++ b/src/Extension/H264Rtp.cpp @@ -88,24 +88,24 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { * Type==7:SPS 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 - Type Packet Type name Section - --------------------------------------------------------- - 0 undefined - - 1-23 NAL unit Single NAL unit packet per H.264 5.6 - 24 STAP-A 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 - 27 MTAP24 Multi-time aggregation packet 5.7.2 - 28 FU-A Fragmentation unit 5.8 - 29 FU-B Fragmentation unit 5.8 - 30-31 undefined - + Type Packet Type name Section + --------------------------------------------------------- + 0 undefined - + 1-23 NAL unit Single NAL unit packet per H.264 5.6 + 24 STAP-A 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 + 27 MTAP24 Multi-time aggregation packet 5.7.2 + 28 FU-A Fragmentation unit 5.8 + 29 FU-B Fragmentation unit 5.8 + 30-31 undefined - - */ + */ const uint8_t *frame = (uint8_t *) rtppack->data() + rtppack->offset; int length = rtppack->size() - rtppack->offset; NALU nal; diff --git a/src/Extension/H265.cpp b/src/Extension/H265.cpp index fc7fd8f2..eae223d8 100644 --- a/src/Extension/H265.cpp +++ b/src/Extension/H265.cpp @@ -34,36 +34,36 @@ bool getHEVCInfo(const char * vps, int vps_len,const char * sps,int sps_len,int T_GetBitContext tGetBitBuf; T_HEVCSPS tH265SpsInfo; T_HEVCVPS tH265VpsInfo; - if ( vps_len > 2 ){ - memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); - memset(&tH265VpsInfo,0,sizeof(tH265VpsInfo)); - tGetBitBuf.pu8Buf = (uint8_t*)vps+2; - tGetBitBuf.iBufSize = vps_len-2; - if(0 != h265DecVideoParameterSet((void *) &tGetBitBuf, &tH265VpsInfo)){ - return false; - } - } + if ( vps_len > 2 ){ + memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); + memset(&tH265VpsInfo,0,sizeof(tH265VpsInfo)); + tGetBitBuf.pu8Buf = (uint8_t*)vps+2; + tGetBitBuf.iBufSize = vps_len-2; + if(0 != h265DecVideoParameterSet((void *) &tGetBitBuf, &tH265VpsInfo)){ + return false; + } + } - if ( sps_len > 2 ){ - memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); - memset(&tH265SpsInfo,0,sizeof(tH265SpsInfo)); - tGetBitBuf.pu8Buf = (uint8_t*)sps+2; - tGetBitBuf.iBufSize = sps_len-2; - if(0 != h265DecSeqParameterSet((void *) &tGetBitBuf, &tH265SpsInfo)){ - return false; - } - } - else - return false; + if ( sps_len > 2 ){ + memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); + memset(&tH265SpsInfo,0,sizeof(tH265SpsInfo)); + tGetBitBuf.pu8Buf = (uint8_t*)sps+2; + tGetBitBuf.iBufSize = sps_len-2; + if(0 != h265DecSeqParameterSet((void *) &tGetBitBuf, &tH265SpsInfo)){ + return false; + } + } + else + return false; h265GetWidthHeight(&tH265SpsInfo, &iVideoWidth, &iVideoHeight); - iVideoFps = 0; + iVideoFps = 0; h265GeFramerate(&tH265VpsInfo, &tH265SpsInfo, &iVideoFps); // ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps; return true; } 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() { diff --git a/src/Extension/H265.h b/src/Extension/H265.h index 80591e32..cfed9412 100644 --- a/src/Extension/H265.h +++ b/src/Extension/H265.h @@ -202,7 +202,7 @@ public: _vps = vps.substr(vps_prefix_len); _sps = sps.substr(sps_prefix_len); _pps = pps.substr(pps_prefix_len); - onReady(); + onReady(); } /** @@ -267,10 +267,10 @@ public: * @param frame 数据帧 */ 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){ - bool first_frame = true; - splitH264(frame->data() + frame->prefixSize(), + bool first_frame = true; + splitH264(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize(), [&](const char *ptr, int len){ if(first_frame){ @@ -288,9 +288,9 @@ public: inputFrame_l(sub_frame); } }); - }else{ - inputFrame_l(frame); - } + }else{ + inputFrame_l(frame); + } } private: @@ -336,7 +336,7 @@ private: } } - /** + /** * 解析sps获取宽高fps */ void onReady(){ diff --git a/src/Extension/SPSParser.c b/src/Extension/SPSParser.c index 54c19592..36c2aed7 100644 --- a/src/Extension/SPSParser.c +++ b/src/Extension/SPSParser.c @@ -234,16 +234,16 @@ static const T_AVRational sg_atVuiSar[] = { static inline int getBitsLeft(void *pvHandle) { - int iResLen = 0; - T_GetBitContext *ptPtr = (T_GetBitContext *)pvHandle; - if(ptPtr->iBufSize <= 0 || ptPtr->iTotalBit <= 0) - { - RPT(RPT_WRN, "buffer size is zero"); - return 0; - } + int iResLen = 0; + T_GetBitContext *ptPtr = (T_GetBitContext *)pvHandle; + if(ptPtr->iBufSize <= 0 || ptPtr->iTotalBit <= 0) + { + RPT(RPT_WRN, "buffer size is zero"); + return 0; + } - iResLen = ptPtr->iTotalBit - ptPtr->iBitPos; + iResLen = ptPtr->iTotalBit - ptPtr->iBitPos; return iResLen; } @@ -264,7 +264,7 @@ static int getOneBit(void *pvHandle) int iRet = 0; uint8_t *pu8CurChar = NULL; uint8_t u8Shift; - int iResoLen = 0; + int iResoLen = 0; if(NULL == ptPtr) { @@ -272,12 +272,12 @@ static int getOneBit(void *pvHandle) iRet = -1; goto exit; } - iResoLen = getBitsLeft(ptPtr); - if(iResoLen < 1) - { + iResoLen = getBitsLeft(ptPtr); + if(iResoLen < 1) + { iRet = -1; goto exit; - } + } pu8CurChar = ptPtr->pu8Buf + (ptPtr->iBitPos >> 3); u8Shift = 7 - (ptPtr->iCurBitPos); @@ -307,7 +307,7 @@ static int getBits(void *pvHandle, int iN) uint8_t u8Shift; uint32_t u32Result = 0; int iRet = 0; - int iResoLen = 0; + int iResoLen = 0; if(NULL == ptPtr) { @@ -321,12 +321,12 @@ static int getBits(void *pvHandle, int iN) iN = MAX_LEN; } - iResoLen = getBitsLeft(ptPtr); - if(iResoLen < iN) - { + iResoLen = getBitsLeft(ptPtr); + if(iResoLen < iN) + { iRet = -1; goto exit; - } + } if((ptPtr->iBitPos + iN) > ptPtr->iTotalBit) @@ -374,7 +374,7 @@ static inline unsigned int showBits(void *pvHandle, int iN) uint8_t u8Shift; uint32_t u32Result = 0; int iRet = 0; - int iResoLen = 0; + int iResoLen = 0; if(NULL == ptPtr) { @@ -388,12 +388,12 @@ static inline unsigned int showBits(void *pvHandle, int iN) iN = MAX_LEN; } - iResoLen = getBitsLeft(ptPtr); - if(iResoLen < iN) - { + iResoLen = getBitsLeft(ptPtr); + if(iResoLen < iN) + { iRet = -1; goto exit; - } + } if((ptPtr->iBitPos + iN) > ptPtr->iTotalBit) @@ -435,7 +435,7 @@ exit: */ static inline unsigned int showBitsLong(void *pvHandle, int iN) { - T_GetBitContext *ptPtr = (T_GetBitContext *)pvHandle; + T_GetBitContext *ptPtr = (T_GetBitContext *)pvHandle; if (iN <= 32) { return showBits(ptPtr, iN); @@ -611,23 +611,23 @@ static void decodeScalingList(void *pvBuf, uint8_t *pu8Factors, int iSize, const uint8_t *pu8FallbackList) { int i; - int iLast = 8; - int iNext = 8; + int iLast = 8; + int iNext = 8; const uint8_t *pu8Scan = iSize == 16 ? sg_au8ZigzagScan : g_au8FfZigzagDirect; if (!getOneBit(pvBuf)) /* matrix not written, we use the predicted one */ memcpy(pu8Factors, pu8FallbackList, iSize * sizeof(uint8_t)); else for (i = 0; i < iSize; i++) - { + { if (iNext) { iNext = (iLast + parseSe(pvBuf)) & 0xff; } if (!i && !iNext) - { - /* matrix not written, we use the preset one */ + { + /* matrix not written, we use the preset one */ memcpy(pu8Factors, pu8JvtList, iSize * sizeof(uint8_t)); break; } @@ -652,49 +652,49 @@ static void decodeScalingList(void *pvBuf, uint8_t *pu8Factors, int iSize, ptSps->iScalingMatrixPresent |= iIsSps; decodeScalingList(pvBuf, pau8ScalingMatrix4[0], 16, sg_aau8DefaultScaling4[0], pau8Fallback[0]); // Intra, Y decodeScalingList(pvBuf, pau8ScalingMatrix4[1], 16, sg_aau8DefaultScaling4[0], pau8ScalingMatrix4[0]); // Intra, Cr - decodeScalingList(pvBuf, pau8ScalingMatrix4[2], 16, sg_aau8DefaultScaling4[0], pau8ScalingMatrix4[1]); // Intra, Cb + decodeScalingList(pvBuf, pau8ScalingMatrix4[2], 16, sg_aau8DefaultScaling4[0], pau8ScalingMatrix4[1]); // Intra, Cb - decodeScalingList(pvBuf, pau8ScalingMatrix4[3], 16, sg_aau8DefaultScaling4[1], pau8Fallback[1]); // Inter, Y + decodeScalingList(pvBuf, pau8ScalingMatrix4[3], 16, sg_aau8DefaultScaling4[1], pau8Fallback[1]); // Inter, Y - decodeScalingList(pvBuf, pau8ScalingMatrix4[4], 16, sg_aau8DefaultScaling4[1], pau8ScalingMatrix4[3]); // Inter, Cr + decodeScalingList(pvBuf, pau8ScalingMatrix4[4], 16, sg_aau8DefaultScaling4[1], pau8ScalingMatrix4[3]); // Inter, Cr - decodeScalingList(pvBuf, pau8ScalingMatrix4[5], 16, sg_aau8DefaultScaling4[1], pau8ScalingMatrix4[4]); // Inter, Cb + decodeScalingList(pvBuf, pau8ScalingMatrix4[5], 16, sg_aau8DefaultScaling4[1], pau8ScalingMatrix4[4]); // Inter, Cb if (iIsSps || ptPps->iTransform8x8Mode) - { + { decodeScalingList(pvBuf, pau8ScalingMatrix8[0], 64, sg_aau8DefaultScaling8[0], pau8Fallback[2]); // Intra, Y decodeScalingList(pvBuf, pau8ScalingMatrix8[3], 64, sg_aau8DefaultScaling8[1], pau8Fallback[3]); // Inter, Y if (ptSps->iChromaFormatIdc == 3) { decodeScalingList(pvBuf, pau8ScalingMatrix8[1], 64, sg_aau8DefaultScaling8[0], pau8ScalingMatrix8[0]); // Intra, Cr - decodeScalingList(pvBuf, pau8ScalingMatrix8[4], 64, sg_aau8DefaultScaling8[1], pau8ScalingMatrix8[3]); // Inter, Cr - decodeScalingList(pvBuf, pau8ScalingMatrix8[2], 64, sg_aau8DefaultScaling8[0], pau8ScalingMatrix8[1]); // Intra, Cb - decodeScalingList(pvBuf, pau8ScalingMatrix8[5], 64, sg_aau8DefaultScaling8[1], pau8ScalingMatrix8[4]); // Inter, Cb - } + decodeScalingList(pvBuf, pau8ScalingMatrix8[4], 64, sg_aau8DefaultScaling8[1], pau8ScalingMatrix8[3]); // Inter, Cr + decodeScalingList(pvBuf, pau8ScalingMatrix8[2], 64, sg_aau8DefaultScaling8[0], pau8ScalingMatrix8[1]); // Intra, Cb + decodeScalingList(pvBuf, pau8ScalingMatrix8[5], 64, sg_aau8DefaultScaling8[1], pau8ScalingMatrix8[4]); // Inter, Cb + } } } - return 0; + return 0; } static int decodeHrdPAarameters(void *pvBuf, T_SPS *ptSps) { int iCpbCount = 0; - int i; + int i; iCpbCount = parseUe(pvBuf); if (iCpbCount > 32U) - { - RPT(RPT_ERR,"iCpbCount %d invalid\n", iCpbCount); - return -1; + { + RPT(RPT_ERR,"iCpbCount %d invalid\n", iCpbCount); + return -1; } getBits(pvBuf, 4); /* bit_rate_scale */ getBits(pvBuf, 4); /* cpb_size_scale */ for (i = 0; i < iCpbCount; i++) - { - parseUe(pvBuf); - parseUe(pvBuf); + { + parseUe(pvBuf); + parseUe(pvBuf); //get_ue_golomb_long(&h->gb); /* bit_rate_value_minus1 */ //get_ue_golomb_long(&h->gb); /* cpb_size_value_minus1 */ getOneBit(pvBuf); /* cbr_flag */ @@ -712,7 +712,7 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) { int iAspectRatioInfoPresentFlag; unsigned int uiAspectRatioIdc; - int iChromaSampleLocation; + int iChromaSampleLocation; iAspectRatioInfoPresentFlag = getOneBit(pvBuf); @@ -725,7 +725,7 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) ptSps->tSar = sg_atFfH264PixelSspect[uiAspectRatioIdc]; } else { - RPT(RPT_ERR,"illegal aspect ratio\n"); + RPT(RPT_ERR,"illegal aspect ratio\n"); return -1; } } else @@ -758,15 +758,15 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) /* chroma_location_info_present_flag */ if (getOneBit(pvBuf)) - { + { /* chroma_sample_location_type_top_field */ iChromaSampleLocation = parseUe(pvBuf); parseUe(pvBuf); /* chroma_sample_location_type_bottom_field */ } - if(getBitsLeft(pvBuf) < 10) - { - return 0; - } + if(getBitsLeft(pvBuf) < 10) + { + return 0; + } ptSps->iTimingInfoPresentFlag = getOneBit(pvBuf); @@ -775,7 +775,7 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) unsigned u32TimeScale = getBits(pvBuf, 32); if (!u32NumUnitsInTick || !u32TimeScale) { - RPT(RPT_ERR,"u32TimeScale/u32NumUnitsInTick invalid or unsupported (%u/%u)\n",u32TimeScale, u32NumUnitsInTick); + RPT(RPT_ERR,"u32TimeScale/u32NumUnitsInTick invalid or unsupported (%u/%u)\n",u32TimeScale, u32NumUnitsInTick); ptSps->iTimingInfoPresentFlag = 0; } else { ptSps->u32NumUnitsInTick = u32NumUnitsInTick; @@ -797,12 +797,12 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) getOneBit(pvBuf); /* low_delay_hrd_flag */ ptSps->iPicStructPresentFlag = getOneBit(pvBuf); - if(getBitsLeft(pvBuf) == 0) - return 0; + if(getBitsLeft(pvBuf) == 0) + return 0; ptSps->iBitstreamRestrictionFlag = getOneBit(pvBuf); if (ptSps->iBitstreamRestrictionFlag) { getOneBit(pvBuf); /* motion_vectors_over_pic_boundaries_flag */ - parseUe(pvBuf); + parseUe(pvBuf); //get_ue_golomb(&h->gb); /* max_bytes_per_pic_denom */ parseUe(pvBuf); //get_ue_golomb(&h->gb); /* max_bits_per_mb_denom */ @@ -812,11 +812,11 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) //get_ue_golomb(&h->gb); /* log2_max_mv_length_vertical */ ptSps->iNumReorderFrames = parseUe(pvBuf); - parseUe(pvBuf); + parseUe(pvBuf); //get_ue_golomb(&h->gb); /*max_dec_frame_buffering*/ if (getBitsLeft(pvBuf) < 0) - { + { ptSps->iNumReorderFrames = 0; ptSps->iBitstreamRestrictionFlag = 0; } @@ -824,7 +824,7 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) if (ptSps->iNumReorderFrames > 16U /* max_dec_frame_buffering || max_dec_frame_buffering > 16 */) { - RPT(RPT_DBG, "Clipping illegal iNumReorderFrames %d\n", + RPT(RPT_DBG, "Clipping illegal iNumReorderFrames %d\n", ptSps->iNumReorderFrames); ptSps->iNumReorderFrames = 16; return -1; @@ -838,10 +838,10 @@ static inline int decodeVuiParameters(void *pvBuf, T_SPS *ptSps) int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) { int iLevelIdc; - int iConstraintSetFlags = 0; + int iConstraintSetFlags = 0; unsigned int uiSpsId; int i; - int iLog2MaxFrameNumMinus4; + int iLog2MaxFrameNumMinus4; int iRet = 0; int iProfileIdc = 0; @@ -910,44 +910,44 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) ptSps->iProfileIdc == 144) { // old High444 profile ptSps->iChromaFormatIdc = parseUe(pvBuf); if (ptSps->iChromaFormatIdc > 3U) - { + { RPT(RPT_ERR, "iChromaFormatIdc %u",ptSps->iChromaFormatIdc); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } - else if (ptSps->iChromaFormatIdc == 3) - { + else if (ptSps->iChromaFormatIdc == 3) + { ptSps->iResidualColorTransformFlag = getOneBit(pvBuf); if (ptSps->iResidualColorTransformFlag) - { - RPT(RPT_ERR, "separate color planes are not supported\n"); - iRet = -1; - goto exit; + { + RPT(RPT_ERR, "separate color planes are not supported\n"); + iRet = -1; + goto exit; } } ptSps->iBitDepthLuma = parseUe(pvBuf) + 8; ptSps->iBitDepthChroma = parseUe(pvBuf) + 8; if (ptSps->iBitDepthChroma != ptSps->iBitDepthLuma) - { - RPT(RPT_ERR, "Different chroma and luma bit depth"); - iRet = -1; - goto exit; + { + RPT(RPT_ERR, "Different chroma and luma bit depth"); + iRet = -1; + goto exit; } if (ptSps->iBitDepthLuma < 8 || ptSps->iBitDepthLuma > 14 || ptSps->iBitDepthChroma < 8 || ptSps->iBitDepthChroma > 14) { - RPT(RPT_ERR, "illegal bit depth value (%d, %d)\n",ptSps->iBitDepthLuma, ptSps->iBitDepthChroma); - iRet = -1; - goto exit; + RPT(RPT_ERR, "illegal bit depth value (%d, %d)\n",ptSps->iBitDepthLuma, ptSps->iBitDepthChroma); + iRet = -1; + goto exit; } ptSps->iTransformBypass = getOneBit(pvBuf); decodeScalingMatrices(pvBuf, ptSps, NULL, 1, ptSps->aau8ScalingMatrix4, ptSps->aau8ScalingMatrix8); } - else - { + else + { ptSps->iChromaFormatIdc = 1; ptSps->iBitDepthLuma = 8; @@ -959,9 +959,9 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) if (iLog2MaxFrameNumMinus4 < MIN_LOG2_MAX_FRAME_NUM - 4 || iLog2MaxFrameNumMinus4 > MAX_LOG2_MAX_FRAME_NUM - 4) { - RPT(RPT_ERR, "iLog2MaxFrameNumMinus4 out of range (0-12): %d\n", iLog2MaxFrameNumMinus4); - iRet = -1; - goto exit; + RPT(RPT_ERR, "iLog2MaxFrameNumMinus4 out of range (0-12): %d\n", iLog2MaxFrameNumMinus4); + iRet = -1; + goto exit; } ptSps->iLog2MaxFrameNum = iLog2MaxFrameNumMinus4 + 4; @@ -969,21 +969,21 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) ptSps->iPocType = parseUe(pvBuf); if (ptSps->iPocType == 0) - { - // FIXME #define + { + // FIXME #define unsigned t = parseUe(pvBuf); if (t>12) - { - RPT(RPT_ERR, "iLog2MaxPocLsb (%d) is out of range\n", t); - iRet = -1; - goto exit; + { + RPT(RPT_ERR, "iLog2MaxPocLsb (%d) is out of range\n", t); + iRet = -1; + goto exit; } ptSps->iLog2MaxPocLsb = t + 4; } - else if (ptSps->iPocType == 1) - { - // FIXME #define + else if (ptSps->iPocType == 1) + { + // FIXME #define ptSps->iDeltaPicOrderAlwaysZeroFlag = getOneBit(pvBuf); ptSps->iOffsetForNonRefPic = parseSe(pvBuf); ptSps->iOffsetForTopToBottomField = parseSe(pvBuf); @@ -991,20 +991,20 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) if ((unsigned)ptSps->iPocCycleLength >= FF_ARRAY_ELEMS(ptSps->asOffsetForRefFrame)) { - RPT(RPT_ERR, "iPocCycleLength overflow %d\n", ptSps->iPocCycleLength); - iRet = -1; - goto exit; + RPT(RPT_ERR, "iPocCycleLength overflow %d\n", ptSps->iPocCycleLength); + iRet = -1; + goto exit; } for (i = 0; i < ptSps->iPocCycleLength; i++) ptSps->asOffsetForRefFrame[i] = parseSe(pvBuf); } - else if (ptSps->iPocType != 2) - { - RPT(RPT_ERR, "illegal POC type %d\n", ptSps->iPocType); - iRet = -1; - goto exit; + else if (ptSps->iPocType != 2) + { + RPT(RPT_ERR, "illegal POC type %d\n", ptSps->iPocType); + iRet = -1; + goto exit; } @@ -1012,9 +1012,9 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) if (ptSps->iRefFrameCount > H264_MAX_PICTURE_COUNT - 2 || ptSps->iRefFrameCount > 16U) { - RPT(RPT_ERR, "too many reference frames %d\n", ptSps->iRefFrameCount); - iRet = -1; - goto exit; + RPT(RPT_ERR, "too many reference frames %d\n", ptSps->iRefFrameCount); + iRet = -1; + goto exit; } ptSps->iGapsInFrameNumAllowedFlag = getOneBit(pvBuf); @@ -1039,8 +1039,8 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) int iWidth = 16 * ptSps->iMbWidth; int iHeight = 16 * ptSps->iMbHeight * (2 - ptSps->iFrameMbsOnlyFlag); - if(1) - { + if(1) + { int vsub = (ptSps->iChromaFormatIdc == 1) ? 1 : 0; int hsub = (ptSps->iChromaFormatIdc == 1 || ptSps->iChromaFormatIdc == 2) ? 1 : 0; @@ -1048,7 +1048,7 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) int step_y = (2 - ptSps->iFrameMbsOnlyFlag) << vsub; if (uiCropLeft & (0x1F >> (ptSps->iBitDepthLuma > 8))) - { + { uiCropLeft &= ~(0x1F >> (ptSps->iBitDepthLuma > 8)); } @@ -1060,9 +1060,9 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) (uiCropTop + uiCropBottom) * step_y >= iHeight ) { - RPT(RPT_ERR, "crop values invalid %d %d %d %d / %d %d\n", uiCropLeft, uiCropRight, uiCropTop, uiCropBottom, iWidth, iHeight); - iRet = -1; - goto exit; + RPT(RPT_ERR, "crop values invalid %d %d %d %d / %d %d\n", uiCropLeft, uiCropRight, uiCropTop, uiCropBottom, iWidth, iHeight); + iRet = -1; + goto exit; } ptSps->uiCropLeft = uiCropLeft * step_x; @@ -1071,8 +1071,8 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) ptSps->uiCropBottom = uiCropBottom * step_y; } } - else - { + else + { ptSps->uiCropLeft = ptSps->uiCropRight = ptSps->uiCropTop = @@ -1088,9 +1088,9 @@ int h264DecSeqParameterSet(void *pvBufSrc, T_SPS *ptSps) } if (getBitsLeft(pvBuf) < 0) - { - RPT(RPT_ERR, "Overread %s by %d bits\n", ptSps->iVuiParametersPresentFlag ? "VUI" : "SPS", -getBitsLeft(pvBuf)); - iRet = -1; + { + RPT(RPT_ERR, "Overread %s by %d bits\n", ptSps->iVuiParametersPresentFlag ? "VUI" : "SPS", -getBitsLeft(pvBuf)); + iRet = -1; } if (!ptSps->tSar.den) @@ -1102,7 +1102,7 @@ exit: #ifdef SPS_PPS_DEBUG if (1) - { + { static const char csp[4][5] = { "Gray", "420", "422", "444" }; RPT(RPT_DBG, "ptSps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %d/%d b%d reo:%d\n", @@ -1168,7 +1168,7 @@ static int decodeProfileTierLevel(T_GetBitContext *pvBuf, T_PTLCommon *tPtl) return 0; } - + static int parsePtl(T_GetBitContext *pvBuf, T_PTL *tPtl, int max_num_sub_layers) { @@ -1208,7 +1208,7 @@ static int parsePtl(T_GetBitContext *pvBuf, T_PTL *tPtl, int max_num_sub_layers) return 0; } - + static void setDefaultScalingListData(T_ScalingList *sl) { @@ -1536,7 +1536,7 @@ static int decodeHrd(T_GetBitContext *pvBuf, int common_inf_present, return 0; } - + static void decodeVui(T_GetBitContext *pvBuf, T_HEVCSPS *ptSps) { @@ -1702,16 +1702,16 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) ptSps->uiVpsId = getBits(pvBuf, 4); if (ptSps->uiVpsId >= HEVC_MAX_VPS_COUNT) { RPT(RPT_ERR, "VPS id out of range: %d\n", ptSps->uiVpsId); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } ptSps->iMaxSubLayers = getBits(pvBuf, 3) + 1; if (ptSps->iMaxSubLayers > HEVC_MAX_SUB_LAYERS) { RPT(RPT_ERR, "sps_max_sub_layers out of range: %d\n", ptSps->iMaxSubLayers); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } ptSps->u8temporalIdNestingFlag = getBits(pvBuf, 1); @@ -1721,15 +1721,15 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) int sps_id = parseUe(pvBuf); if (sps_id >= HEVC_MAX_SPS_COUNT) { RPT(RPT_ERR, "SPS id out of range: %d\n", sps_id); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } ptSps->iChromaFormatIdc = parseUe(pvBuf); if (ptSps->iChromaFormatIdc > 3U) { RPT(RPT_ERR, "iChromaFormatIdc %d is invalid\n", ptSps->iChromaFormatIdc); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } if (ptSps->iChromaFormatIdc == 3) @@ -1754,14 +1754,14 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) ptSps->iBitDepth = parseUe(pvBuf) + 8; iBitDepthChroma = parseUe(pvBuf) + 8; - + if (ptSps->iChromaFormatIdc && iBitDepthChroma != ptSps->iBitDepth) { RPT(RPT_ERR, "Luma bit depth (%d) is different from chroma bit depth (%d), " "this is unsupported.\n", ptSps->iBitDepth, iBitDepthChroma); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } ptSps->iBitDepthChroma = iBitDepthChroma; @@ -1769,8 +1769,8 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) if (ptSps->uiLog2MaxPocLsb > 16) { RPT(RPT_ERR, "log2_max_pic_order_cnt_lsb_minus4 out range: %d\n", ptSps->uiLog2MaxPocLsb - 4); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } iSublayerOrderingInfo = getOneBit(pvBuf); @@ -1782,15 +1782,15 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) if (ptSps->stTemporalLayer[i].iMaxDecPicBuffering > (unsigned)HEVC_MAX_DPB_SIZE) { RPT(RPT_ERR, "sps_max_dec_pic_buffering_minus1 out of range: %d\n", ptSps->stTemporalLayer[i].iMaxDecPicBuffering - 1U); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } if (ptSps->stTemporalLayer[i].iNumReorderPics > ptSps->stTemporalLayer[i].iMaxDecPicBuffering - 1) { RPT(RPT_WRN, "sps_max_num_reorder_pics out of range: %d\n", ptSps->stTemporalLayer[i].iNumReorderPics); if (ptSps->stTemporalLayer[i].iNumReorderPics > HEVC_MAX_DPB_SIZE - 1) { - iRet = -1; - goto exit; + iRet = -1; + goto exit; } ptSps->stTemporalLayer[i].iMaxDecPicBuffering = ptSps->stTemporalLayer[i].iNumReorderPics + 1; } @@ -1813,33 +1813,33 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) if (ptSps->uiLog2MinCbSize < 3 || ptSps->uiLog2MinCbSize > 30) { RPT(RPT_ERR, "Invalid value %d for uiLog2MinCbSize", ptSps->uiLog2MinCbSize); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } if (ptSps->uiLog2DiffMaxMinCodingBlockSize > 30) { RPT(RPT_ERR, "Invalid value %d for uiLog2DiffMaxMinCodingBlockSize", ptSps->uiLog2DiffMaxMinCodingBlockSize); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } if (ptSps->uiLog2MinTbSize >= ptSps->uiLog2MinCbSize || ptSps->uiLog2MinTbSize < 2) { RPT(RPT_ERR, "Invalid value for uiLog2MinTbSize"); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } if (iLog2DiffMaxMinTransformBlockSize < 0 || iLog2DiffMaxMinTransformBlockSize > 30) { RPT(RPT_ERR, "Invalid value %d for iLog2DiffMaxMinTransformBlockSize", iLog2DiffMaxMinTransformBlockSize); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } ptSps->iMaxTransformHierarchyDepthInter = parseUe(pvBuf); ptSps->iMaxTransformHierarchyDepthIntra = parseUe(pvBuf); ptSps->u8ScalingListEnableFlag = getOneBit(pvBuf); - + if (ptSps->u8ScalingListEnableFlag) { setDefaultScalingListData(&ptSps->tScalingList); @@ -1854,7 +1854,7 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) ptSps->u8SaoEnabled = getOneBit(pvBuf); ptSps->iPcmEnabledFlag = getOneBit(pvBuf); - + if (ptSps->iPcmEnabledFlag) { ptSps->pcm.u8BitDepth = getBits(pvBuf, 4) + 1; ptSps->pcm.u8BitDepthChroma = getBits(pvBuf, 4) + 1; @@ -1865,8 +1865,8 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) RPT(RPT_ERR, "PCM bit depth (%d, %d) is greater than normal bit depth (%d)\n", ptSps->pcm.u8BitDepth, ptSps->pcm.u8BitDepthChroma, ptSps->iBitDepth); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } ptSps->pcm.u8LoopFilterDisableFlag = getOneBit(pvBuf); @@ -1876,8 +1876,8 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) if (ptSps->uiNbStRps > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) { RPT(RPT_ERR, "Too many short term RPS: %d.\n", ptSps->uiNbStRps); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } for (i = 0; i < ptSps->uiNbStRps; i++) { if ((iRet = hevcDecodeShortTermRps(pvBuf, &ptSps->atStRps[i], @@ -1891,8 +1891,8 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) if (ptSps->u8NumLongTermRefPicsSps > HEVC_MAX_LONG_TERM_REF_PICS) { RPT(RPT_ERR, "Too many long term ref pics: %d.\n", ptSps->u8NumLongTermRefPicsSps); - iRet = -1; - goto exit; + iRet = -1; + goto exit; } for (i = 0; i < ptSps->u8NumLongTermRefPicsSps; i++) { ptSps->au16LtRefPicPocLsbSps[i] = getBits(pvBuf, ptSps->uiLog2MaxPocLsb); @@ -1962,14 +1962,14 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) if (ptSps->uiLog2CtbSize > HEVC_MAX_LOG2_CTB_SIZE) { RPT(RPT_ERR, "CTB size out of range: 2^%d\n", ptSps->uiLog2CtbSize); iRet = -1; - goto exit; + goto exit; } if (ptSps->uiLog2CtbSize < 4) { RPT(RPT_ERR, "uiLog2CtbSize %d differs from the bounds of any known profile\n", ptSps->uiLog2CtbSize); iRet = -1; - goto exit; + goto exit; } ptSps->iCtbWidth = (ptSps->iWidth + (1 << ptSps->uiLog2CtbSize) - 1) >> ptSps->uiLog2CtbSize; @@ -1990,201 +1990,201 @@ int h265DecSeqParameterSet( void *pvBufSrc, T_HEVCSPS *ptSps ) avModUintp2c(ptSps->iHeight, ptSps->uiLog2MinCbSize)) { RPT(RPT_ERR, "Invalid coded frame dimensions.\n"); iRet = -1; - goto exit; + goto exit; } if (ptSps->iMaxTransformHierarchyDepthInter > ptSps->uiLog2CtbSize - ptSps->uiLog2MinTbSize) { RPT(RPT_ERR, "iMaxTransformHierarchyDepthInter out of range: %d\n", ptSps->iMaxTransformHierarchyDepthInter); iRet = -1; - goto exit; + goto exit; } if (ptSps->iMaxTransformHierarchyDepthIntra > ptSps->uiLog2CtbSize - ptSps->uiLog2MinTbSize) { RPT(RPT_ERR, "iMaxTransformHierarchyDepthIntra out of range: %d\n", ptSps->iMaxTransformHierarchyDepthIntra); iRet = -1; - goto exit; + goto exit; } if (ptSps->uiLog2MaxTrafoSize > FFMIN(ptSps->uiLog2CtbSize, 5)) { RPT(RPT_ERR, "max transform block size out of range: %d\n", ptSps->uiLog2MaxTrafoSize); iRet = -1; - goto exit; + goto exit; } if (getBitsLeft(pvBuf) < 0) { RPT(RPT_ERR, "Overread SPS by %d bits\n", -getBitsLeft(pvBuf)); iRet = -1; - goto exit; + goto exit; } - + exit: - getBitContextFree(pvBuf); - return iRet; + getBitContextFree(pvBuf); + return iRet; } int h265DecVideoParameterSet( void *pvBufSrc, T_HEVCVPS *ptVps ) { - int iRet = 0; + int iRet = 0; int i,j; int uiVpsId = 0; - - void *pvBuf = NULL; - if(NULL == pvBufSrc || NULL == ptVps) - { - RPT(RPT_ERR,"ERR null pointer\n"); - iRet = -1; - goto exit; - } + + void *pvBuf = NULL; + if(NULL == pvBufSrc || NULL == ptVps) + { + RPT(RPT_ERR,"ERR null pointer\n"); + iRet = -1; + goto exit; + } - memset((void *)ptVps, 0, sizeof(T_HEVCVPS)); + memset((void *)ptVps, 0, sizeof(T_HEVCVPS)); - pvBuf = deEmulationPrevention(pvBufSrc); - if(NULL == pvBuf) - { - RPT(RPT_ERR,"ERR null pointer\n"); - iRet = -1; - goto exit; - } + pvBuf = deEmulationPrevention(pvBufSrc); + if(NULL == pvBuf) + { + RPT(RPT_ERR,"ERR null pointer\n"); + iRet = -1; + goto exit; + } - RPT(RPT_DBG, "Decoding VPS\n"); + RPT(RPT_DBG, "Decoding VPS\n"); - uiVpsId = getBits(pvBuf, 4); - if (uiVpsId >= HEVC_MAX_VPS_COUNT) { - RPT(RPT_ERR, "VPS id out of range: %d\n", uiVpsId); - iRet = -1; - goto exit; - } + uiVpsId = getBits(pvBuf, 4); + if (uiVpsId >= HEVC_MAX_VPS_COUNT) { + RPT(RPT_ERR, "VPS id out of range: %d\n", uiVpsId); + iRet = -1; + goto exit; + } - if (getBits(pvBuf, 2) != 3) { // vps_reserved_three_2bits - RPT(RPT_ERR, "vps_reserved_three_2bits is not three\n"); - iRet = -1; - goto exit; - } + if (getBits(pvBuf, 2) != 3) { // vps_reserved_three_2bits + RPT(RPT_ERR, "vps_reserved_three_2bits is not three\n"); + iRet = -1; + goto exit; + } - ptVps->iVpsMaxLayers = getBits(pvBuf, 6) + 1; - ptVps->iVpsMaxSubLayers = getBits(pvBuf, 3) + 1; - ptVps->u8VpsTemporalIdNestingFlag = getOneBit(pvBuf); + ptVps->iVpsMaxLayers = getBits(pvBuf, 6) + 1; + ptVps->iVpsMaxSubLayers = getBits(pvBuf, 3) + 1; + ptVps->u8VpsTemporalIdNestingFlag = getOneBit(pvBuf); - if (getBits(pvBuf, 16) != 0xffff) { // vps_reserved_ffff_16bits - RPT(RPT_ERR, "vps_reserved_ffff_16bits is not 0xffff\n"); - iRet = -1; - goto exit; - } + if (getBits(pvBuf, 16) != 0xffff) { // vps_reserved_ffff_16bits + RPT(RPT_ERR, "vps_reserved_ffff_16bits is not 0xffff\n"); + iRet = -1; + goto exit; + } - if (ptVps->iVpsMaxSubLayers > HEVC_MAX_SUB_LAYERS) { - RPT(RPT_ERR, "iVpsMaxSubLayers out of range: %d\n", - ptVps->iVpsMaxSubLayers); - iRet = -1; - goto exit; - } + if (ptVps->iVpsMaxSubLayers > HEVC_MAX_SUB_LAYERS) { + RPT(RPT_ERR, "iVpsMaxSubLayers out of range: %d\n", + ptVps->iVpsMaxSubLayers); + iRet = -1; + goto exit; + } - if (parsePtl(pvBuf, &ptVps->tPtl, ptVps->iVpsMaxSubLayers) < 0){ - iRet = -1; - goto exit; - } + if (parsePtl(pvBuf, &ptVps->tPtl, ptVps->iVpsMaxSubLayers) < 0){ + iRet = -1; + goto exit; + } - ptVps->iVpsSubLayerOrderingInfoPresentFlag = getOneBit(pvBuf); + ptVps->iVpsSubLayerOrderingInfoPresentFlag = getOneBit(pvBuf); - i = ptVps->iVpsSubLayerOrderingInfoPresentFlag ? 0 : ptVps->iVpsMaxSubLayers - 1; - for (; i < ptVps->iVpsMaxSubLayers; i++) { - ptVps->uiVpsMaxDecPicBuffering[i] = parseUe(pvBuf) + 1; - ptVps->auiVpsNumReorderPics[i] = parseUe(pvBuf); - ptVps->auiVpsMaxLatencyIncrease[i] = parseUe(pvBuf) - 1; + i = ptVps->iVpsSubLayerOrderingInfoPresentFlag ? 0 : ptVps->iVpsMaxSubLayers - 1; + for (; i < ptVps->iVpsMaxSubLayers; i++) { + ptVps->uiVpsMaxDecPicBuffering[i] = parseUe(pvBuf) + 1; + ptVps->auiVpsNumReorderPics[i] = parseUe(pvBuf); + ptVps->auiVpsMaxLatencyIncrease[i] = parseUe(pvBuf) - 1; - if (ptVps->uiVpsMaxDecPicBuffering[i] > HEVC_MAX_DPB_SIZE || !ptVps->uiVpsMaxDecPicBuffering[i]) { - RPT(RPT_ERR, "vps_max_dec_pic_buffering_minus1 out of range: %d\n", - ptVps->uiVpsMaxDecPicBuffering[i] - 1); - iRet = -1; - goto exit; - } - if (ptVps->auiVpsNumReorderPics[i] > ptVps->uiVpsMaxDecPicBuffering[i] - 1) { - RPT(RPT_WRN, "vps_max_num_reorder_pics out of range: %d\n", - ptVps->auiVpsNumReorderPics[i]); - } - } + if (ptVps->uiVpsMaxDecPicBuffering[i] > HEVC_MAX_DPB_SIZE || !ptVps->uiVpsMaxDecPicBuffering[i]) { + RPT(RPT_ERR, "vps_max_dec_pic_buffering_minus1 out of range: %d\n", + ptVps->uiVpsMaxDecPicBuffering[i] - 1); + iRet = -1; + goto exit; + } + if (ptVps->auiVpsNumReorderPics[i] > ptVps->uiVpsMaxDecPicBuffering[i] - 1) { + RPT(RPT_WRN, "vps_max_num_reorder_pics out of range: %d\n", + ptVps->auiVpsNumReorderPics[i]); + } + } - ptVps->iVpsMaxLayerId = getBits(pvBuf, 6); - ptVps->iVpsNumLayerSets = parseUe(pvBuf) + 1; - if (ptVps->iVpsNumLayerSets < 1 || ptVps->iVpsNumLayerSets > 1024 || - (ptVps->iVpsNumLayerSets - 1LL) * (ptVps->iVpsMaxLayerId + 1LL) > getBitsLeft(pvBuf)) { - RPT(RPT_ERR, "too many layer_id_included_flags\n"); - iRet = -1; - goto exit; - } + ptVps->iVpsMaxLayerId = getBits(pvBuf, 6); + ptVps->iVpsNumLayerSets = parseUe(pvBuf) + 1; + if (ptVps->iVpsNumLayerSets < 1 || ptVps->iVpsNumLayerSets > 1024 || + (ptVps->iVpsNumLayerSets - 1LL) * (ptVps->iVpsMaxLayerId + 1LL) > getBitsLeft(pvBuf)) { + RPT(RPT_ERR, "too many layer_id_included_flags\n"); + iRet = -1; + goto exit; + } - for (i = 1; i < ptVps->iVpsNumLayerSets; i++) - for (j = 0; j <= ptVps->iVpsMaxLayerId; j++) - getBits(pvBuf, 1); // layer_id_included_flag[i][j] + for (i = 1; i < ptVps->iVpsNumLayerSets; i++) + for (j = 0; j <= ptVps->iVpsMaxLayerId; j++) + getBits(pvBuf, 1); // layer_id_included_flag[i][j] - ptVps->u8VpsTimingInfoPresentFlag = getOneBit(pvBuf); - if (ptVps->u8VpsTimingInfoPresentFlag) { - ptVps->u32VpsNumUnitsInTick = getBits(pvBuf, 32); - ptVps->u32VpsTimeScale = getBits(pvBuf, 32); - ptVps->u8VpsPocProportionalToTimingFlag = getOneBit(pvBuf); - if (ptVps->u8VpsPocProportionalToTimingFlag) - ptVps->iVpsNumTicksPocDiffOne = parseUe(pvBuf) + 1; - ptVps->iVpsNumHrdParameters = parseUe(pvBuf); - if (ptVps->iVpsNumHrdParameters > (unsigned)ptVps->iVpsNumLayerSets) { - RPT(RPT_ERR, - "iVpsNumHrdParameters %d is invalid\n", ptVps->iVpsNumHrdParameters); - iRet = -1; - goto exit; - } - for (i = 0; i < ptVps->iVpsNumHrdParameters; i++) { - int common_inf_present = 1; + ptVps->u8VpsTimingInfoPresentFlag = getOneBit(pvBuf); + if (ptVps->u8VpsTimingInfoPresentFlag) { + ptVps->u32VpsNumUnitsInTick = getBits(pvBuf, 32); + ptVps->u32VpsTimeScale = getBits(pvBuf, 32); + ptVps->u8VpsPocProportionalToTimingFlag = getOneBit(pvBuf); + if (ptVps->u8VpsPocProportionalToTimingFlag) + ptVps->iVpsNumTicksPocDiffOne = parseUe(pvBuf) + 1; + ptVps->iVpsNumHrdParameters = parseUe(pvBuf); + if (ptVps->iVpsNumHrdParameters > (unsigned)ptVps->iVpsNumLayerSets) { + RPT(RPT_ERR, + "iVpsNumHrdParameters %d is invalid\n", ptVps->iVpsNumHrdParameters); + iRet = -1; + goto exit; + } + for (i = 0; i < ptVps->iVpsNumHrdParameters; i++) { + int common_inf_present = 1; - parseUe(pvBuf); // hrd_layer_set_idx - if (i) - common_inf_present = getOneBit(pvBuf); - decodeHrd(pvBuf, common_inf_present, ptVps->iVpsMaxSubLayers); - } - } - getOneBit(pvBuf); /* vps_extension_flag */ + parseUe(pvBuf); // hrd_layer_set_idx + if (i) + common_inf_present = getOneBit(pvBuf); + decodeHrd(pvBuf, common_inf_present, ptVps->iVpsMaxSubLayers); + } + } + getOneBit(pvBuf); /* vps_extension_flag */ - if (getBitsLeft(pvBuf) < 0) { - RPT(RPT_ERR, - "Overread VPS by %d bits\n", -getBitsLeft(pvBuf)); - - iRet = -1; - goto exit; - } + if (getBitsLeft(pvBuf) < 0) { + RPT(RPT_ERR, + "Overread VPS by %d bits\n", -getBitsLeft(pvBuf)); + + iRet = -1; + goto exit; + } exit: - getBitContextFree(pvBuf); - return iRet; + getBitContextFree(pvBuf); + return iRet; } - + void h264GetWidthHeight(T_SPS *ptSps, int *piWidth, int *piHeight) { - // ¿í¸ß¼ÆË㹫ʽ - int iCodeWidth = 0; - int iCodedHeight = 0; - iCodeWidth = 16 * ptSps->iMbWidth; - iCodedHeight = 16 * ptSps->iMbHeight; - *piWidth = iCodeWidth - (ptSps->uiCropRight + ptSps->uiCropLeft); - *piHeight = iCodedHeight - (ptSps->uiCropTop + ptSps->uiCropBottom); - if (*piWidth <= 0 || *piHeight <= 0) { - *piWidth = iCodeWidth; - *piHeight = iCodedHeight; - } + // ¿í¸ß¼ÆË㹫ʽ + int iCodeWidth = 0; + int iCodedHeight = 0; + iCodeWidth = 16 * ptSps->iMbWidth; + iCodedHeight = 16 * ptSps->iMbHeight; + *piWidth = iCodeWidth - (ptSps->uiCropRight + ptSps->uiCropLeft); + *piHeight = iCodedHeight - (ptSps->uiCropTop + ptSps->uiCropBottom); + if (*piWidth <= 0 || *piHeight <= 0) { + *piWidth = iCodeWidth; + *piHeight = iCodedHeight; + } - RPT(RPT_DBG, "iCodeWidth:%d, iCodedHeight:%d\n", iCodeWidth, iCodedHeight); + RPT(RPT_DBG, "iCodeWidth:%d, iCodedHeight:%d\n", iCodeWidth, iCodedHeight); - RPT(RPT_DBG, "*piWidth:%d, *piHeight:%d\n", *piWidth, *piHeight); + RPT(RPT_DBG, "*piWidth:%d, *piHeight:%d\n", *piWidth, *piHeight); - RPT(RPT_DBG, "ptSps->uiCropRight:%d, ptSps->uiCropLeft:%d\n", ptSps->uiCropRight, ptSps->uiCropLeft); + RPT(RPT_DBG, "ptSps->uiCropRight:%d, ptSps->uiCropLeft:%d\n", ptSps->uiCropRight, ptSps->uiCropLeft); - RPT(RPT_DBG, "ptSps->uiCropTop:%d, ptSps->uiCropBottom:%d\n", ptSps->uiCropTop, ptSps->uiCropBottom); + RPT(RPT_DBG, "ptSps->uiCropTop:%d, ptSps->uiCropBottom:%d\n", ptSps->uiCropTop, ptSps->uiCropBottom); } @@ -2213,43 +2213,43 @@ void h264GeFramerate(T_SPS *ptSps, float *pfFramerate) switch(iFrInt) { case 23:// 23.98 - RPT(RPT_DBG, "frame rate:23.98"); + RPT(RPT_DBG, "frame rate:23.98"); break; case 24: - RPT(RPT_DBG, "frame rate:24"); + RPT(RPT_DBG, "frame rate:24"); break; case 25: - RPT(RPT_DBG, "frame rate:25"); + RPT(RPT_DBG, "frame rate:25"); break; case 29://29.97 - RPT(RPT_DBG, "frame rate:29.97"); + RPT(RPT_DBG, "frame rate:29.97"); break; case 30: - RPT(RPT_DBG, "frame rate:30"); + RPT(RPT_DBG, "frame rate:30"); break; case 50: - RPT(RPT_DBG, "frame rate:50"); + RPT(RPT_DBG, "frame rate:50"); break; case 59://59.94 - RPT(RPT_DBG, "frame rate:59.94"); + RPT(RPT_DBG, "frame rate:59.94"); break; case 60: - RPT(RPT_DBG, "frame rate:60"); + RPT(RPT_DBG, "frame rate:60"); break; case 6: - RPT(RPT_DBG, "frame rate:6"); + RPT(RPT_DBG, "frame rate:6"); break; case 8: - RPT(RPT_DBG, "frame rate:8"); + RPT(RPT_DBG, "frame rate:8"); break; case 12: - RPT(RPT_DBG, "frame rate:12"); + RPT(RPT_DBG, "frame rate:12"); break; case 15: - RPT(RPT_DBG, "frame rate:15"); + RPT(RPT_DBG, "frame rate:15"); break; case 10: - RPT(RPT_DBG, "frame rate:10"); + RPT(RPT_DBG, "frame rate:10"); break; default: @@ -2266,21 +2266,21 @@ void h264GeFramerate(T_SPS *ptSps, float *pfFramerate) void h265GetWidthHeight(T_HEVCSPS *ptSps, int *piWidth, int *piHeight) { #if 1 - int iCodeWidth = 0; - int iCodedHeight = 0; - iCodeWidth = ptSps->iWidth; - iCodedHeight = ptSps->iHeight; - *piWidth = ptSps->iWidth - ptSps->tOutputWindow.uiLeftOffset - ptSps->tOutputWindow.uiRightOffset; - *piHeight = ptSps->iHeight - ptSps->tOutputWindow.uiTopOffset - ptSps->tOutputWindow.uiBottomOffset; + int iCodeWidth = 0; + int iCodedHeight = 0; + iCodeWidth = ptSps->iWidth; + iCodedHeight = ptSps->iHeight; + *piWidth = ptSps->iWidth - ptSps->tOutputWindow.uiLeftOffset - ptSps->tOutputWindow.uiRightOffset; + *piHeight = ptSps->iHeight - ptSps->tOutputWindow.uiTopOffset - ptSps->tOutputWindow.uiBottomOffset; - RPT(RPT_DBG, "iCodeWidth:%d, iCodedHeight:%d\n", iCodeWidth, iCodedHeight); + RPT(RPT_DBG, "iCodeWidth:%d, iCodedHeight:%d\n", iCodeWidth, iCodedHeight); - RPT(RPT_DBG, "*piWidth:%d, *piHeight:%d\n", *piWidth, *piHeight); + RPT(RPT_DBG, "*piWidth:%d, *piHeight:%d\n", *piWidth, *piHeight); - RPT(RPT_DBG, "ptSps->tOutputWindow.uiRightOffset:%d, ptSps->tOutputWindow.uiLeftOffset:%d\n", ptSps->tOutputWindow.uiRightOffset, ptSps->tOutputWindow.uiLeftOffset); + RPT(RPT_DBG, "ptSps->tOutputWindow.uiRightOffset:%d, ptSps->tOutputWindow.uiLeftOffset:%d\n", ptSps->tOutputWindow.uiRightOffset, ptSps->tOutputWindow.uiLeftOffset); - RPT(RPT_DBG, "ptSps->tOutputWindow.uiTopOffset:%d, ptSps->tOutputWindow.uiBottomOffset:%d\n", ptSps->tOutputWindow.uiTopOffset, ptSps->tOutputWindow.uiBottomOffset); + RPT(RPT_DBG, "ptSps->tOutputWindow.uiTopOffset:%d, ptSps->tOutputWindow.uiBottomOffset:%d\n", ptSps->tOutputWindow.uiTopOffset, ptSps->tOutputWindow.uiBottomOffset); #endif } @@ -2290,15 +2290,15 @@ void h265GetWidthHeight(T_HEVCSPS *ptSps, int *piWidth, int *piHeight) void h265GeFramerate(T_HEVCVPS *ptVps, T_HEVCSPS *ptSps,float *pfFramerate) { if (ptVps && ptVps->u8VpsTimingInfoPresentFlag) { - *pfFramerate = (float)(ptVps->u32VpsTimeScale) / (float)(ptVps->u32VpsNumUnitsInTick); - + *pfFramerate = (float)(ptVps->u32VpsTimeScale) / (float)(ptVps->u32VpsNumUnitsInTick); + } else if (ptSps && ptSps->tVui.iVuiTimingInfoPresentFlag && ptSps->iVuiPresent) { - *pfFramerate = (float)(ptSps->tVui.u32VuiTimeScale) / (float)(ptSps->tVui.u32VuiNumUnitsInTick); + *pfFramerate = (float)(ptSps->tVui.u32VuiTimeScale) / (float)(ptSps->tVui.u32VuiNumUnitsInTick); + } + else{ + //vps sps可能不包含帧率 + *pfFramerate = 0.0F; + RPT(RPT_WRN, "frame rate:0"); } - else{ - //vps sps可能不包含帧率 - *pfFramerate = 0.0F; - RPT(RPT_WRN, "frame rate:0"); - } } diff --git a/src/Extension/SPSParser.h b/src/Extension/SPSParser.h index 1fb97adc..6cdb6005 100644 --- a/src/Extension/SPSParser.h +++ b/src/Extension/SPSParser.h @@ -434,7 +434,7 @@ typedef struct T_HEVCSPS { int iQpBdOffset; - int iVuiPresent; + int iVuiPresent; }T_HEVCSPS; diff --git a/src/Extension/Track.h b/src/Extension/Track.h index ccd675e9..2d23e652 100644 --- a/src/Extension/Track.h +++ b/src/Extension/Track.h @@ -137,10 +137,10 @@ public: virtual ~TrackSource(){} /** - * 获取全部的Track - * @param trackReady 是否获取全部已经准备好的Track - * @return - */ + * 获取全部的Track + * @param trackReady 是否获取全部已经准备好的Track + * @return + */ virtual vector getTracks(bool trackReady = true) const = 0; /** diff --git a/src/Http/HttpClient.h b/src/Http/HttpClient.h index 59ab4629..b2997580 100644 --- a/src/Http/HttpClient.h +++ b/src/Http/HttpClient.h @@ -148,7 +148,7 @@ protected: * 接收http回复完毕, */ virtual void onResponseCompleted(){ - DebugL; + DebugL; } /** diff --git a/src/Http/HttpClientImp.cpp b/src/Http/HttpClientImp.cpp index c6dff3ed..2d880d4f 100644 --- a/src/Http/HttpClientImp.cpp +++ b/src/Http/HttpClientImp.cpp @@ -29,11 +29,11 @@ namespace mediakit { void HttpClientImp::onConnect(const SockException &ex) { - if(!_isHttps){ - HttpClient::onConnect(ex); - } else { - TcpClientWithSSL::onConnect(ex); - } + if(!_isHttps){ + HttpClient::onConnect(ex); + } else { + TcpClientWithSSL::onConnect(ex); + } } diff --git a/src/Http/HttpClientImp.h b/src/Http/HttpClientImp.h index 277d85b5..76a28af7 100644 --- a/src/Http/HttpClientImp.h +++ b/src/Http/HttpClientImp.h @@ -36,11 +36,11 @@ namespace mediakit { class HttpClientImp: public TcpClientWithSSL { public: - typedef std::shared_ptr Ptr; - HttpClientImp() {} - virtual ~HttpClientImp() {} + typedef std::shared_ptr Ptr; + HttpClientImp() {} + virtual ~HttpClientImp() {} protected: - void onConnect(const SockException &ex) override ; + void onConnect(const SockException &ex) override ; }; } /* namespace mediakit */ diff --git a/src/Http/HttpDownloader.cpp b/src/Http/HttpDownloader.cpp index aac62e0b..4a6fc4e1 100644 --- a/src/Http/HttpDownloader.cpp +++ b/src/Http/HttpDownloader.cpp @@ -36,75 +36,75 @@ HttpDownloader::HttpDownloader() { } HttpDownloader::~HttpDownloader() { - closeFile(); + closeFile(); } void HttpDownloader::startDownload(const string& url, const string& filePath,bool bAppend,float timeOutSecond) { - _filePath = filePath; - if(_filePath.empty()){ - _filePath = exeDir() + "HttpDownloader/" + MD5(url).hexdigest(); - } - _saveFile = File::createfile_file(_filePath.data(),bAppend ? "ab" : "wb"); - if(!_saveFile){ - auto strErr = StrPrinter << "打开文件失败:" << filePath << endl; - throw std::runtime_error(strErr); - } - _bDownloadSuccess = false; - if(bAppend){ - auto currentLen = ftell(_saveFile); - if(currentLen){ - //最少续传一个字节,怕遇到http 416的错误 - currentLen -= 1; - fseek(_saveFile,-1,SEEK_CUR); - } - addHeader("Range", StrPrinter << "bytes=" << currentLen << "-" << endl); - } - setMethod("GET"); - sendRequest(url,timeOutSecond); + _filePath = filePath; + if(_filePath.empty()){ + _filePath = exeDir() + "HttpDownloader/" + MD5(url).hexdigest(); + } + _saveFile = File::createfile_file(_filePath.data(),bAppend ? "ab" : "wb"); + if(!_saveFile){ + auto strErr = StrPrinter << "打开文件失败:" << filePath << endl; + throw std::runtime_error(strErr); + } + _bDownloadSuccess = false; + if(bAppend){ + auto currentLen = ftell(_saveFile); + if(currentLen){ + //最少续传一个字节,怕遇到http 416的错误 + currentLen -= 1; + fseek(_saveFile,-1,SEEK_CUR); + } + addHeader("Range", StrPrinter << "bytes=" << currentLen << "-" << endl); + } + setMethod("GET"); + sendRequest(url,timeOutSecond); } int64_t HttpDownloader::onResponseHeader(const string& status,const HttpHeader& headers) { if(status != "200" && status != "206"){ - //失败 - shutdown(SockException(Err_shutdown,StrPrinter << "Http Status:" << status)); - } - //后续全部是content - return -1; + //失败 + shutdown(SockException(Err_shutdown,StrPrinter << "Http Status:" << status)); + } + //后续全部是content + return -1; } void HttpDownloader::onResponseBody(const char* buf, int64_t size, int64_t recvedSize, int64_t totalSize) { if(_saveFile){ - fwrite(buf,size,1,_saveFile); - } + fwrite(buf,size,1,_saveFile); + } } void HttpDownloader::onResponseCompleted() { - closeFile(); - //InfoL << "md5Sum:" << getMd5Sum(_filePath); - _bDownloadSuccess = true; - if(_onResult){ - _onResult(Err_success,"success",_filePath); - _onResult = nullptr; - } + closeFile(); + //InfoL << "md5Sum:" << getMd5Sum(_filePath); + _bDownloadSuccess = true; + if(_onResult){ + _onResult(Err_success,"success",_filePath); + _onResult = nullptr; + } } void HttpDownloader::onDisconnect(const SockException &ex) { - closeFile(); - if(!_bDownloadSuccess){ - File::delete_file(_filePath.data()); - } - if(_onResult){ - _onResult(ex.getErrCode(),ex.what(),_filePath); - _onResult = nullptr; - } + closeFile(); + if(!_bDownloadSuccess){ + File::delete_file(_filePath.data()); + } + if(_onResult){ + _onResult(ex.getErrCode(),ex.what(),_filePath); + _onResult = nullptr; + } } void HttpDownloader::closeFile() { - if(_saveFile){ - fflush(_saveFile); - fclose(_saveFile); - _saveFile = nullptr; - } + if(_saveFile){ + fflush(_saveFile); + fclose(_saveFile); + _saveFile = nullptr; + } } diff --git a/src/Http/HttpDownloader.h b/src/Http/HttpDownloader.h index d8d147ce..b839521f 100644 --- a/src/Http/HttpDownloader.h +++ b/src/Http/HttpDownloader.h @@ -33,30 +33,30 @@ namespace mediakit { class HttpDownloader: public HttpClientImp { public: - typedef std::shared_ptr Ptr; - typedef std::function onDownloadResult; - HttpDownloader(); - virtual ~HttpDownloader(); - //开始下载文件,默认断点续传方式下载 - 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){ - setOnResult(cb); - startDownload(url,"",false,timeOutSecond); - } - void setOnResult(const onDownloadResult &cb){ - _onResult = cb; - } + typedef std::shared_ptr Ptr; + typedef std::function onDownloadResult; + HttpDownloader(); + virtual ~HttpDownloader(); + //开始下载文件,默认断点续传方式下载 + 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){ + setOnResult(cb); + startDownload(url,"",false,timeOutSecond); + } + void setOnResult(const onDownloadResult &cb){ + _onResult = cb; + } private: - 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 onResponseCompleted() override; - void onDisconnect(const SockException &ex) 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 onResponseCompleted() override; + void onDisconnect(const SockException &ex) override; void closeFile(); private: - FILE *_saveFile = nullptr; - string _filePath; - onDownloadResult _onResult; - bool _bDownloadSuccess = false; + FILE *_saveFile = nullptr; + string _filePath; + onDownloadResult _onResult; + bool _bDownloadSuccess = false; }; } /* namespace mediakit */ diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index a1bae44f..a6a886d1 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -45,8 +45,8 @@ HttpSession::HttpSession(const Socket::Ptr &pSock) : TcpSession(pSock) { TraceP(this); GET_CONFIG(uint32_t,keep_alive_sec,Http::kKeepAliveSecond); pSock->setSendTimeOutSecond(keep_alive_sec); - //起始接收buffer缓存设置为4K,节省内存 - pSock->setReadBuffer(std::make_shared(4 * 1024)); + //起始接收buffer缓存设置为4K,节省内存 + pSock->setReadBuffer(std::make_shared(4 * 1024)); } HttpSession::~HttpSession() { @@ -61,48 +61,48 @@ void HttpSession::Handle_Req_HEAD(int64_t &content_len){ } int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) { - typedef void (HttpSession::*HttpCMDHandle)(int64_t &); - static unordered_map s_func_map; - static onceToken token([]() { - s_func_map.emplace("GET",&HttpSession::Handle_Req_GET); - s_func_map.emplace("POST",&HttpSession::Handle_Req_POST); + typedef void (HttpSession::*HttpCMDHandle)(int64_t &); + static unordered_map s_func_map; + static onceToken token([]() { + s_func_map.emplace("GET",&HttpSession::Handle_Req_GET); + s_func_map.emplace("POST",&HttpSession::Handle_Req_POST); s_func_map.emplace("HEAD",&HttpSession::Handle_Req_HEAD); }, nullptr); - _parser.Parse(header); - urlDecode(_parser); - string cmd = _parser.Method(); - auto it = s_func_map.find(cmd); - if (it == s_func_map.end()) { - WarnL << "不支持该命令:" << cmd; - sendResponse("405 Not Allowed", true); + _parser.Parse(header); + urlDecode(_parser); + string cmd = _parser.Method(); + auto it = s_func_map.find(cmd); + if (it == s_func_map.end()) { + WarnL << "不支持该命令:" << cmd; + sendResponse("405 Not Allowed", true); return 0; - } + } //跨域 _origin = _parser["Origin"]; //默认后面数据不是content而是header - int64_t content_len = 0; - auto &fun = it->second; + int64_t content_len = 0; + auto &fun = it->second; try { (this->*fun)(content_len); }catch (exception &ex){ shutdown(SockException(Err_shutdown,ex.what())); } - //清空解析器节省内存 - _parser.Clear(); - //返回content长度 - return content_len; + //清空解析器节省内存 + _parser.Clear(); + //返回content长度 + return content_len; } void HttpSession::onRecvContent(const char *data,uint64_t len) { - if(_contentCallBack){ - if(!_contentCallBack(data,len)){ - _contentCallBack = nullptr; - } - } + if(_contentCallBack){ + if(!_contentCallBack(data,len)){ + _contentCallBack = nullptr; + } + } } void HttpSession::onRecv(const Buffer::Ptr &pBuf) { @@ -140,25 +140,25 @@ void HttpSession::onManager() { GET_CONFIG(uint32_t,keepAliveSec,Http::kKeepAliveSecond); if(_ticker.elapsedTime() > keepAliveSec * 1000){ - //1分钟超时 - shutdown(SockException(Err_timeout,"session timeouted")); - } + //1分钟超时 + shutdown(SockException(Err_timeout,"session timeouted")); + } } bool HttpSession::checkWebSocket(){ - auto Sec_WebSocket_Key = _parser["Sec-WebSocket-Key"]; - if(Sec_WebSocket_Key.empty()){ - return false; - } - auto Sec_WebSocket_Accept = encodeBase64(SHA1::encode_bin(Sec_WebSocket_Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); + auto Sec_WebSocket_Key = _parser["Sec-WebSocket-Key"]; + if(Sec_WebSocket_Key.empty()){ + return false; + } + auto Sec_WebSocket_Accept = encodeBase64(SHA1::encode_bin(Sec_WebSocket_Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); - KeyValue headerOut; - headerOut["Upgrade"] = "websocket"; - headerOut["Connection"] = "Upgrade"; - headerOut["Sec-WebSocket-Accept"] = Sec_WebSocket_Accept; - if(!_parser["Sec-WebSocket-Protocol"].empty()){ - headerOut["Sec-WebSocket-Protocol"] = _parser["Sec-WebSocket-Protocol"]; - } + KeyValue headerOut; + headerOut["Upgrade"] = "websocket"; + headerOut["Connection"] = "Upgrade"; + headerOut["Sec-WebSocket-Accept"] = Sec_WebSocket_Accept; + if(!_parser["Sec-WebSocket-Protocol"].empty()){ + headerOut["Sec-WebSocket-Protocol"] = _parser["Sec-WebSocket-Protocol"]; + } auto res_cb = [this,headerOut](){ _flv_over_websocket = true; @@ -177,28 +177,28 @@ bool HttpSession::checkWebSocket(){ return true; } sendResponse("101 Switching Protocols",false, nullptr,headerOut); - return true; + return true; } //http-flv 链接格式:http://vhost-url:port/app/streamid.flv?key1=value1&key2=value2 //如果url(除去?以及后面的参数)后缀是.flv,那么表明该url是一个http-flv直播。 bool HttpSession::checkLiveFlvStream(const function &cb){ - auto pos = strrchr(_parser.Url().data(),'.'); - if(!pos){ - //未找到".flv"后缀 - return false; - } - if(strcasecmp(pos,".flv") != 0){ - //未找到".flv"后缀 - return false; - } - - //这是个.flv的流 - _mediaInfo.parse(string(RTMP_SCHEMA) + "://" + _parser["Host"] + _parser.FullUrl()); - if(_mediaInfo._app.empty() || _mediaInfo._streamid.size() < 5){ - //url不合法 + auto pos = strrchr(_parser.Url().data(),'.'); + if(!pos){ + //未找到".flv"后缀 return false; - } + } + if(strcasecmp(pos,".flv") != 0){ + //未找到".flv"后缀 + return false; + } + + //这是个.flv的流 + _mediaInfo.parse(string(RTMP_SCHEMA) + "://" + _parser["Host"] + _parser.FullUrl()); + if(_mediaInfo._app.empty() || _mediaInfo._streamid.size() < 5){ + //url不合法 + return false; + } _mediaInfo._streamid.erase(_mediaInfo._streamid.size() - 4);//去除.flv后缀 bool bClose = !strcasecmp(_parser["Connection"].data(),"close"); @@ -270,21 +270,21 @@ void HttpSession::Handle_Req_GET(int64_t &content_len) { } void HttpSession::Handle_Req_GET_l(int64_t &content_len, bool sendBody) { - //先看看是否为WebSocket请求 - if(checkWebSocket()){ - content_len = -1; - _contentCallBack = [this](const char *data,uint64_t len){ + //先看看是否为WebSocket请求 + if(checkWebSocket()){ + content_len = -1; + _contentCallBack = [this](const char *data,uint64_t len){ WebSocketSplitter::decode((uint8_t *)data,len); - //_contentCallBack是可持续的,后面还要处理后续数据 - return true; - }; - return; - } + //_contentCallBack是可持续的,后面还要处理后续数据 + return true; + }; + return; + } - if(emitHttpEvent(false)){ + if(emitHttpEvent(false)){ //拦截http api事件 - return; - } + return; + } if(checkLiveFlvStream()){ //拦截http-flv播放器 @@ -498,111 +498,111 @@ void HttpSession::sendResponse(const char *pcStatus, } string HttpSession::urlDecode(const string &str){ - auto ret = strCoding::UrlDecode(str); + auto ret = strCoding::UrlDecode(str); #ifdef _WIN32 GET_CONFIG(string,charSet,Http::kCharSet); - bool isGb2312 = !strcasecmp(charSet.data(), "gb2312"); - if (isGb2312) { - ret = strCoding::UTF8ToGB2312(ret); - } + bool isGb2312 = !strcasecmp(charSet.data(), "gb2312"); + if (isGb2312) { + ret = strCoding::UTF8ToGB2312(ret); + } #endif // _WIN32 return ret; } void HttpSession::urlDecode(Parser &parser){ - parser.setUrl(urlDecode(parser.Url())); - for(auto &pr : _parser.getUrlArgs()){ - const_cast(pr.second) = urlDecode(pr.second); - } + parser.setUrl(urlDecode(parser.Url())); + for(auto &pr : _parser.getUrlArgs()){ + const_cast(pr.second) = urlDecode(pr.second); + } } bool HttpSession::emitHttpEvent(bool doInvoke){ bool bClose = !strcasecmp(_parser["Connection"].data(),"close"); - /////////////////////异步回复Invoker/////////////////////////////// - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - HttpResponseInvoker invoker = [weakSelf,bClose](const string &codeOut, const KeyValue &headerOut, const HttpBody::Ptr &body){ - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } - strongSelf->async([weakSelf,bClose,codeOut,headerOut,body]() { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { + /////////////////////异步回复Invoker/////////////////////////////// + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + HttpResponseInvoker invoker = [weakSelf,bClose](const string &codeOut, const KeyValue &headerOut, const HttpBody::Ptr &body){ + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } + strongSelf->async([weakSelf,bClose,codeOut,headerOut,body]() { + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { //本对象已经销毁 - return; - } + return; + } strongSelf->sendResponse(codeOut.data(), bClose, nullptr, headerOut, body); - }); - }; - ///////////////////广播HTTP事件/////////////////////////// - bool consumed = false;//该事件是否被消费 - NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpRequest,_parser,invoker,consumed,*this); - if(!consumed && doInvoke){ - //该事件无人消费,所以返回404 - invoker("404 Not Found",KeyValue(), HttpBody::Ptr()); - } - return consumed; + }); + }; + ///////////////////广播HTTP事件/////////////////////////// + bool consumed = false;//该事件是否被消费 + NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastHttpRequest,_parser,invoker,consumed,*this); + if(!consumed && doInvoke){ + //该事件无人消费,所以返回404 + invoker("404 Not Found",KeyValue(), HttpBody::Ptr()); + } + return consumed; } void HttpSession::Handle_Req_POST(int64_t &content_len) { - GET_CONFIG(uint64_t,maxReqSize,Http::kMaxReqSize); + GET_CONFIG(uint64_t,maxReqSize,Http::kMaxReqSize); int64_t totalContentLen = _parser["Content-Length"].empty() ? -1 : atoll(_parser["Content-Length"].data()); - if(totalContentLen == 0){ - //content为空 - //emitHttpEvent内部会选择是否关闭连接 - emitHttpEvent(true); - return; - } + if(totalContentLen == 0){ + //content为空 + //emitHttpEvent内部会选择是否关闭连接 + emitHttpEvent(true); + return; + } //根据Content-Length设置接收缓存大小 if(totalContentLen > 0){ _sock->setReadBuffer(std::make_shared(MIN(totalContentLen + 1,256 * 1024))); }else{ - //不定长度的Content-Length + //不定长度的Content-Length _sock->setReadBuffer(std::make_shared(256 * 1024)); - } + } if(totalContentLen > 0 && totalContentLen < maxReqSize ){ - //返回固定长度的content - content_len = totalContentLen; - auto parserCopy = _parser; - _contentCallBack = [this,parserCopy](const char *data,uint64_t len){ - //恢复http头 - _parser = parserCopy; - //设置content - _parser.setContent(string(data,len)); - //触发http事件,emitHttpEvent内部会选择是否关闭连接 - emitHttpEvent(true); - //清空数据,节省内存 - _parser.Clear(); - //content已经接收完毕 - return false; - }; - }else{ - //返回不固定长度的content - content_len = -1; - auto parserCopy = _parser; - std::shared_ptr recvedContentLen = std::make_shared(0); - bool bClose = !strcasecmp(_parser["Connection"].data(),"close"); + //返回固定长度的content + content_len = totalContentLen; + auto parserCopy = _parser; + _contentCallBack = [this,parserCopy](const char *data,uint64_t len){ + //恢复http头 + _parser = parserCopy; + //设置content + _parser.setContent(string(data,len)); + //触发http事件,emitHttpEvent内部会选择是否关闭连接 + emitHttpEvent(true); + //清空数据,节省内存 + _parser.Clear(); + //content已经接收完毕 + return false; + }; + }else{ + //返回不固定长度的content + content_len = -1; + auto parserCopy = _parser; + std::shared_ptr recvedContentLen = std::make_shared(0); + bool bClose = !strcasecmp(_parser["Connection"].data(),"close"); - _contentCallBack = [this,parserCopy,totalContentLen,recvedContentLen,bClose](const char *data,uint64_t len){ - *(recvedContentLen) += len; + _contentCallBack = [this,parserCopy,totalContentLen,recvedContentLen,bClose](const char *data,uint64_t len){ + *(recvedContentLen) += len; - onRecvUnlimitedContent(parserCopy,data,len,totalContentLen,*(recvedContentLen)); + onRecvUnlimitedContent(parserCopy,data,len,totalContentLen,*(recvedContentLen)); - if(*(recvedContentLen) < totalContentLen){ - //数据还没接收完毕 + if(*(recvedContentLen) < totalContentLen){ + //数据还没接收完毕 //_contentCallBack是可持续的,后面还要处理后续content数据 return true; - } + } - //数据接收完毕 + //数据接收完毕 if(!bClose){ - //keep-alive类型连接 - //content接收完毕,后续都是http header - setContentLen(0); + //keep-alive类型连接 + //content接收完毕,后续都是http header + setContentLen(0); //content已经接收完毕 return false; } @@ -611,9 +611,9 @@ void HttpSession::Handle_Req_POST(int64_t &content_len) { shutdown(SockException(Err_shutdown,"recv http content completed")); //content已经接收完毕 return false ; - }; - } - //有后续content数据要处理,暂时不关闭连接 + }; + } + //有后续content数据要处理,暂时不关闭连接 } void HttpSession::sendNotFound(bool bClose) { @@ -632,7 +632,7 @@ void HttpSession::setSocketFlags(){ } void HttpSession::onWrite(const Buffer::Ptr &buffer) { - _ticker.resetTime(); + _ticker.resetTime(); if(!_flv_over_websocket){ _ui64TotalBytes += buffer->size(); send(buffer); @@ -653,11 +653,11 @@ void HttpSession::onWebSocketEncodeData(const Buffer::Ptr &buffer){ } void HttpSession::onDetach() { - shutdown(SockException(Err_shutdown,"rtmp ring buffer detached")); + shutdown(SockException(Err_shutdown,"rtmp ring buffer detached")); } std::shared_ptr HttpSession::getSharedPtr(){ - return dynamic_pointer_cast(shared_from_this()); + return dynamic_pointer_cast(shared_from_this()); } } /* namespace mediakit */ diff --git a/src/Http/HttpSession.h b/src/Http/HttpSession.h index 072681d3..8c74abbd 100644 --- a/src/Http/HttpSession.h +++ b/src/Http/HttpSession.h @@ -45,51 +45,51 @@ class HttpSession: public TcpSession, public HttpRequestSplitter, public WebSocketSplitter { public: - typedef StrCaseMap KeyValue; - typedef HttpResponseInvokerImp HttpResponseInvoker; - friend class AsyncSender; - /** - * @param errMsg 如果为空,则代表鉴权通过,否则为错误提示 - * @param accessPath 运行或禁止访问的根目录 - * @param cookieLifeSecond 鉴权cookie有效期 - **/ - typedef std::function HttpAccessPathInvoker; + typedef StrCaseMap KeyValue; + typedef HttpResponseInvokerImp HttpResponseInvoker; + friend class AsyncSender; + /** + * @param errMsg 如果为空,则代表鉴权通过,否则为错误提示 + * @param accessPath 运行或禁止访问的根目录 + * @param cookieLifeSecond 鉴权cookie有效期 + **/ + typedef std::function HttpAccessPathInvoker; - HttpSession(const Socket::Ptr &pSock); - virtual ~HttpSession(); + HttpSession(const Socket::Ptr &pSock); + virtual ~HttpSession(); - virtual void onRecv(const Buffer::Ptr &) override; - virtual void onError(const SockException &err) override; - virtual void onManager() override; - static string urlDecode(const string &str); + virtual void onRecv(const Buffer::Ptr &) override; + virtual void onError(const SockException &err) override; + virtual void onManager() override; + static string urlDecode(const string &str); protected: - //FlvMuxer override - void onWrite(const Buffer::Ptr &data) override ; - void onDetach() override; - std::shared_ptr getSharedPtr() override; + //FlvMuxer override + void onWrite(const Buffer::Ptr &data) override ; + void onDetach() override; + std::shared_ptr getSharedPtr() override; - //HttpRequestSplitter override - int64_t onRecvHeader(const char *data,uint64_t len) override; - void onRecvContent(const char *data,uint64_t len) override; + //HttpRequestSplitter override + int64_t onRecvHeader(const char *data,uint64_t len) override; + void onRecvContent(const char *data,uint64_t len) override; - /** - * 重载之用于处理不定长度的content - * 这个函数可用于处理大文件上传、http-flv推流 - * @param header http请求头 - * @param data content分片数据 - * @param len content分片数据大小 - * @param totalSize content总大小,如果为0则是不限长度content - * @param recvedSize 已收数据大小 - */ - virtual void onRecvUnlimitedContent(const Parser &header, - const char *data, - uint64_t len, - uint64_t totalSize, - uint64_t recvedSize){ + /** + * 重载之用于处理不定长度的content + * 这个函数可用于处理大文件上传、http-flv推流 + * @param header http请求头 + * @param data content分片数据 + * @param len content分片数据大小 + * @param totalSize content总大小,如果为0则是不限长度content + * @param recvedSize 已收数据大小 + */ + virtual void onRecvUnlimitedContent(const Parser &header, + const char *data, + uint64_t len, + uint64_t totalSize, + uint64_t recvedSize){ shutdown(SockException(Err_shutdown,"http post content is too huge,default closed")); - } + } - /** + /** * websocket客户端连接上事件 * @param header http头 * @return true代表允许websocket连接,否则拒绝 @@ -99,31 +99,31 @@ protected: return false; } - //WebSocketSplitter override - /** + //WebSocketSplitter override + /** * 发送数据进行websocket协议打包后回调 * @param buffer websocket协议数据 */ - void onWebSocketEncodeData(const Buffer::Ptr &buffer) override; + void onWebSocketEncodeData(const Buffer::Ptr &buffer) override; 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_POST(int64_t &content_len); void Handle_Req_HEAD(int64_t &content_len); bool checkLiveFlvStream(const function &cb = nullptr); - bool checkWebSocket(); - bool emitHttpEvent(bool doInvoke); - void urlDecode(Parser &parser); - void sendNotFound(bool bClose); - void sendResponse(const char *pcStatus, bool bClose, const char *pcContentType = nullptr, - const HttpSession::KeyValue &header = HttpSession::KeyValue(), + bool checkWebSocket(); + bool emitHttpEvent(bool doInvoke); + void urlDecode(Parser &parser); + void sendNotFound(bool bClose); + void sendResponse(const char *pcStatus, bool bClose, const char *pcContentType = nullptr, + const HttpSession::KeyValue &header = HttpSession::KeyValue(), const HttpBody::Ptr &body = nullptr,bool is_http_flv = false); - //设置socket标志 - void setSocketFlags(); + //设置socket标志 + void setSocketFlags(); private: - string _origin; + string _origin; Parser _parser; Ticker _ticker; //消耗的总流量 @@ -132,8 +132,8 @@ private: MediaInfo _mediaInfo; //处理content数据的callback function _contentCallBack; - bool _flv_over_websocket = false; - bool _is_flv_stream = false; + bool _flv_over_websocket = false; + bool _is_flv_stream = false; }; diff --git a/src/Http/strCoding.cpp b/src/Http/strCoding.cpp index 2a01f73e..c49153b6 100644 --- a/src/Http/strCoding.cpp +++ b/src/Http/strCoding.cpp @@ -36,76 +36,76 @@ namespace mediakit { //////////////////////////通用/////////////////////// void UTF8ToUnicode(wchar_t* pOut, const char *pText) { - char* uchar = (char *)pOut; - uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F); - uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F); - return; + char* uchar = (char *)pOut; + uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F); + uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F); + return; } void UnicodeToUTF8(char* pOut, const wchar_t* pText) { - // 注意 WCHAR高低字的顺序,低字节在前,高字节在后 - const char* pchar = (const char *)pText; - pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4)); - pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6); - pOut[2] = (0x80 | (pchar[0] & 0x3F)); - return; + // 注意 WCHAR高低字的顺序,低字节在前,高字节在后 + const char* pchar = (const char *)pText; + pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4)); + pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6); + pOut[2] = (0x80 | (pchar[0] & 0x3F)); + return; } char CharToInt(char ch) { - 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); - return -1; + 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); + return -1; } char StrToBin(const char *str) { - char tempWord[2]; - char chn; - tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011 - tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000 - chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000 - return chn; + char tempWord[2]; + char chn; + tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011 + tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000 + chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000 + return chn; } string strCoding::UrlEncode(const string &str) { - string out; + string out; 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]; - if (isalnum((uint8_t)ch)) { + if (isalnum((uint8_t)ch)) { out.push_back(ch); - }else { - char buf[4]; - sprintf(buf, "%%%X%X", (uint8_t)ch >> 4,(uint8_t)ch & 0x0F); + }else { + char buf[4]; + sprintf(buf, "%%%X%X", (uint8_t)ch >> 4,(uint8_t)ch & 0x0F); out.append(buf); - } - } - return out; + } + } + return out; } string strCoding::UrlDecode(const string &str) { - string output = ""; - char tmp[2]; - int i = 0, len = str.length(); - while (i < len) { - if (str[i] == '%') { - if(i > len - 3){ - //防止内存溢出 + string output = ""; + char tmp[2]; + int i = 0, len = str.length(); + while (i < len) { + if (str[i] == '%') { + if(i > len - 3){ + //防止内存溢出 break; - } - tmp[0] = str[i + 1]; - tmp[1] = str[i + 2]; - output += StrToBin(tmp); - i = i + 3; - } else if (str[i] == '+') { - output += ' '; - i++; - } else { - output += str[i]; - i++; - } - } - return output; + } + tmp[0] = str[i + 1]; + tmp[1] = str[i + 2]; + output += StrToBin(tmp); + i = i + 3; + } else if (str[i] == '+') { + output += ' '; + i++; + } else { + output += str[i]; + i++; + } + } + return output; } @@ -113,73 +113,73 @@ string strCoding::UrlDecode(const string &str) { #if defined(_WIN32) 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) { - MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbBuffer, 2, pOut, 1); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, gbBuffer, 2, pOut, 1); } string strCoding::UTF8ToGB2312(const string &str) { - auto len = str.size(); - auto pText = str.data(); - char Ctemp[4] = {0}; - char *pOut = new char[len + 1]; - memset(pOut, 0, len + 1); + auto len = str.size(); + auto pText = str.data(); + char Ctemp[4] = {0}; + char *pOut = new char[len + 1]; + memset(pOut, 0, len + 1); - int i = 0, j = 0; - while (i < len) - { - if (pText[i] >= 0) - { - pOut[j++] = pText[i++]; - } - else - { - wchar_t Wtemp; - UTF8ToUnicode(&Wtemp, pText + i); - UnicodeToGB2312(Ctemp, Wtemp); - pOut[j] = Ctemp[0]; - pOut[j + 1] = Ctemp[1]; - i += 3; - j += 2; - } - } - string ret = pOut; - delete[] pOut; - return ret; + int i = 0, j = 0; + while (i < len) + { + if (pText[i] >= 0) + { + pOut[j++] = pText[i++]; + } + else + { + wchar_t Wtemp; + UTF8ToUnicode(&Wtemp, pText + i); + UnicodeToGB2312(Ctemp, Wtemp); + pOut[j] = Ctemp[0]; + pOut[j + 1] = Ctemp[1]; + i += 3; + j += 2; + } + } + string ret = pOut; + delete[] pOut; + return ret; } string strCoding::GB2312ToUTF8(const string &str) { - auto len = str.size(); - auto pText = str.data(); - char buf[4] = { 0 }; - int nLength = len * 3; - char* pOut = new char[nLength]; - memset(pOut, 0, nLength); - int i = 0, j = 0; - while (i < len) - { - //如果是英文直接复制就可以 - if (*(pText + i) >= 0) - { - pOut[j++] = pText[i++]; - } - else - { - wchar_t pbuffer; - Gb2312ToUnicode(&pbuffer, pText + i); - UnicodeToUTF8(buf, &pbuffer); - pOut[j] = buf[0]; - pOut[j + 1] = buf[1]; - pOut[j + 2] = buf[2]; - j += 3; - i += 2; - } - } - string ret = pOut; - delete[] pOut; - return ret; + auto len = str.size(); + auto pText = str.data(); + char buf[4] = { 0 }; + int nLength = len * 3; + char* pOut = new char[nLength]; + memset(pOut, 0, nLength); + int i = 0, j = 0; + while (i < len) + { + //如果是英文直接复制就可以 + if (*(pText + i) >= 0) + { + pOut[j++] = pText[i++]; + } + else + { + wchar_t pbuffer; + Gb2312ToUnicode(&pbuffer, pText + i); + UnicodeToUTF8(buf, &pbuffer); + pOut[j] = buf[0]; + pOut[j + 1] = buf[1]; + pOut[j + 2] = buf[2]; + j += 3; + i += 2; + } + } + string ret = pOut; + delete[] pOut; + return ret; } #endif//defined(_WIN32) diff --git a/src/Http/strCoding.h b/src/Http/strCoding.h index 7a2f1411..4525ca1c 100644 --- a/src/Http/strCoding.h +++ b/src/Http/strCoding.h @@ -36,15 +36,15 @@ namespace mediakit { class strCoding { public: - static string UrlEncode(const string &str); //urlutf8 编码 - static string UrlDecode(const string &str); //urlutf8解码 + static string UrlEncode(const string &str); //urlutf8 编码 + static string UrlDecode(const string &str); //urlutf8解码 #if defined(_WIN32) - static string UTF8ToGB2312(const string &str);//utf_8转为gb2312 - static string GB2312ToUTF8(const string &str); //gb2312 转utf_8 + static string UTF8ToGB2312(const string &str);//utf_8转为gb2312 + static string GB2312ToUTF8(const string &str); //gb2312 转utf_8 #endif//defined(_WIN32) private: - strCoding(void); - virtual ~strCoding(void); + strCoding(void); + virtual ~strCoding(void); }; } /* namespace mediakit */ diff --git a/src/Player/MediaPlayer.cpp b/src/Player/MediaPlayer.cpp index 53365d1a..389baeba 100644 --- a/src/Player/MediaPlayer.cpp +++ b/src/Player/MediaPlayer.cpp @@ -42,29 +42,29 @@ MediaPlayer::MediaPlayer(const EventPoller::Ptr &poller) { MediaPlayer::~MediaPlayer() { } void MediaPlayer::play(const string &strUrl) { - _delegate = PlayerBase::createPlayer(_poller,strUrl); - _delegate->setOnShutdown(_shutdownCB); - _delegate->setOnPlayResult(_playResultCB); + _delegate = PlayerBase::createPlayer(_poller,strUrl); + _delegate->setOnShutdown(_shutdownCB); + _delegate->setOnPlayResult(_playResultCB); _delegate->setOnResume(_resumeCB); _delegate->setMediaSouce(_pMediaSrc); - _delegate->mINI::operator=(*this); - _delegate->play(strUrl); + _delegate->mINI::operator=(*this); + _delegate->play(strUrl); } EventPoller::Ptr MediaPlayer::getPoller(){ - return _poller; + return _poller; } void MediaPlayer::pause(bool bPause) { - if (_delegate) { - _delegate->pause(bPause); - } + if (_delegate) { + _delegate->pause(bPause); + } } void MediaPlayer::teardown() { - if (_delegate) { - _delegate->teardown(); - } + if (_delegate) { + _delegate->teardown(); + } } diff --git a/src/Player/MediaPlayer.h b/src/Player/MediaPlayer.h index c4d989b8..072639ad 100644 --- a/src/Player/MediaPlayer.h +++ b/src/Player/MediaPlayer.h @@ -39,16 +39,16 @@ namespace mediakit { class MediaPlayer : public PlayerImp { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - MediaPlayer(const EventPoller::Ptr &poller = nullptr); - virtual ~MediaPlayer(); - void play(const string &strUrl) override; - void pause(bool bPause) override; - void teardown() override; - EventPoller::Ptr getPoller(); + MediaPlayer(const EventPoller::Ptr &poller = nullptr); + virtual ~MediaPlayer(); + void play(const string &strUrl) override; + void pause(bool bPause) override; + void teardown() override; + EventPoller::Ptr getPoller(); private: - EventPoller::Ptr _poller; + EventPoller::Ptr _poller; }; } /* namespace mediakit */ diff --git a/src/Player/PlayerBase.cpp b/src/Player/PlayerBase.cpp index 5b94a976..9d1e6d7b 100644 --- a/src/Player/PlayerBase.cpp +++ b/src/Player/PlayerBase.cpp @@ -33,92 +33,92 @@ using namespace toolkit; namespace mediakit { PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const string &strUrl) { - static auto releasePlayer = [](PlayerBase *ptr){ - onceToken token(nullptr,[&](){ - delete ptr; - }); - ptr->teardown(); - }; - string prefix = FindField(strUrl.data(), NULL, "://"); + static auto releasePlayer = [](PlayerBase *ptr){ + onceToken token(nullptr,[&](){ + delete ptr; + }); + ptr->teardown(); + }; + string prefix = FindField(strUrl.data(), NULL, "://"); - if (strcasecmp("rtsps",prefix.data()) == 0) { - return PlayerBase::Ptr(new TcpClientWithSSL(poller),releasePlayer); - } + if (strcasecmp("rtsps",prefix.data()) == 0) { + return PlayerBase::Ptr(new TcpClientWithSSL(poller),releasePlayer); + } - if (strcasecmp("rtsp",prefix.data()) == 0) { - return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); - } + if (strcasecmp("rtsp",prefix.data()) == 0) { + return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); + } - if (strcasecmp("rtmps",prefix.data()) == 0) { - return PlayerBase::Ptr(new TcpClientWithSSL(poller),releasePlayer); - } + if (strcasecmp("rtmps",prefix.data()) == 0) { + return PlayerBase::Ptr(new TcpClientWithSSL(poller),releasePlayer); + } - if (strcasecmp("rtmp",prefix.data()) == 0) { - return PlayerBase::Ptr(new RtmpPlayerImp(poller),releasePlayer); - } + if (strcasecmp("rtmp",prefix.data()) == 0) { + return PlayerBase::Ptr(new RtmpPlayerImp(poller),releasePlayer); + } - return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); + return PlayerBase::Ptr(new RtspPlayerImp(poller),releasePlayer); } PlayerBase::PlayerBase() { - this->mINI::operator[](kTimeoutMS) = 10000; - this->mINI::operator[](kMediaTimeoutMS) = 5000; - this->mINI::operator[](kBeatIntervalMS) = 5000; - this->mINI::operator[](kMaxAnalysisMS) = 5000; + this->mINI::operator[](kTimeoutMS) = 10000; + this->mINI::operator[](kMediaTimeoutMS) = 5000; + this->mINI::operator[](kBeatIntervalMS) = 5000; + this->mINI::operator[](kMaxAnalysisMS) = 5000; } ///////////////////////////Demuxer////////////////////////////// bool Demuxer::isInited(int analysisMs) { - if(analysisMs && _ticker.createdTime() > analysisMs){ - //analysisMs毫秒后强制初始化完毕 - return true; - } - if (_videoTrack && !_videoTrack->ready()) { - //视频未准备好 - return false; - } - if (_audioTrack && !_audioTrack->ready()) { - //音频未准备好 - return false; - } - return true; + if(analysisMs && _ticker.createdTime() > analysisMs){ + //analysisMs毫秒后强制初始化完毕 + return true; + } + if (_videoTrack && !_videoTrack->ready()) { + //视频未准备好 + return false; + } + if (_audioTrack && !_audioTrack->ready()) { + //音频未准备好 + return false; + } + return true; } vector Demuxer::getTracks(bool trackReady) const { - vector ret; - if(_videoTrack){ - if(trackReady){ - if(_videoTrack->ready()){ - ret.emplace_back(_videoTrack); - } - }else{ - ret.emplace_back(_videoTrack); - } - } - if(_audioTrack){ - if(trackReady){ - if(_audioTrack->ready()){ - ret.emplace_back(_audioTrack); - } - }else{ - ret.emplace_back(_audioTrack); - } - } - return std::move(ret); + vector ret; + if(_videoTrack){ + if(trackReady){ + if(_videoTrack->ready()){ + ret.emplace_back(_videoTrack); + } + }else{ + ret.emplace_back(_videoTrack); + } + } + if(_audioTrack){ + if(trackReady){ + if(_audioTrack->ready()){ + ret.emplace_back(_audioTrack); + } + }else{ + ret.emplace_back(_audioTrack); + } + } + return std::move(ret); } float Demuxer::getDuration() const { - return _fDuration; + return _fDuration; } void Demuxer::onAddTrack(const Track::Ptr &track){ - if(_listener){ - _listener->onAddTrack(track); - } + if(_listener){ + _listener->onAddTrack(track); + } } void Demuxer::setTrackListener(Demuxer::Listener *listener) { - _listener = listener; + _listener = listener; } } /* namespace mediakit */ diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index 8fb397b3..3c810e99 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -43,59 +43,59 @@ namespace mediakit { class DemuxerBase : public TrackSource{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - /** - * 获取节目总时长,单位秒 - * @return - */ - virtual float getDuration() const { return 0;} + /** + * 获取节目总时长,单位秒 + * @return + */ + virtual float getDuration() const { return 0;} - /** - * 是否初始化完毕,完毕后方可调用getTrack方法 - * @param analysisMs 数据流最大分析时间 单位毫秒 - * @return - */ - virtual bool isInited(int analysisMs) { return true; } + /** + * 是否初始化完毕,完毕后方可调用getTrack方法 + * @param analysisMs 数据流最大分析时间 单位毫秒 + * @return + */ + virtual bool isInited(int analysisMs) { return true; } }; class PlayerBase : public DemuxerBase, public mINI{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; static Ptr createPlayer(const EventPoller::Ptr &poller,const string &strUrl); - PlayerBase(); - virtual ~PlayerBase(){} + PlayerBase(); + virtual ~PlayerBase(){} - /** - * 开始播放 - * @param strUrl 视频url,支持rtsp/rtmp - */ - virtual void play(const string &strUrl) {} + /** + * 开始播放 + * @param strUrl 视频url,支持rtsp/rtmp + */ + virtual void play(const string &strUrl) {} - /** - * 暂停或恢复 - * @param bPause - */ - virtual void pause(bool bPause) {} + /** + * 暂停或恢复 + * @param bPause + */ + virtual void pause(bool bPause) {} - /** - * 中断播放 - */ - virtual void teardown() {} + /** + * 中断播放 + */ + virtual void teardown() {} - /** - * 设置异常中断回调 - * @param cb - */ - virtual void setOnShutdown( const function &cb) {} + /** + * 设置异常中断回调 + * @param cb + */ + virtual void setOnShutdown( const function &cb) {} - /** - * 设置播放结果回调 - * @param cb - */ - virtual void setOnPlayResult( const function &cb) {} + /** + * 设置播放结果回调 + * @param cb + */ + virtual void setOnPlayResult( const function &cb) {} /** * 设置播放恢复回调 @@ -103,10 +103,10 @@ public: */ virtual void setOnResume( const function &cb) {} - /** - * 获取播放进度,取值 0.0 ~ 1.0 - * @return - */ + /** + * 获取播放进度,取值 0.0 ~ 1.0 + * @return + */ virtual float getProgress() const { return 0;} /** @@ -126,7 +126,7 @@ public: * @param trackType 音频或视频,TrackInvalid时为总丢包率 * @return */ - virtual float getPacketLossRate(TrackType trackType) const {return 0; } + virtual float getPacketLossRate(TrackType trackType) const {return 0; } /** * 获取所有track @@ -146,24 +146,24 @@ protected: template class PlayerImp : public Parent { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - template - PlayerImp(ArgsType &&...args):Parent(std::forward(args)...){} + template + PlayerImp(ArgsType &&...args):Parent(std::forward(args)...){} - virtual ~PlayerImp(){} - void setOnShutdown(const function &cb) override { - if (_delegate) { - _delegate->setOnShutdown(cb); - } - _shutdownCB = cb; - } - void setOnPlayResult(const function &cb) override { - if (_delegate) { - _delegate->setOnPlayResult(cb); - } - _playResultCB = cb; - } + virtual ~PlayerImp(){} + void setOnShutdown(const function &cb) override { + if (_delegate) { + _delegate->setOnShutdown(cb); + } + _shutdownCB = cb; + } + void setOnPlayResult(const function &cb) override { + if (_delegate) { + _delegate->setOnPlayResult(cb); + } + _playResultCB = cb; + } void setOnResume(const function &cb) override { if (_delegate) { @@ -178,12 +178,12 @@ public: } return Parent::isInited(analysisMs); } - float getDuration() const override { - if (_delegate) { - return _delegate->getDuration(); - } - return Parent::getDuration(); - } + float getDuration() const override { + if (_delegate) { + return _delegate->getDuration(); + } + return Parent::getDuration(); + } float getProgress() const override{ if (_delegate) { return _delegate->getProgress(); @@ -198,95 +198,95 @@ public: } void setMediaSouce(const MediaSource::Ptr & src) override { - if (_delegate) { - _delegate->setMediaSouce(src); - } - _pMediaSrc = src; + if (_delegate) { + _delegate->setMediaSouce(src); + } + _pMediaSrc = src; } vector getTracks(bool trackReady = true) const override{ - if (_delegate) { - return _delegate->getTracks(trackReady); - } - return Parent::getTracks(trackReady); - } + if (_delegate) { + return _delegate->getTracks(trackReady); + } + return Parent::getTracks(trackReady); + } protected: - void onShutdown(const SockException &ex) override { - if (_shutdownCB) { - _shutdownCB(ex); - _shutdownCB = nullptr; - } - } + void onShutdown(const SockException &ex) override { + if (_shutdownCB) { + _shutdownCB(ex); + _shutdownCB = nullptr; + } + } - void onPlayResult(const SockException &ex) override { - if(_playResultCB) { - _playResultCB(ex); - _playResultCB = nullptr; - } - } + void onPlayResult(const SockException &ex) override { + if(_playResultCB) { + _playResultCB(ex); + _playResultCB = nullptr; + } + } - void onResume() override{ + void onResume() override{ if(_resumeCB){ _resumeCB(); } } protected: - function _shutdownCB; - function _playResultCB; + function _shutdownCB; + function _playResultCB; function _resumeCB; std::shared_ptr _delegate; - MediaSource::Ptr _pMediaSrc; + MediaSource::Ptr _pMediaSrc; }; class Demuxer : public PlayerBase{ public: - class Listener{ - public: - Listener() = default; - virtual ~Listener() = default; - virtual void onAddTrack(const Track::Ptr &track) = 0; - }; + class Listener{ + public: + Listener() = default; + virtual ~Listener() = default; + virtual void onAddTrack(const Track::Ptr &track) = 0; + }; - Demuxer(){}; - virtual ~Demuxer(){}; + Demuxer(){}; + virtual ~Demuxer(){}; - /** - * 返回是否完成初始化完毕 - * 在构造RtspDemuxer对象时有些rtsp的sdp不包含sps pps信息 - * 所以要等待接收到到sps的rtp包后才能完成 - * - * 在构造RtmpDemuxer对象时是无法获取sps pps aac_cfg等这些信息, - * 所以要调用inputRtmp后才会获取到这些信息,这时才初始化成功 - * @param analysisMs 数据流最大分析时间 单位毫秒 - * @return - */ - bool isInited(int analysisMs) override; + /** + * 返回是否完成初始化完毕 + * 在构造RtspDemuxer对象时有些rtsp的sdp不包含sps pps信息 + * 所以要等待接收到到sps的rtp包后才能完成 + * + * 在构造RtmpDemuxer对象时是无法获取sps pps aac_cfg等这些信息, + * 所以要调用inputRtmp后才会获取到这些信息,这时才初始化成功 + * @param analysisMs 数据流最大分析时间 单位毫秒 + * @return + */ + bool isInited(int analysisMs) override; - /** - * 获取所有Track - * @return 所有Track - */ - vector getTracks(bool trackReady = true) const override; + /** + * 获取所有Track + * @return 所有Track + */ + vector getTracks(bool trackReady = true) const override; - /** - * 获取节目总时长 - * @return 节目总时长,单位秒 - */ - float getDuration() const override; + /** + * 获取节目总时长 + * @return 节目总时长,单位秒 + */ + float getDuration() const override; - /** - * 设置track监听器 - */ - void setTrackListener(Listener *listener); + /** + * 设置track监听器 + */ + void setTrackListener(Listener *listener); protected: - void onAddTrack(const Track::Ptr &track); + void onAddTrack(const Track::Ptr &track); protected: - Listener *_listener = nullptr; - AudioTrack::Ptr _audioTrack; - VideoTrack::Ptr _videoTrack; - Ticker _ticker; - float _fDuration = 0; + Listener *_listener = nullptr; + AudioTrack::Ptr _audioTrack; + VideoTrack::Ptr _videoTrack; + Ticker _ticker; + float _fDuration = 0; }; } /* namespace mediakit */ diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 1ba1d1b7..6547be7c 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -65,17 +65,17 @@ static uint8_t s_mute_adts[] = {0xff, 0xf1, 0x6c, 0x40, 0x2d, 0x3f, 0xfc, 0x00, PlayerProxy::PlayerProxy(const string &strVhost, const string &strApp, const string &strSrc, - bool bEnableRtsp, - bool bEnableRtmp, + bool bEnableRtsp, + bool bEnableRtmp, bool bEnableHls, bool bEnableMp4, int iRetryCount, - const EventPoller::Ptr &poller) : MediaPlayer(poller){ - _strVhost = strVhost; - _strApp = strApp; - _strSrc = strSrc; - _bEnableRtsp = bEnableRtsp; - _bEnableRtmp = bEnableRtmp; + const EventPoller::Ptr &poller) : MediaPlayer(poller){ + _strVhost = strVhost; + _strApp = strApp; + _strSrc = strSrc; + _bEnableRtsp = bEnableRtsp; + _bEnableRtmp = bEnableRtmp; _bEnableHls = bEnableHls; _bEnableMp4 = bEnableMp4; _iRetryCount = iRetryCount; @@ -90,88 +90,88 @@ void PlayerProxy::setOnClose(const function &cb){ } void PlayerProxy::play(const string &strUrlTmp) { - weak_ptr weakSelf = shared_from_this(); - std::shared_ptr piFailedCnt(new int(0)); //连续播放失败次数 - setOnPlayResult([weakSelf,strUrlTmp,piFailedCnt](const SockException &err) { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } + weak_ptr weakSelf = shared_from_this(); + std::shared_ptr piFailedCnt(new int(0)); //连续播放失败次数 + setOnPlayResult([weakSelf,strUrlTmp,piFailedCnt](const SockException &err) { + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } - if(strongSelf->_playCB) { + if(strongSelf->_playCB) { strongSelf->_playCB(err); strongSelf->_playCB = nullptr; } - if(!err) { - // 播放成功 - *piFailedCnt = 0;//连续播放失败次数清0 - strongSelf->onPlaySuccess(); - }else if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) { - // 播放失败,延时重试播放 - strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++); - } - }); - setOnShutdown([weakSelf,strUrlTmp,piFailedCnt](const SockException &err) { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } - if(strongSelf->_mediaMuxer) { - auto tracks = strongSelf->getTracks(false); - for (auto & track : tracks){ - track->delDelegate(strongSelf->_mediaMuxer.get()); - } + if(!err) { + // 播放成功 + *piFailedCnt = 0;//连续播放失败次数清0 + strongSelf->onPlaySuccess(); + }else if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) { + // 播放失败,延时重试播放 + strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++); + } + }); + setOnShutdown([weakSelf,strUrlTmp,piFailedCnt](const SockException &err) { + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } + if(strongSelf->_mediaMuxer) { + auto tracks = strongSelf->getTracks(false); + for (auto & track : tracks){ + track->delDelegate(strongSelf->_mediaMuxer.get()); + } - GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay); - if (resetWhenRePlay) { - strongSelf->_mediaMuxer.reset(); - } else { - strongSelf->_mediaMuxer->resetTracks(); - } - } - //播放异常中断,延时重试播放 - if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) { - strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++); - } - }); - MediaPlayer::play(strUrlTmp); + GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay); + if (resetWhenRePlay) { + strongSelf->_mediaMuxer.reset(); + } else { + strongSelf->_mediaMuxer->resetTracks(); + } + } + //播放异常中断,延时重试播放 + if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) { + strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++); + } + }); + MediaPlayer::play(strUrlTmp); - MediaSource::Ptr mediaSource; - if(dynamic_pointer_cast(_delegate)){ - //rtsp拉流 - GET_CONFIG(bool,directProxy,Rtsp::kDirectProxy); - if(directProxy && _bEnableRtsp){ - mediaSource = std::make_shared(_strVhost,_strApp,_strSrc); - } - } else if(dynamic_pointer_cast(_delegate)){ - //rtmp拉流 - if(_bEnableRtmp){ - mediaSource = std::make_shared(_strVhost,_strApp,_strSrc); - } - } - if(mediaSource){ - setMediaSouce(mediaSource); - mediaSource->setListener(shared_from_this()); - } + MediaSource::Ptr mediaSource; + if(dynamic_pointer_cast(_delegate)){ + //rtsp拉流 + GET_CONFIG(bool,directProxy,Rtsp::kDirectProxy); + if(directProxy && _bEnableRtsp){ + mediaSource = std::make_shared(_strVhost,_strApp,_strSrc); + } + } else if(dynamic_pointer_cast(_delegate)){ + //rtmp拉流 + if(_bEnableRtmp){ + mediaSource = std::make_shared(_strVhost,_strApp,_strSrc); + } + } + if(mediaSource){ + setMediaSouce(mediaSource); + mediaSource->setListener(shared_from_this()); + } } PlayerProxy::~PlayerProxy() { - _timer.reset(); + _timer.reset(); } void PlayerProxy::rePlay(const string &strUrl,int iFailedCnt){ - auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000, 60*1000)); - weak_ptr weakSelf = shared_from_this(); - _timer = std::make_shared(iDelay / 1000.0f,[weakSelf,strUrl,iFailedCnt]() { - //播放失败次数越多,则延时越长 - auto strongPlayer = weakSelf.lock(); - if(!strongPlayer) { - return false; - } - WarnL << "重试播放[" << iFailedCnt << "]:" << strUrl; - strongPlayer->MediaPlayer::play(strUrl); - return false; - }, getPoller()); + auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000, 60*1000)); + weak_ptr weakSelf = shared_from_this(); + _timer = std::make_shared(iDelay / 1000.0f,[weakSelf,strUrl,iFailedCnt]() { + //播放失败次数越多,则延时越长 + auto strongPlayer = weakSelf.lock(); + if(!strongPlayer) { + return false; + } + WarnL << "重试播放[" << iFailedCnt << "]:" << strUrl; + strongPlayer->MediaPlayer::play(strUrl); + return false; + }, getPoller()); } bool PlayerProxy::close(MediaSource &sender,bool force) { @@ -179,19 +179,19 @@ bool PlayerProxy::close(MediaSource &sender,bool force) { return false; } - //通知其停止推流 - weak_ptr weakSlef = dynamic_pointer_cast(shared_from_this()); - getPoller()->async_first([weakSlef]() { - auto stronSelf = weakSlef.lock(); - if (stronSelf) { - stronSelf->_mediaMuxer.reset(); - stronSelf->setMediaSouce(nullptr); - stronSelf->teardown(); - if(stronSelf->_onClose){ + //通知其停止推流 + weak_ptr weakSlef = dynamic_pointer_cast(shared_from_this()); + getPoller()->async_first([weakSlef]() { + auto stronSelf = weakSlef.lock(); + if (stronSelf) { + stronSelf->_mediaMuxer.reset(); + stronSelf->setMediaSouce(nullptr); + stronSelf->teardown(); + if(stronSelf->_onClose){ stronSelf->_onClose(); - } - } - }); + } + } + }); WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force; return true; } @@ -208,90 +208,90 @@ int PlayerProxy::totalReaderCount(){ } int PlayerProxy::totalReaderCount(MediaSource &sender) { - return totalReaderCount(); + return totalReaderCount(); } class MuteAudioMaker : public FrameDispatcher{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - MuteAudioMaker(){}; - virtual ~MuteAudioMaker(){} - void inputFrame(const Frame::Ptr &frame) override { - if(frame->getTrackType() == TrackVideo){ - auto iAudioIndex = frame->dts() / MUTE_ADTS_DATA_MS; - if(_iAudioIndex != iAudioIndex){ - _iAudioIndex = iAudioIndex; - auto aacFrame = std::make_shared((char *)MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN, _iAudioIndex * MUTE_ADTS_DATA_MS); - FrameDispatcher::inputFrame(aacFrame); - } - } - } + MuteAudioMaker(){}; + virtual ~MuteAudioMaker(){} + void inputFrame(const Frame::Ptr &frame) override { + if(frame->getTrackType() == TrackVideo){ + auto iAudioIndex = frame->dts() / MUTE_ADTS_DATA_MS; + if(_iAudioIndex != iAudioIndex){ + _iAudioIndex = iAudioIndex; + auto aacFrame = std::make_shared((char *)MUTE_ADTS_DATA, MUTE_ADTS_DATA_LEN, _iAudioIndex * MUTE_ADTS_DATA_MS); + FrameDispatcher::inputFrame(aacFrame); + } + } + } private: - class AACFrameCacheAble : public AACFrameNoCacheAble{ - public: - template - AACFrameCacheAble(ARGS && ...args) : AACFrameNoCacheAble(std::forward(args)...){}; - virtual ~AACFrameCacheAble() = default; + class AACFrameCacheAble : public AACFrameNoCacheAble{ + public: + template + AACFrameCacheAble(ARGS && ...args) : AACFrameNoCacheAble(std::forward(args)...){}; + virtual ~AACFrameCacheAble() = default; - bool cacheAble() const override { - return true; - } - }; + bool cacheAble() const override { + return true; + } + }; private: - int _iAudioIndex = 0; + int _iAudioIndex = 0; }; void PlayerProxy::onPlaySuccess() { - GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay); - if (dynamic_pointer_cast(_pMediaSrc)) { - //rtsp拉流代理 - if (resetWhenRePlay || !_mediaMuxer) { - _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), false, _bEnableRtmp, _bEnableHls, _bEnableMp4)); - } - } else if (dynamic_pointer_cast(_pMediaSrc)) { - //rtmp拉流代理 - if (resetWhenRePlay || !_mediaMuxer) { - _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, false, _bEnableHls, _bEnableMp4)); - } - } else { - //其他拉流代理 - if (resetWhenRePlay || !_mediaMuxer) { - _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, _bEnableRtmp, _bEnableHls, _bEnableMp4)); - } - } - _mediaMuxer->setListener(shared_from_this()); + GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay); + if (dynamic_pointer_cast(_pMediaSrc)) { + //rtsp拉流代理 + if (resetWhenRePlay || !_mediaMuxer) { + _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), false, _bEnableRtmp, _bEnableHls, _bEnableMp4)); + } + } else if (dynamic_pointer_cast(_pMediaSrc)) { + //rtmp拉流代理 + if (resetWhenRePlay || !_mediaMuxer) { + _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, false, _bEnableHls, _bEnableMp4)); + } + } else { + //其他拉流代理 + if (resetWhenRePlay || !_mediaMuxer) { + _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, _bEnableRtmp, _bEnableHls, _bEnableMp4)); + } + } + _mediaMuxer->setListener(shared_from_this()); - auto videoTrack = getTrack(TrackVideo,false); - if(videoTrack){ - //添加视频 - _mediaMuxer->addTrack(videoTrack); - //视频数据写入_mediaMuxer - videoTrack->addDelegate(_mediaMuxer); - } + auto videoTrack = getTrack(TrackVideo,false); + if(videoTrack){ + //添加视频 + _mediaMuxer->addTrack(videoTrack); + //视频数据写入_mediaMuxer + videoTrack->addDelegate(_mediaMuxer); + } - //是否添加静音音频 - GET_CONFIG(bool,addMuteAudio,General::kAddMuteAudio); + //是否添加静音音频 + GET_CONFIG(bool,addMuteAudio,General::kAddMuteAudio); - auto audioTrack = getTrack(TrackAudio, false); - if(audioTrack){ - //添加音频 - _mediaMuxer->addTrack(audioTrack); - //音频数据写入_mediaMuxer + auto audioTrack = getTrack(TrackAudio, false); + if(audioTrack){ + //添加音频 + _mediaMuxer->addTrack(audioTrack); + //音频数据写入_mediaMuxer audioTrack->addDelegate(_mediaMuxer); }else if(addMuteAudio && videoTrack){ - //没有音频信息,产生一个静音音频 - MuteAudioMaker::Ptr audioMaker = std::make_shared(); - //videoTrack把数据写入MuteAudioMaker - videoTrack->addDelegate(audioMaker); - //添加一个静音Track至_mediaMuxer - _mediaMuxer->addTrack(std::make_shared()); - //MuteAudioMaker生成静音音频然后写入_mediaMuxer; - audioMaker->addDelegate(_mediaMuxer); - } + //没有音频信息,产生一个静音音频 + MuteAudioMaker::Ptr audioMaker = std::make_shared(); + //videoTrack把数据写入MuteAudioMaker + videoTrack->addDelegate(audioMaker); + //添加一个静音Track至_mediaMuxer + _mediaMuxer->addTrack(std::make_shared()); + //MuteAudioMaker生成静音音频然后写入_mediaMuxer; + audioMaker->addDelegate(_mediaMuxer); + } - //添加完毕所有track,防止单track情况下最大等待3秒 + //添加完毕所有track,防止单track情况下最大等待3秒 _mediaMuxer->addTrackCompleted(); if(_pMediaSrc){ diff --git a/src/Player/PlayerProxy.h b/src/Player/PlayerProxy.h index 7560e4c3..83bfe8e0 100644 --- a/src/Player/PlayerProxy.h +++ b/src/Player/PlayerProxy.h @@ -39,24 +39,24 @@ using namespace toolkit; namespace mediakit { class PlayerProxy :public MediaPlayer, - public std::enable_shared_from_this , - public MediaSourceEvent{ + public std::enable_shared_from_this , + public MediaSourceEvent{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; //如果iRetryCount<0,则一直重试播放;否则重试iRetryCount次数 //默认一直重试 - PlayerProxy(const string &strVhost, + PlayerProxy(const string &strVhost, const string &strApp, const string &strSrc, - bool bEnableRtsp = true, - bool bEnableRtmp = true, + bool bEnableRtsp = true, + bool bEnableRtmp = true, bool bEnableHls = true, bool bEnableMp4 = false, int iRetryCount = -1, - const EventPoller::Ptr &poller = nullptr); + const EventPoller::Ptr &poller = nullptr); - virtual ~PlayerProxy(); + virtual ~PlayerProxy(); /** * 设置play结果回调,只触发一次;在play执行之前有效 @@ -81,19 +81,19 @@ public: */ int totalReaderCount() ; private: - //MediaSourceEvent override - bool close(MediaSource &sender,bool force) override; + //MediaSourceEvent override + bool close(MediaSource &sender,bool force) override; void onNoneReader(MediaSource &sender) override; - int totalReaderCount(MediaSource &sender) override; - void rePlay(const string &strUrl,int iFailedCnt); - void onPlaySuccess(); + int totalReaderCount(MediaSource &sender) override; + void rePlay(const string &strUrl,int iFailedCnt); + void onPlaySuccess(); private: bool _bEnableRtsp; bool _bEnableRtmp; - bool _bEnableHls; - bool _bEnableMp4; + bool _bEnableHls; + bool _bEnableMp4; int _iRetryCount; - MultiMediaSourceMuxer::Ptr _mediaMuxer; + MultiMediaSourceMuxer::Ptr _mediaMuxer; string _strVhost; string _strApp; string _strSrc; diff --git a/src/Record/HlsMediaSource.h b/src/Record/HlsMediaSource.h index 38a192b7..664781b1 100644 --- a/src/Record/HlsMediaSource.h +++ b/src/Record/HlsMediaSource.h @@ -44,16 +44,16 @@ public: virtual ~HlsMediaSource() = default; /** - * 获取媒体源的环形缓冲 - */ + * 获取媒体源的环形缓冲 + */ const RingType::Ptr &getRing() const { return _ring; } /** - * 获取播放器个数 - * @return - */ + * 获取播放器个数 + * @return + */ int readerCount() override { return _readerCount.load(); } diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index a8dd967a..69ceb463 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -192,7 +192,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { 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("\x00\x00\x00\x01", 4) + h264_track->getPps(); h264_annexbtomp4(&avc, sps_pps.data(), sps_pps.size(), NULL, 0, NULL, NULL); @@ -230,7 +230,7 @@ void MP4Muxer::addTrack(const Track::Ptr &track) { 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("\x00\x00\x00\x01", 4) + h265_track->getSps() + string("\x00\x00\x00\x01", 4) + h265_track->getPps(); diff --git a/src/Record/MP4Reader.cpp b/src/Record/MP4Reader.cpp index 3fd552b4..795cbb09 100644 --- a/src/Record/MP4Reader.cpp +++ b/src/Record/MP4Reader.cpp @@ -39,118 +39,118 @@ namespace mediakit { #ifdef ENABLE_MP4V2 MP4Reader::MP4Reader(const string &strVhost,const string &strApp, const string &strId,const string &filePath ) { - _poller = WorkThreadPool::Instance().getPoller(); + _poller = WorkThreadPool::Instance().getPoller(); auto strFileName = filePath; if(strFileName.empty()){ - GET_CONFIG(string,recordPath,Record::kFilePath); + GET_CONFIG(string,recordPath,Record::kFilePath); GET_CONFIG(bool,enableVhost,General::kEnableVhost); if(enableVhost){ strFileName = strVhost + "/" + strApp + "/" + strId; }else{ strFileName = strApp + "/" + strId; } - strFileName = File::absolutePath(strFileName,recordPath); + strFileName = File::absolutePath(strFileName,recordPath); } - _hMP4File = MP4Read(strFileName.data()); - if(_hMP4File == MP4_INVALID_FILE_HANDLE){ - throw runtime_error(StrPrinter << "打开MP4文件失败:" << strFileName << endl); - } - _video_trId = MP4FindTrackId(_hMP4File, 0, MP4_VIDEO_TRACK_TYPE, 0); - if(_video_trId != MP4_INVALID_TRACK_ID){ - if(strcmp(MP4GetTrackMediaDataName(_hMP4File, _video_trId),"avc1") ==0){ - auto _video_timescale = MP4GetTrackTimeScale(_hMP4File, _video_trId); - auto _video_duration = MP4GetTrackDuration(_hMP4File, _video_trId); - _video_num_samples = MP4GetTrackNumberOfSamples(_hMP4File, _video_trId); - _video_sample_max_size = MP4GetTrackMaxSampleSize(_hMP4File, _video_trId); - _video_width = MP4GetTrackVideoWidth(_hMP4File, _video_trId); - _video_height = MP4GetTrackVideoHeight(_hMP4File, _video_trId); - _video_framerate = MP4GetTrackVideoFrameRate(_hMP4File, _video_trId); - _pcVideoSample = std::shared_ptr (new uint8_t[_video_sample_max_size],[](uint8_t *ptr){ - delete [] ptr; - }); - uint8_t **seqheader; - uint8_t **pictheader; - uint32_t *pictheadersize; - uint32_t *seqheadersize; - uint32_t ix; - if(MP4GetTrackH264SeqPictHeaders(_hMP4File, _video_trId, &seqheader, &seqheadersize, &pictheader, &pictheadersize)){ - for (ix = 0; seqheadersize[ix] != 0; ix++) { - _strSps.assign((char *)(seqheader[ix]), seqheadersize[ix]); - float framerate; - getAVCInfo(_strSps, (int &)_video_width, (int &)_video_height, framerate); - _video_framerate = framerate; - _strSps = string("\x0\x0\x0\x1",4) + _strSps; - MP4Free(seqheader[ix]); - } - MP4Free(seqheader); - MP4Free(seqheadersize); - for (ix = 0; pictheadersize[ix] != 0; ix++) { - _strPps.assign("\x0\x0\x0\x1",4); - _strPps.append((char *)(pictheader[ix]), pictheadersize[ix]); - MP4Free(pictheader[ix]); - } - MP4Free(pictheader); - MP4Free(pictheadersize); - } - _video_ms = 1000.0 * _video_duration / _video_timescale; - /*InfoL << "\r\n" - << _video_ms << "\r\n" - << _video_num_samples << "\r\n" - << _video_framerate << "\r\n" - << _video_width << "\r\n" - << _video_height << "\r\n";*/ - } else { - //如果不是h264,则忽略 - _video_trId = MP4_INVALID_TRACK_ID; - } - } + _hMP4File = MP4Read(strFileName.data()); + if(_hMP4File == MP4_INVALID_FILE_HANDLE){ + throw runtime_error(StrPrinter << "打开MP4文件失败:" << strFileName << endl); + } + _video_trId = MP4FindTrackId(_hMP4File, 0, MP4_VIDEO_TRACK_TYPE, 0); + if(_video_trId != MP4_INVALID_TRACK_ID){ + if(strcmp(MP4GetTrackMediaDataName(_hMP4File, _video_trId),"avc1") ==0){ + auto _video_timescale = MP4GetTrackTimeScale(_hMP4File, _video_trId); + auto _video_duration = MP4GetTrackDuration(_hMP4File, _video_trId); + _video_num_samples = MP4GetTrackNumberOfSamples(_hMP4File, _video_trId); + _video_sample_max_size = MP4GetTrackMaxSampleSize(_hMP4File, _video_trId); + _video_width = MP4GetTrackVideoWidth(_hMP4File, _video_trId); + _video_height = MP4GetTrackVideoHeight(_hMP4File, _video_trId); + _video_framerate = MP4GetTrackVideoFrameRate(_hMP4File, _video_trId); + _pcVideoSample = std::shared_ptr (new uint8_t[_video_sample_max_size],[](uint8_t *ptr){ + delete [] ptr; + }); + uint8_t **seqheader; + uint8_t **pictheader; + uint32_t *pictheadersize; + uint32_t *seqheadersize; + uint32_t ix; + if(MP4GetTrackH264SeqPictHeaders(_hMP4File, _video_trId, &seqheader, &seqheadersize, &pictheader, &pictheadersize)){ + for (ix = 0; seqheadersize[ix] != 0; ix++) { + _strSps.assign((char *)(seqheader[ix]), seqheadersize[ix]); + float framerate; + getAVCInfo(_strSps, (int &)_video_width, (int &)_video_height, framerate); + _video_framerate = framerate; + _strSps = string("\x0\x0\x0\x1",4) + _strSps; + MP4Free(seqheader[ix]); + } + MP4Free(seqheader); + MP4Free(seqheadersize); + for (ix = 0; pictheadersize[ix] != 0; ix++) { + _strPps.assign("\x0\x0\x0\x1",4); + _strPps.append((char *)(pictheader[ix]), pictheadersize[ix]); + MP4Free(pictheader[ix]); + } + MP4Free(pictheader); + MP4Free(pictheadersize); + } + _video_ms = 1000.0 * _video_duration / _video_timescale; + /*InfoL << "\r\n" + << _video_ms << "\r\n" + << _video_num_samples << "\r\n" + << _video_framerate << "\r\n" + << _video_width << "\r\n" + << _video_height << "\r\n";*/ + } else { + //如果不是h264,则忽略 + _video_trId = MP4_INVALID_TRACK_ID; + } + } - _audio_trId = MP4FindTrackId(_hMP4File, 0, MP4_AUDIO_TRACK_TYPE, 0); - if (_audio_trId != MP4_INVALID_TRACK_ID) { - if (strcmp(MP4GetTrackMediaDataName(_hMP4File, _audio_trId), "mp4a") == 0) { - _audio_sample_rate = MP4GetTrackTimeScale(_hMP4File, _audio_trId); - auto _audio_duration = MP4GetTrackDuration(_hMP4File, _audio_trId); - _audio_num_samples = MP4GetTrackNumberOfSamples(_hMP4File,_audio_trId); - _audio_num_channels = MP4GetTrackAudioChannels(_hMP4File, _audio_trId); - _audio_sample_max_size = MP4GetTrackMaxSampleSize(_hMP4File,_audio_trId); - uint8_t *ppConfig; - uint32_t pConfigSize; - if(MP4GetTrackESConfiguration(_hMP4File,_audio_trId,&ppConfig,&pConfigSize)){ - _strAacCfg.assign((char *)ppConfig, pConfigSize); - makeAdtsHeader(_strAacCfg, _adts); - writeAdtsHeader(_adts,_adts.buffer); - getAACInfo(_adts, (int &)_audio_sample_rate, (int &)_audio_num_channels); - MP4Free(ppConfig); - } - _audio_ms = 1000.0 * _audio_duration / _audio_sample_rate; - /*InfoL << "\r\n" - << _audio_ms << "\r\n" - << _audio_num_samples << "\r\n" - << _audio_num_channels << "\r\n" - << _audio_sample_rate << "\r\n";*/ - }else{ - _audio_trId = MP4_INVALID_TRACK_ID; - } - } - if(_audio_trId == MP4_INVALID_TRACK_ID && _video_trId == MP4_INVALID_TRACK_ID){ - MP4Close(_hMP4File); - _hMP4File = MP4_INVALID_FILE_HANDLE; - throw runtime_error(StrPrinter << "该MP4文件音视频格式不支持:" << strFileName << endl); - } + _audio_trId = MP4FindTrackId(_hMP4File, 0, MP4_AUDIO_TRACK_TYPE, 0); + if (_audio_trId != MP4_INVALID_TRACK_ID) { + if (strcmp(MP4GetTrackMediaDataName(_hMP4File, _audio_trId), "mp4a") == 0) { + _audio_sample_rate = MP4GetTrackTimeScale(_hMP4File, _audio_trId); + auto _audio_duration = MP4GetTrackDuration(_hMP4File, _audio_trId); + _audio_num_samples = MP4GetTrackNumberOfSamples(_hMP4File,_audio_trId); + _audio_num_channels = MP4GetTrackAudioChannels(_hMP4File, _audio_trId); + _audio_sample_max_size = MP4GetTrackMaxSampleSize(_hMP4File,_audio_trId); + uint8_t *ppConfig; + uint32_t pConfigSize; + if(MP4GetTrackESConfiguration(_hMP4File,_audio_trId,&ppConfig,&pConfigSize)){ + _strAacCfg.assign((char *)ppConfig, pConfigSize); + makeAdtsHeader(_strAacCfg, _adts); + writeAdtsHeader(_adts,_adts.buffer); + getAACInfo(_adts, (int &)_audio_sample_rate, (int &)_audio_num_channels); + MP4Free(ppConfig); + } + _audio_ms = 1000.0 * _audio_duration / _audio_sample_rate; + /*InfoL << "\r\n" + << _audio_ms << "\r\n" + << _audio_num_samples << "\r\n" + << _audio_num_channels << "\r\n" + << _audio_sample_rate << "\r\n";*/ + }else{ + _audio_trId = MP4_INVALID_TRACK_ID; + } + } + if(_audio_trId == MP4_INVALID_TRACK_ID && _video_trId == MP4_INVALID_TRACK_ID){ + MP4Close(_hMP4File); + _hMP4File = MP4_INVALID_FILE_HANDLE; + throw runtime_error(StrPrinter << "该MP4文件音视频格式不支持:" << strFileName << endl); + } - _iDuration = MAX(_video_ms,_audio_ms); - _mediaMuxer.reset(new MultiMediaSourceMuxer(strVhost, strApp, strId, _iDuration / 1000.0, true, true, false, false)); - if (_audio_trId != MP4_INVALID_TRACK_ID) { - AACTrack::Ptr track = std::make_shared(_strAacCfg); - _mediaMuxer->addTrack(track); - } + _iDuration = MAX(_video_ms,_audio_ms); + _mediaMuxer.reset(new MultiMediaSourceMuxer(strVhost, strApp, strId, _iDuration / 1000.0, true, true, false, false)); + if (_audio_trId != MP4_INVALID_TRACK_ID) { + AACTrack::Ptr track = std::make_shared(_strAacCfg); + _mediaMuxer->addTrack(track); + } - if (_video_trId != MP4_INVALID_TRACK_ID) { - H264Track::Ptr track = std::make_shared(_strSps,_strPps); - _mediaMuxer->addTrack(track); - } + if (_video_trId != MP4_INVALID_TRACK_ID) { + H264Track::Ptr track = std::make_shared(_strSps,_strPps); + _mediaMuxer->addTrack(track); + } //添加完毕所有track,防止单track情况下最大等待3秒 _mediaMuxer->addTrackCompleted(); @@ -158,34 +158,34 @@ MP4Reader::MP4Reader(const string &strVhost,const string &strApp, const string & MP4Reader::~MP4Reader() { - if (_hMP4File != MP4_INVALID_FILE_HANDLE) { - MP4Close(_hMP4File); - _hMP4File = MP4_INVALID_FILE_HANDLE; - } + if (_hMP4File != MP4_INVALID_FILE_HANDLE) { + MP4Close(_hMP4File); + _hMP4File = MP4_INVALID_FILE_HANDLE; + } } void MP4Reader::startReadMP4() { - auto strongSelf = shared_from_this(); + auto strongSelf = shared_from_this(); GET_CONFIG(uint32_t,sampleMS,Record::kSampleMS); - _timer = std::make_shared(sampleMS / 1000.0f,[strongSelf](){ - return strongSelf->readSample(0,false); - }, _poller); + _timer = std::make_shared(sampleMS / 1000.0f,[strongSelf](){ + return strongSelf->readSample(0,false); + }, _poller); //先读sampleMS毫秒的数据用于产生MediaSouce - readSample(sampleMS, false); - _mediaMuxer->setListener(strongSelf); + readSample(sampleMS, false); + _mediaMuxer->setListener(strongSelf); } bool MP4Reader::seekTo(MediaSource &sender,uint32_t ui32Stamp){ - seek(ui32Stamp); - return true; + seek(ui32Stamp); + return true; } bool MP4Reader::close(MediaSource &sender,bool force){ if(!_mediaMuxer || (!force && _mediaMuxer->totalReaderCount())){ return false; } - _timer.reset(); + _timer.reset(); WarnL << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force; return true; } @@ -198,145 +198,145 @@ void MP4Reader::onNoneReader(MediaSource &sender) { } int MP4Reader::totalReaderCount(MediaSource &sender) { - return _mediaMuxer ? _mediaMuxer->totalReaderCount() : sender.readerCount(); + return _mediaMuxer ? _mediaMuxer->totalReaderCount() : sender.readerCount(); } bool MP4Reader::readSample(int iTimeInc,bool justSeekSyncFrame) { - TimeTicker(); - lock_guard lck(_mtx); - auto bFlag0 = readVideoSample(iTimeInc,justSeekSyncFrame);//数据没读完 - auto bFlag1 = readAudioSample(iTimeInc,justSeekSyncFrame);//数据没读完 - auto bFlag2 = _mediaMuxer->totalReaderCount() > 0;//读取者大于0 - if((bFlag0 || bFlag1) && bFlag2){ - _alive.resetTime(); - } - //重头开始循环读取 - GET_CONFIG(bool,fileRepeat,Record::kFileRepeat); - if (fileRepeat && !bFlag0 && !bFlag1) { - seek(0); - } - //DebugL << "alive ..."; - //3秒延时关闭 - return _alive.elapsedTime() < 3 * 1000; + TimeTicker(); + lock_guard lck(_mtx); + auto bFlag0 = readVideoSample(iTimeInc,justSeekSyncFrame);//数据没读完 + auto bFlag1 = readAudioSample(iTimeInc,justSeekSyncFrame);//数据没读完 + auto bFlag2 = _mediaMuxer->totalReaderCount() > 0;//读取者大于0 + if((bFlag0 || bFlag1) && bFlag2){ + _alive.resetTime(); + } + //重头开始循环读取 + GET_CONFIG(bool,fileRepeat,Record::kFileRepeat); + if (fileRepeat && !bFlag0 && !bFlag1) { + seek(0); + } + //DebugL << "alive ..."; + //3秒延时关闭 + return _alive.elapsedTime() < 3 * 1000; } inline bool MP4Reader::readVideoSample(int iTimeInc,bool justSeekSyncFrame) { - if (_video_trId != MP4_INVALID_TRACK_ID) { - auto iNextSample = getVideoSampleId(iTimeInc); - MP4SampleId iIdx = _video_current; - for (; iIdx < iNextSample; iIdx++) { - uint8_t *pBytes = _pcVideoSample.get(); - uint32_t numBytes = _video_sample_max_size; - MP4Duration pRenderingOffset; - if(MP4ReadSample(_hMP4File, _video_trId, iIdx + 1, &pBytes, &numBytes,NULL,NULL,&pRenderingOffset,&_bSyncSample)){ + if (_video_trId != MP4_INVALID_TRACK_ID) { + auto iNextSample = getVideoSampleId(iTimeInc); + MP4SampleId iIdx = _video_current; + for (; iIdx < iNextSample; iIdx++) { + uint8_t *pBytes = _pcVideoSample.get(); + uint32_t numBytes = _video_sample_max_size; + MP4Duration pRenderingOffset; + if(MP4ReadSample(_hMP4File, _video_trId, iIdx + 1, &pBytes, &numBytes,NULL,NULL,&pRenderingOffset,&_bSyncSample)){ if (!justSeekSyncFrame) { uint32_t dts = (double) _video_ms * iIdx / _video_num_samples; uint32_t pts = dts + pRenderingOffset / 90; uint32_t iOffset = 0; - while (iOffset < numBytes) { - uint32_t iFrameLen; - memcpy(&iFrameLen,pBytes + iOffset,4); - iFrameLen = ntohl(iFrameLen); + while (iOffset < numBytes) { + uint32_t iFrameLen; + memcpy(&iFrameLen,pBytes + iOffset,4); + iFrameLen = ntohl(iFrameLen); if(iFrameLen + iOffset + 4> numBytes){ break; } - memcpy(pBytes + iOffset, "\x0\x0\x0\x1", 4); - writeH264(pBytes + iOffset, iFrameLen + 4, dts, pts); - iOffset += (iFrameLen + 4); - } - }else if(_bSyncSample){ - break; - } - }else{ - ErrorL << "读取视频失败:" << iIdx + 1; - } - } - _video_current = iIdx; - return _video_current < _video_num_samples; - } - return false; + memcpy(pBytes + iOffset, "\x0\x0\x0\x1", 4); + writeH264(pBytes + iOffset, iFrameLen + 4, dts, pts); + iOffset += (iFrameLen + 4); + } + }else if(_bSyncSample){ + break; + } + }else{ + ErrorL << "读取视频失败:" << iIdx + 1; + } + } + _video_current = iIdx; + return _video_current < _video_num_samples; + } + return false; } inline bool MP4Reader::readAudioSample(int iTimeInc,bool justSeekSyncFrame) { - if (_audio_trId != MP4_INVALID_TRACK_ID) { - auto iNextSample = getAudioSampleId(iTimeInc); - for (auto i = _audio_current; i < iNextSample; i++) { - uint32_t numBytes = _audio_sample_max_size; - uint8_t *pBytes = _adts.buffer + 7; - if(MP4ReadSample(_hMP4File, _audio_trId, i + 1, &pBytes, &numBytes)){ - if (!justSeekSyncFrame) { - uint32_t dts = (double) _audio_ms * i / _audio_num_samples; - _adts.aac_frame_length = 7 + numBytes; - writeAdtsHeader(_adts, _adts.buffer); - writeAAC(_adts.buffer, _adts.aac_frame_length, dts); - } - }else{ - ErrorL << "读取音频失败:" << i+ 1; - } - } - _audio_current = iNextSample; - return _audio_current < _audio_num_samples; - } - return false; + if (_audio_trId != MP4_INVALID_TRACK_ID) { + auto iNextSample = getAudioSampleId(iTimeInc); + for (auto i = _audio_current; i < iNextSample; i++) { + uint32_t numBytes = _audio_sample_max_size; + uint8_t *pBytes = _adts.buffer + 7; + if(MP4ReadSample(_hMP4File, _audio_trId, i + 1, &pBytes, &numBytes)){ + if (!justSeekSyncFrame) { + uint32_t dts = (double) _audio_ms * i / _audio_num_samples; + _adts.aac_frame_length = 7 + numBytes; + writeAdtsHeader(_adts, _adts.buffer); + writeAAC(_adts.buffer, _adts.aac_frame_length, dts); + } + }else{ + ErrorL << "读取音频失败:" << i+ 1; + } + } + _audio_current = iNextSample; + return _audio_current < _audio_num_samples; + } + return false; } inline void MP4Reader::writeH264(uint8_t *pucData,int iLen,uint32_t dts,uint32_t pts) { - _mediaMuxer->inputFrame(std::make_shared((char*)pucData,iLen,dts,pts)); + _mediaMuxer->inputFrame(std::make_shared((char*)pucData,iLen,dts,pts)); } inline void MP4Reader::writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp) { - _mediaMuxer->inputFrame(std::make_shared((char*)pucData,iLen,uiStamp)); + _mediaMuxer->inputFrame(std::make_shared((char*)pucData,iLen,uiStamp)); } inline MP4SampleId MP4Reader::getVideoSampleId(int iTimeInc ) { - MP4SampleId video_current = (double)_video_num_samples * (_iSeekTime + _ticker.elapsedTime() + iTimeInc) / _video_ms; - video_current = MAX(0,MIN(_video_num_samples, video_current)); - return video_current; + MP4SampleId video_current = (double)_video_num_samples * (_iSeekTime + _ticker.elapsedTime() + iTimeInc) / _video_ms; + video_current = MAX(0,MIN(_video_num_samples, video_current)); + return video_current; } inline MP4SampleId MP4Reader::getAudioSampleId(int iTimeInc) { - MP4SampleId audio_current = (double)_audio_num_samples * (_iSeekTime + _ticker.elapsedTime() + iTimeInc) / _audio_ms ; - audio_current = MAX(0,MIN(_audio_num_samples,audio_current)); - return audio_current; + MP4SampleId audio_current = (double)_audio_num_samples * (_iSeekTime + _ticker.elapsedTime() + iTimeInc) / _audio_ms ; + audio_current = MAX(0,MIN(_audio_num_samples,audio_current)); + return audio_current; } inline void MP4Reader::setSeekTime(uint32_t iSeekTime){ - _iSeekTime = MAX(0, MIN(iSeekTime,_iDuration)); - _ticker.resetTime(); - if (_audio_trId != MP4_INVALID_TRACK_ID) { - _audio_current = getAudioSampleId(); - } - if (_video_trId != MP4_INVALID_TRACK_ID) { - _video_current = getVideoSampleId(); - } + _iSeekTime = MAX(0, MIN(iSeekTime,_iDuration)); + _ticker.resetTime(); + if (_audio_trId != MP4_INVALID_TRACK_ID) { + _audio_current = getAudioSampleId(); + } + if (_video_trId != MP4_INVALID_TRACK_ID) { + _video_current = getVideoSampleId(); + } } inline uint32_t MP4Reader::getVideoCurrentTime(){ - return (double)_video_current * _video_ms /_video_num_samples; + return (double)_video_current * _video_ms /_video_num_samples; } void MP4Reader::seek(uint32_t iSeekTime,bool bReStart){ - lock_guard lck(_mtx); - if(iSeekTime == 0 || _video_trId == MP4_INVALID_TRACK_ID){ - setSeekTime(iSeekTime); - }else{ - setSeekTime(iSeekTime - 5000); - //在之后的10秒查找关键帧 - readVideoSample(10000, true); - if (_bSyncSample) { - //找到关键帧 - auto iIdr = _video_current; - setSeekTime(getVideoCurrentTime()); - _video_current = iIdr; - }else{ - //未找到关键帧 - setSeekTime(iSeekTime); - } - } - _mediaMuxer->setTimeStamp(_iSeekTime); + lock_guard lck(_mtx); + if(iSeekTime == 0 || _video_trId == MP4_INVALID_TRACK_ID){ + setSeekTime(iSeekTime); + }else{ + setSeekTime(iSeekTime - 5000); + //在之后的10秒查找关键帧 + readVideoSample(10000, true); + if (_bSyncSample) { + //找到关键帧 + auto iIdr = _video_current; + setSeekTime(getVideoCurrentTime()); + _video_current = iIdr; + }else{ + //未找到关键帧 + setSeekTime(iSeekTime); + } + } + _mediaMuxer->setTimeStamp(_iSeekTime); - if(bReStart){ - _timer.reset(); - startReadMP4(); - } + if(bReStart){ + _timer.reset(); + startReadMP4(); + } } #endif //ENABLE_MP4V2 @@ -344,26 +344,26 @@ void MP4Reader::seek(uint32_t iSeekTime,bool bReStart){ MediaSource::Ptr MP4Reader::onMakeMediaSource(const string &strSchema, - const string &strVhost, - const string &strApp, - const string &strId, - const string &filePath, - bool checkApp ){ + const string &strVhost, + const string &strApp, + const string &strId, + const string &filePath, + bool checkApp ){ #ifdef ENABLE_MP4V2 GET_CONFIG(string,appName,Record::kAppName); if (checkApp && strApp != appName) { - return nullptr; - } - try { - MP4Reader::Ptr pReader(new MP4Reader(strVhost,strApp, strId,filePath)); - pReader->startReadMP4(); - return MediaSource::find(strSchema,strVhost,strApp, strId, false); - } catch (std::exception &ex) { - WarnL << ex.what(); - return nullptr; - } + return nullptr; + } + try { + MP4Reader::Ptr pReader(new MP4Reader(strVhost,strApp, strId,filePath)); + pReader->startReadMP4(); + return MediaSource::find(strSchema,strVhost,strApp, strId, false); + } catch (std::exception &ex) { + WarnL << ex.what(); + return nullptr; + } #else - return nullptr; + return nullptr; #endif //ENABLE_MP4V2 } diff --git a/src/Record/MP4Reader.h b/src/Record/MP4Reader.h index 30487c41..09d7ef9b 100644 --- a/src/Record/MP4Reader.h +++ b/src/Record/MP4Reader.h @@ -39,91 +39,91 @@ namespace mediakit { class MP4Reader : public std::enable_shared_from_this ,public MediaSourceEvent{ public: - typedef std::shared_ptr Ptr; - virtual ~MP4Reader(); + typedef std::shared_ptr Ptr; + virtual ~MP4Reader(); - /** - * 流化一个mp4文件,使之转换成RtspMediaSource和RtmpMediaSource - * @param strVhost 虚拟主机 - * @param strApp 应用名 - * @param strId 流id - * @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 - */ - MP4Reader(const string &strVhost,const string &strApp, const string &strId,const string &filePath = ""); - /** - * 开始流化MP4文件,需要指出的是,MP4Reader对象一经过调用startReadMP4方法,它的强引用会自持有, - * 意思是在文件流化结束之前或中断之前,MP4Reader对象是不会被销毁的(不管有没有被外部对象持有) - */ - void startReadMP4(); + /** + * 流化一个mp4文件,使之转换成RtspMediaSource和RtmpMediaSource + * @param strVhost 虚拟主机 + * @param strApp 应用名 + * @param strId 流id + * @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 + */ + MP4Reader(const string &strVhost,const string &strApp, const string &strId,const string &filePath = ""); + /** + * 开始流化MP4文件,需要指出的是,MP4Reader对象一经过调用startReadMP4方法,它的强引用会自持有, + * 意思是在文件流化结束之前或中断之前,MP4Reader对象是不会被销毁的(不管有没有被外部对象持有) + */ + void startReadMP4(); - /** - * 自动生成MP4Reader对象然后查找相关的MediaSource对象 - * @param strSchema 协议名 - * @param strVhost 虚拟主机 - * @param strApp 应用名 - * @param strId 流id - * @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 - * @param checkApp 是否检查app,防止服务器上文件被乱访问 - * @return MediaSource - */ - static MediaSource::Ptr onMakeMediaSource(const string &strSchema, - const string &strVhost, - const string &strApp, - const string &strId, - const string &filePath = "", - bool checkApp = true); + /** + * 自动生成MP4Reader对象然后查找相关的MediaSource对象 + * @param strSchema 协议名 + * @param strVhost 虚拟主机 + * @param strApp 应用名 + * @param strId 流id + * @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 + * @param checkApp 是否检查app,防止服务器上文件被乱访问 + * @return MediaSource + */ + static MediaSource::Ptr onMakeMediaSource(const string &strSchema, + const string &strVhost, + const string &strApp, + const string &strId, + const string &filePath = "", + bool checkApp = true); private: - //MediaSourceEvent override - bool seekTo(MediaSource &sender,uint32_t ui32Stamp) override; - bool close(MediaSource &sender,bool force) override; + //MediaSourceEvent override + bool seekTo(MediaSource &sender,uint32_t ui32Stamp) override; + bool close(MediaSource &sender,bool force) override; void onNoneReader(MediaSource &sender) override; - int totalReaderCount(MediaSource &sender) override; + int totalReaderCount(MediaSource &sender) override; #ifdef ENABLE_MP4V2 void seek(uint32_t iSeekTime,bool bReStart = true); - inline void setSeekTime(uint32_t iSeekTime); - inline uint32_t getVideoCurrentTime(); - inline MP4SampleId getVideoSampleId(int iTimeInc = 0); - inline MP4SampleId getAudioSampleId(int iTimeInc = 0); - bool readSample(int iTimeInc, bool justSeekSyncFrame); - inline bool readVideoSample(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 writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp); + inline void setSeekTime(uint32_t iSeekTime); + inline uint32_t getVideoCurrentTime(); + inline MP4SampleId getVideoSampleId(int iTimeInc = 0); + inline MP4SampleId getAudioSampleId(int iTimeInc = 0); + bool readSample(int iTimeInc, bool justSeekSyncFrame); + inline bool readVideoSample(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 writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp); private: - MP4FileHandle _hMP4File = MP4_INVALID_FILE_HANDLE; - MP4TrackId _video_trId = MP4_INVALID_TRACK_ID; - uint32_t _video_ms = 0; - uint32_t _video_num_samples = 0; - uint32_t _video_sample_max_size = 0; - uint32_t _video_width = 0; - uint32_t _video_height = 0; - uint32_t _video_framerate = 0; - string _strPps; - string _strSps; - bool _bSyncSample = false; + MP4FileHandle _hMP4File = MP4_INVALID_FILE_HANDLE; + MP4TrackId _video_trId = MP4_INVALID_TRACK_ID; + uint32_t _video_ms = 0; + uint32_t _video_num_samples = 0; + uint32_t _video_sample_max_size = 0; + uint32_t _video_width = 0; + uint32_t _video_height = 0; + uint32_t _video_framerate = 0; + string _strPps; + string _strSps; + bool _bSyncSample = false; - MP4TrackId _audio_trId = MP4_INVALID_TRACK_ID; - uint32_t _audio_ms = 0; - uint32_t _audio_num_samples = 0; - uint32_t _audio_sample_max_size = 0; - uint32_t _audio_sample_rate = 0; - uint32_t _audio_num_channels = 0; - string _strAacCfg; - AACFrame _adts; + MP4TrackId _audio_trId = MP4_INVALID_TRACK_ID; + uint32_t _audio_ms = 0; + uint32_t _audio_num_samples = 0; + uint32_t _audio_sample_max_size = 0; + uint32_t _audio_sample_rate = 0; + uint32_t _audio_num_channels = 0; + string _strAacCfg; + AACFrame _adts; - int _iDuration = 0; - MultiMediaSourceMuxer::Ptr _mediaMuxer; - MP4SampleId _video_current = 0; - MP4SampleId _audio_current = 0; - std::shared_ptr _pcVideoSample; + int _iDuration = 0; + MultiMediaSourceMuxer::Ptr _mediaMuxer; + MP4SampleId _video_current = 0; + MP4SampleId _audio_current = 0; + std::shared_ptr _pcVideoSample; - int _iSeekTime = 0 ; - Ticker _ticker; - Ticker _alive; - recursive_mutex _mtx; - Timer::Ptr _timer; - EventPoller::Ptr _poller; + int _iSeekTime = 0 ; + Ticker _ticker; + Ticker _alive; + recursive_mutex _mtx; + Timer::Ptr _timer; + EventPoller::Ptr _poller; #endif //ENABLE_MP4V2 }; diff --git a/src/Record/MP4Recorder.cpp b/src/Record/MP4Recorder.cpp index a92f3fde..1247db71 100644 --- a/src/Record/MP4Recorder.cpp +++ b/src/Record/MP4Recorder.cpp @@ -36,31 +36,31 @@ using namespace toolkit; namespace mediakit { MP4Recorder::MP4Recorder(const string& strPath, - const string &strVhost, - const string &strApp, - const string &strStreamId) { - _strPath = strPath; - /////record 业务逻辑////// - _info.strAppName = strApp; - _info.strStreamId = strStreamId; - _info.strVhost = strVhost; - _info.strFolder = strPath; + const string &strVhost, + const string &strApp, + const string &strStreamId) { + _strPath = strPath; + /////record 业务逻辑////// + _info.strAppName = strApp; + _info.strStreamId = strStreamId; + _info.strVhost = strVhost; + _info.strFolder = strPath; } MP4Recorder::~MP4Recorder() { - closeFile(); + closeFile(); } void MP4Recorder::createFile() { - closeFile(); - auto strDate = getTimeStr("%Y-%m-%d"); - auto strTime = getTimeStr("%H-%M-%S"); - auto strFileTmp = _strPath + strDate + "/." + strTime + ".mp4"; - auto strFile = _strPath + strDate + "/" + strTime + ".mp4"; + closeFile(); + auto strDate = getTimeStr("%Y-%m-%d"); + auto strTime = getTimeStr("%H-%M-%S"); + auto strFileTmp = _strPath + strDate + "/." + strTime + ".mp4"; + auto strFile = _strPath + strDate + "/" + strTime + ".mp4"; - /////record 业务逻辑////// - _info.ui64StartedTime = ::time(NULL); - _info.strFileName = strTime + ".mp4"; - _info.strFilePath = strFile; + /////record 业务逻辑////// + _info.ui64StartedTime = ::time(NULL); + _info.strFileName = strTime + ".mp4"; + _info.strFilePath = strFile; GET_CONFIG(string,appName,Record::kAppName); _info.strUrl = appName + "/" + _info.strAppName + "/" @@ -68,78 +68,78 @@ void MP4Recorder::createFile() { + strDate + "/" + strTime + ".mp4"; - try { - _muxer = std::make_shared(strFileTmp.data()); - for(auto &track :_tracks){ + try { + _muxer = std::make_shared(strFileTmp.data()); + for(auto &track :_tracks){ //添加track _muxer->addTrack(track); - } - _strFileTmp = strFileTmp; - _strFile = strFile; - _createFileTicker.resetTime(); - }catch(std::exception &ex) { - WarnL << ex.what(); - } + } + _strFileTmp = strFileTmp; + _strFile = strFile; + _createFileTicker.resetTime(); + }catch(std::exception &ex) { + WarnL << ex.what(); + } } void MP4Recorder::asyncClose() { - auto muxer = _muxer; - auto strFileTmp = _strFileTmp; - auto strFile = _strFile; - auto info = _info; - WorkThreadPool::Instance().getExecutor()->async([muxer,strFileTmp,strFile,info]() { - //获取文件录制时间,放在关闭mp4之前是为了忽略关闭mp4执行时间 - const_cast(info).ui64TimeLen = ::time(NULL) - info.ui64StartedTime; - //关闭mp4非常耗时,所以要放在后台线程执行 - const_cast(muxer).reset(); - //临时文件名改成正式文件名,防止mp4未完成时被访问 - rename(strFileTmp.data(),strFile.data()); - //获取文件大小 - struct stat fileData; - stat(strFile.data(), &fileData); - const_cast(info).ui64FileSize = fileData.st_size; - /////record 业务逻辑////// - NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastRecordMP4,info); - }); + auto muxer = _muxer; + auto strFileTmp = _strFileTmp; + auto strFile = _strFile; + auto info = _info; + WorkThreadPool::Instance().getExecutor()->async([muxer,strFileTmp,strFile,info]() { + //获取文件录制时间,放在关闭mp4之前是为了忽略关闭mp4执行时间 + const_cast(info).ui64TimeLen = ::time(NULL) - info.ui64StartedTime; + //关闭mp4非常耗时,所以要放在后台线程执行 + const_cast(muxer).reset(); + //临时文件名改成正式文件名,防止mp4未完成时被访问 + rename(strFileTmp.data(),strFile.data()); + //获取文件大小 + struct stat fileData; + stat(strFile.data(), &fileData); + const_cast(info).ui64FileSize = fileData.st_size; + /////record 业务逻辑////// + NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastRecordMP4,info); + }); } void MP4Recorder::closeFile() { - if (_muxer) { - asyncClose(); - _muxer = nullptr; - } + if (_muxer) { + asyncClose(); + _muxer = nullptr; + } } void MP4Recorder::inputFrame(const Frame::Ptr &frame) { - GET_CONFIG(uint32_t,recordSec,Record::kFileSecond); - if(!_muxer || ((_createFileTicker.elapsedTime() > recordSec * 1000) && - (!_haveVideo || (_haveVideo && frame->keyFrame()))) ){ - //成立条件 - //1、_muxer为空 - //2、到了切片时间,并且只有音频 - //3、到了切片时间,有视频并且遇到视频的关键帧 - createFile(); - } + GET_CONFIG(uint32_t,recordSec,Record::kFileSecond); + if(!_muxer || ((_createFileTicker.elapsedTime() > recordSec * 1000) && + (!_haveVideo || (_haveVideo && frame->keyFrame()))) ){ + //成立条件 + //1、_muxer为空 + //2、到了切片时间,并且只有音频 + //3、到了切片时间,有视频并且遇到视频的关键帧 + createFile(); + } - if(_muxer){ - //生成mp4文件 - _muxer->inputFrame(frame); - } + if(_muxer){ + //生成mp4文件 + _muxer->inputFrame(frame); + } } void MP4Recorder::addTrack(const Track::Ptr & track){ - //保存所有的track,为创建MP4MuxerFile做准备 - _tracks.emplace_back(track); - if(track->getTrackType() == TrackVideo){ - _haveVideo = true; - } + //保存所有的track,为创建MP4MuxerFile做准备 + _tracks.emplace_back(track); + if(track->getTrackType() == TrackVideo){ + _haveVideo = true; + } } void MP4Recorder::resetTracks() { - closeFile(); - _tracks.clear(); - _haveVideo = false; - _createFileTicker.resetTime(); + closeFile(); + _tracks.clear(); + _haveVideo = false; + _createFileTicker.resetTime(); } } /* namespace mediakit */ diff --git a/src/Record/MP4Recorder.h b/src/Record/MP4Recorder.h index 838f2507..110fa785 100644 --- a/src/Record/MP4Recorder.h +++ b/src/Record/MP4Recorder.h @@ -42,38 +42,38 @@ namespace mediakit { class MP4Info { public: - time_t ui64StartedTime; //GMT标准时间,单位秒 - time_t ui64TimeLen;//录像长度,单位秒 - off_t ui64FileSize;//文件大小,单位BYTE - string strFilePath;//文件路径 - string strFileName;//文件名称 - string strFolder;//文件夹路径 - string strUrl;//播放路径 - string strAppName;//应用名称 - string strStreamId;//流ID - string strVhost;//vhost + time_t ui64StartedTime; //GMT标准时间,单位秒 + time_t ui64TimeLen;//录像长度,单位秒 + off_t ui64FileSize;//文件大小,单位BYTE + string strFilePath;//文件路径 + string strFileName;//文件名称 + string strFolder;//文件夹路径 + string strUrl;//播放路径 + string strAppName;//应用名称 + string strStreamId;//流ID + string strVhost;//vhost }; #ifdef ENABLE_MP4RECORD class MP4Recorder : public MediaSinkInterface{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - MP4Recorder(const string &strPath, - const string &strVhost, - const string &strApp, - const string &strStreamId); - virtual ~MP4Recorder(); + MP4Recorder(const string &strPath, + const string &strVhost, + const string &strApp, + const string &strStreamId); + virtual ~MP4Recorder(); - /** - * 重置所有Track - */ - void resetTracks() override; + /** + * 重置所有Track + */ + void resetTracks() override; - /** + /** * 输入frame */ - void inputFrame(const Frame::Ptr &frame) override; + void inputFrame(const Frame::Ptr &frame) override; /** * 添加ready状态的track @@ -84,14 +84,14 @@ private: void closeFile(); void asyncClose(); private: - string _strPath; - string _strFile; - string _strFileTmp; - Ticker _createFileTicker; - MP4Info _info; - bool _haveVideo = false; - MP4MuxerFile::Ptr _muxer; - list _tracks; + string _strPath; + string _strFile; + string _strFileTmp; + Ticker _createFileTicker; + MP4Info _info; + bool _haveVideo = false; + MP4MuxerFile::Ptr _muxer; + list _tracks; }; #endif ///ENABLE_MP4RECORD diff --git a/src/Record/Recorder.h b/src/Record/Recorder.h index cb3d9cc6..5a072568 100644 --- a/src/Record/Recorder.h +++ b/src/Record/Recorder.h @@ -37,32 +37,32 @@ class MediaSinkInterface; class Recorder{ public: - typedef enum { - // 未录制 - status_not_record = 0, - // 等待MediaSource注册,注册成功后立即开始录制 - status_wait_record = 1, - // MediaSource已注册,并且正在录制 - status_recording = 2, - } status; + typedef enum { + // 未录制 + status_not_record = 0, + // 等待MediaSource注册,注册成功后立即开始录制 + status_wait_record = 1, + // MediaSource已注册,并且正在录制 + status_recording = 2, + } status; - typedef enum { - // 录制hls - type_hls = 0, - // 录制MP4 - type_mp4 = 1 - } type; + typedef enum { + // 录制hls + type_hls = 0, + // 录制MP4 + type_mp4 = 1 + } type; - /** - * 获取录制文件绝对路径 - * @param type hls还是MP4录制 + /** + * 获取录制文件绝对路径 + * @param type hls还是MP4录制 * @param vhost 虚拟主机 * @param app 应用名 * @param stream_id 流id * @param customized_path 录像文件保存自定义目录,默认为空则自动生成 - * @return 录制文件绝对路径 - */ - static string getRecordPath(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path = ""); + * @return 录制文件绝对路径 + */ + static string getRecordPath(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path = ""); /** * 获取录制状态 @@ -72,57 +72,57 @@ public: * @param stream_id 流id * @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 app 应用名 * @param stream_id 流id * @param customized_path 录像文件保存自定义目录,默认为空则自动生成 - * @param waitForRecord 是否等待流注册后再录制,未注册时,置false将返回失败 - * @param continueRecord 流注销时是否继续等待录制还是立即停止录制 - * @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); + * @param waitForRecord 是否等待流注册后再录制,未注册时,置false将返回失败 + * @param continueRecord 流注销时是否继续等待录制还是立即停止录制 + * @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); - /** - * 停止录制 - * @param type hls还是MP4录制 + /** + * 停止录制 + * @param type hls还是MP4录制 * @param vhost 虚拟主机 * @param app 应用名 * @param stream_id 流id - */ - static bool stopRecord(type type, const string &vhost, const string &app, const string &stream_id); + */ + 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 app 应用名 * @param stream_id 流id - */ - static std::shared_ptr getRecorder(type type, const string &vhost, const string &app, const string &stream_id); + */ + static std::shared_ptr getRecorder(type type, const string &vhost, const string &app, const string &stream_id); - /** - * 创建录制器对象 - * @param type hls还是MP4录制 + /** + * 创建录制器对象 + * @param type hls还是MP4录制 * @param vhost 虚拟主机 * @param app 应用名 * @param stream_id 流id * @param customized_path 录像文件保存自定义目录,默认为空则自动生成 - * @return 对象指针,可能为nullptr - */ + * @return 对象指针,可能为nullptr + */ static std::shared_ptr createRecorder(type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path); private: - Recorder() = delete; - ~Recorder() = delete; + Recorder() = delete; + ~Recorder() = delete; }; } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpDemuxer.h b/src/Rtmp/RtmpDemuxer.h index a2c900a8..b0acc4a5 100644 --- a/src/Rtmp/RtmpDemuxer.h +++ b/src/Rtmp/RtmpDemuxer.h @@ -41,27 +41,27 @@ namespace mediakit { class RtmpDemuxer : public Demuxer{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - RtmpDemuxer() = default; - virtual ~RtmpDemuxer() = default; + RtmpDemuxer() = default; + virtual ~RtmpDemuxer() = default; - void loadMetaData(const AMFValue &metadata); + void loadMetaData(const AMFValue &metadata); - /** - * 开始解复用 - * @param pkt rtmp包 - * @return true 代表是i帧 - */ - bool inputRtmp(const RtmpPacket::Ptr &pkt); + /** + * 开始解复用 + * @param pkt rtmp包 + * @return true 代表是i帧 + */ + bool inputRtmp(const RtmpPacket::Ptr &pkt); private: - void makeVideoTrack(const AMFValue &val); - void makeAudioTrack(const AMFValue &val); + void makeVideoTrack(const AMFValue &val); + void makeAudioTrack(const AMFValue &val); private: - bool _tryedGetVideoTrack = false; - bool _tryedGetAudioTrack = false; - RtmpCodec::Ptr _audioRtmpDecoder; - RtmpCodec::Ptr _videoRtmpDecoder; + bool _tryedGetVideoTrack = false; + bool _tryedGetAudioTrack = false; + RtmpCodec::Ptr _audioRtmpDecoder; + RtmpCodec::Ptr _videoRtmpDecoder; }; } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpMediaSource.h b/src/Rtmp/RtmpMediaSource.h index db13960e..a4f221e1 100644 --- a/src/Rtmp/RtmpMediaSource.h +++ b/src/Rtmp/RtmpMediaSource.h @@ -58,163 +58,163 @@ namespace mediakit { */ class RtmpMediaSource : public MediaSource, public RingDelegate { public: - typedef std::shared_ptr Ptr; - typedef RingBuffer RingType; + typedef std::shared_ptr Ptr; + typedef RingBuffer RingType; - /** - * 构造函数 - * @param vhost 虚拟主机名 - * @param app 应用名 - * @param stream_id 流id - * @param ring_size 可以设置固定的环形缓冲大小,0则自适应 - */ - RtmpMediaSource(const string &vhost, - const string &app, - const string &stream_id, - int ring_size = RTMP_GOP_SIZE) : - MediaSource(RTMP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) { - } + /** + * 构造函数 + * @param vhost 虚拟主机名 + * @param app 应用名 + * @param stream_id 流id + * @param ring_size 可以设置固定的环形缓冲大小,0则自适应 + */ + RtmpMediaSource(const string &vhost, + const string &app, + const string &stream_id, + int ring_size = RTMP_GOP_SIZE) : + MediaSource(RTMP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) { + } - virtual ~RtmpMediaSource() {} + virtual ~RtmpMediaSource() {} - /** - * 获取媒体源的环形缓冲 - */ - const RingType::Ptr &getRing() const { - return _ring; - } + /** + * 获取媒体源的环形缓冲 + */ + const RingType::Ptr &getRing() const { + return _ring; + } - /** - * 获取播放器个数 - * @return - */ - int readerCount() override { - return _ring ? _ring->readerCount() : 0; - } + /** + * 获取播放器个数 + * @return + */ + int readerCount() override { + return _ring ? _ring->readerCount() : 0; + } - /** - * 获取metadata - */ - const AMFValue &getMetaData() const { - lock_guard lock(_mtx); - return _metadata; - } + /** + * 获取metadata + */ + const AMFValue &getMetaData() const { + lock_guard lock(_mtx); + return _metadata; + } - /** - * 获取所有的config帧 - */ - template - void getConfigFrame(const FUNC &f) { - lock_guard lock(_mtx); - for (auto &pr : _config_frame_map) { - f(pr.second); - } - } + /** + * 获取所有的config帧 + */ + template + void getConfigFrame(const FUNC &f) { + lock_guard lock(_mtx); + for (auto &pr : _config_frame_map) { + f(pr.second); + } + } - /** - * 设置metadata - */ - virtual void setMetaData(const AMFValue &metadata) { - lock_guard lock(_mtx); - _metadata = metadata; - if(_ring){ - regist(); - } - } + /** + * 设置metadata + */ + virtual void setMetaData(const AMFValue &metadata) { + lock_guard lock(_mtx); + _metadata = metadata; + if(_ring){ + regist(); + } + } - /** - * 输入rtmp包 - * @param pkt rtmp包 - * @param key 是否为关键帧 - */ - void onWrite(const RtmpPacket::Ptr &pkt, bool key = true) override { - lock_guard lock(_mtx); - if(pkt->typeId == MSG_VIDEO){ - //有视频,那么启用GOP缓存 + /** + * 输入rtmp包 + * @param pkt rtmp包 + * @param key 是否为关键帧 + */ + void onWrite(const RtmpPacket::Ptr &pkt, bool key = true) override { + lock_guard lock(_mtx); + if(pkt->typeId == MSG_VIDEO){ + //有视频,那么启用GOP缓存 _have_video = true; - } - if (pkt->isCfgFrame()) { - _config_frame_map[pkt->typeId] = pkt; - return; - } + } + if (pkt->isCfgFrame()) { + _config_frame_map[pkt->typeId] = pkt; + return; + } - if (!_ring) { - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - auto lam = [weakSelf](const EventPoller::Ptr &, int size, bool) { - auto strongSelf = weakSelf.lock(); - if (!strongSelf) { - return; - } - strongSelf->onReaderChanged(size); - }; + if (!_ring) { + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + auto lam = [weakSelf](const EventPoller::Ptr &, int size, bool) { + auto strongSelf = weakSelf.lock(); + if (!strongSelf) { + return; + } + strongSelf->onReaderChanged(size); + }; - //rtmp包缓存最大允许512个,如果是纯视频(25fps)大概为20秒数据 - //但是这个是GOP缓存的上限值,真实的GOP缓存大小等于两个I帧之间的包数的两倍 - //而且每次遇到I帧,则会清空GOP缓存,所以真实的GOP缓存远小于此值 - _ring = std::make_shared(_ring_size,std::move(lam)); - onReaderChanged(0); + //rtmp包缓存最大允许512个,如果是纯视频(25fps)大概为20秒数据 + //但是这个是GOP缓存的上限值,真实的GOP缓存大小等于两个I帧之间的包数的两倍 + //而且每次遇到I帧,则会清空GOP缓存,所以真实的GOP缓存远小于此值 + _ring = std::make_shared(_ring_size,std::move(lam)); + onReaderChanged(0); - if(_metadata){ - regist(); - } - } - _track_stamps_map[pkt->typeId] = pkt->timeStamp; - //不存在视频,为了减少缓存延时,那么关闭GOP缓存 - _ring->write(pkt, _have_video ? pkt->isVideoKeyFrame() : true); - checkNoneReader(); - } + if(_metadata){ + regist(); + } + } + _track_stamps_map[pkt->typeId] = pkt->timeStamp; + //不存在视频,为了减少缓存延时,那么关闭GOP缓存 + _ring->write(pkt, _have_video ? pkt->isVideoKeyFrame() : true); + checkNoneReader(); + } - /** - * 获取当前时间戳 - */ - uint32_t getTimeStamp(TrackType trackType) override { - lock_guard lock(_mtx); - switch (trackType) { - case TrackVideo: - return _track_stamps_map[MSG_VIDEO]; - case TrackAudio: - return _track_stamps_map[MSG_AUDIO]; - default: - return MAX(_track_stamps_map[MSG_VIDEO], _track_stamps_map[MSG_AUDIO]); - } - } + /** + * 获取当前时间戳 + */ + uint32_t getTimeStamp(TrackType trackType) override { + lock_guard lock(_mtx); + switch (trackType) { + case TrackVideo: + return _track_stamps_map[MSG_VIDEO]; + case TrackAudio: + return _track_stamps_map[MSG_AUDIO]; + default: + return MAX(_track_stamps_map[MSG_VIDEO], _track_stamps_map[MSG_AUDIO]); + } + } private: - /** - * 每次增减消费者都会触发该函数 - */ - void onReaderChanged(int size) { - //我们记录最后一次活动时间 - _reader_changed_ticker.resetTime(); - if (size != 0 || totalReaderCount() != 0) { - //还有消费者正在观看该流 - _async_emit_none_reader = false; - return; - } - _async_emit_none_reader = true; - } + /** + * 每次增减消费者都会触发该函数 + */ + void onReaderChanged(int size) { + //我们记录最后一次活动时间 + _reader_changed_ticker.resetTime(); + if (size != 0 || totalReaderCount() != 0) { + //还有消费者正在观看该流 + _async_emit_none_reader = false; + return; + } + _async_emit_none_reader = true; + } - /** - * 检查是否无人消费该流, - * 如果无人消费且超过一定时间会触发onNoneReader事件 - */ - void checkNoneReader() { - GET_CONFIG(int, stream_none_reader_delay, General::kStreamNoneReaderDelayMS); - if (_async_emit_none_reader && _reader_changed_ticker.elapsedTime() > stream_none_reader_delay) { - _async_emit_none_reader = false; - onNoneReader(); - } - } + /** + * 检查是否无人消费该流, + * 如果无人消费且超过一定时间会触发onNoneReader事件 + */ + void checkNoneReader() { + GET_CONFIG(int, stream_none_reader_delay, General::kStreamNoneReaderDelayMS); + if (_async_emit_none_reader && _reader_changed_ticker.elapsedTime() > stream_none_reader_delay) { + _async_emit_none_reader = false; + onNoneReader(); + } + } protected: - int _ring_size; - bool _async_emit_none_reader = false; - bool _have_video = false; - mutable recursive_mutex _mtx; - Ticker _reader_changed_ticker; - AMFValue _metadata; - RingBuffer::Ptr _ring; - unordered_map _track_stamps_map; - unordered_map _config_frame_map; + int _ring_size; + bool _async_emit_none_reader = false; + bool _have_video = false; + mutable recursive_mutex _mtx; + Ticker _reader_changed_ticker; + AMFValue _metadata; + RingBuffer::Ptr _ring; + unordered_map _track_stamps_map; + unordered_map _config_frame_map; }; } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpMediaSourceImp.h b/src/Rtmp/RtmpMediaSourceImp.h index fca06936..2261b003 100644 --- a/src/Rtmp/RtmpMediaSourceImp.h +++ b/src/Rtmp/RtmpMediaSourceImp.h @@ -45,46 +45,46 @@ using namespace toolkit; namespace mediakit { class RtmpMediaSourceImp: public RtmpMediaSource, public Demuxer::Listener , public MultiMediaSourceMuxer::Listener { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - /** - * 构造函数 - * @param vhost 虚拟主机 - * @param app 应用名 - * @param id 流id - * @param 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(); - _demuxer->setTrackListener(this); - } + /** + * 构造函数 + * @param vhost 虚拟主机 + * @param app 应用名 + * @param id 流id + * @param 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(); + _demuxer->setTrackListener(this); + } - ~RtmpMediaSourceImp() = default; + ~RtmpMediaSourceImp() = default; - /** - * 设置metadata - */ - void setMetaData(const AMFValue &metadata) override{ - _demuxer->loadMetaData(metadata); - RtmpMediaSource::setMetaData(metadata); - } + /** + * 设置metadata + */ + void setMetaData(const AMFValue &metadata) override{ + _demuxer->loadMetaData(metadata); + RtmpMediaSource::setMetaData(metadata); + } - /** - * 输入rtmp并解析 - */ - void onWrite(const RtmpPacket::Ptr &pkt,bool key_pos = true) override { - key_pos = _demuxer->inputRtmp(pkt); - RtmpMediaSource::onWrite(pkt,key_pos); - } + /** + * 输入rtmp并解析 + */ + void onWrite(const RtmpPacket::Ptr &pkt,bool key_pos = true) override { + key_pos = _demuxer->inputRtmp(pkt); + RtmpMediaSource::onWrite(pkt,key_pos); + } - /** - * 设置监听器 - * @param listener - */ - void setListener(const std::weak_ptr &listener) override { + /** + * 设置监听器 + * @param listener + */ + void setListener(const std::weak_ptr &listener) override { RtmpMediaSource::setListener(listener); if(_muxer){ - _muxer->setListener(listener); + _muxer->setListener(listener); } } @@ -95,42 +95,42 @@ public: return readerCount() + (_muxer ? _muxer->totalReaderCount() : 0); } - /** - * 设置协议转换 - * @param enableRtsp 是否转换成rtsp - * @param enableHls 是否转换成hls - * @param enableMP4 是否mp4录制 - */ - void setProtocolTranslation(bool enableRtsp, bool enableHls, bool enableMP4) { - //不重复生成rtmp - _muxer = std::make_shared(getVhost(), getApp(), getId(), _demuxer->getDuration(), enableRtsp, false, enableHls, enableMP4); - _muxer->setListener(getListener()); - _muxer->setTrackListener(this); + /** + * 设置协议转换 + * @param enableRtsp 是否转换成rtsp + * @param enableHls 是否转换成hls + * @param enableMP4 是否mp4录制 + */ + void setProtocolTranslation(bool enableRtsp, bool enableHls, bool enableMP4) { + //不重复生成rtmp + _muxer = std::make_shared(getVhost(), getApp(), getId(), _demuxer->getDuration(), enableRtsp, false, enableHls, enableMP4); + _muxer->setListener(getListener()); + _muxer->setTrackListener(this); for(auto &track : _demuxer->getTracks(false)){ _muxer->addTrack(track); track->addDelegate(_muxer); } - } + } - /** - * _demuxer触发的添加Track事件 - */ - void onAddTrack(const Track::Ptr &track) override { - if(_muxer){ - _muxer->addTrack(track); - track->addDelegate(_muxer); - } - } + /** + * _demuxer触发的添加Track事件 + */ + void onAddTrack(const Track::Ptr &track) override { + if(_muxer){ + _muxer->addTrack(track); + track->addDelegate(_muxer); + } + } - /** - * _muxer触发的所有Track就绪的事件 - */ - void onAllTrackReady() override{ - setTrackSource(_muxer); - } + /** + * _muxer触发的所有Track就绪的事件 + */ + void onAllTrackReady() override{ + setTrackSource(_muxer); + } private: - RtmpDemuxer::Ptr _demuxer; - MultiMediaSourceMuxer::Ptr _muxer; + RtmpDemuxer::Ptr _demuxer; + MultiMediaSourceMuxer::Ptr _muxer; }; } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpPlayer.cpp b/src/Rtmp/RtmpPlayer.cpp index 5251ca42..c3df0eba 100644 --- a/src/Rtmp/RtmpPlayer.cpp +++ b/src/Rtmp/RtmpPlayer.cpp @@ -38,35 +38,35 @@ RtmpPlayer::RtmpPlayer(const EventPoller::Ptr &poller) : TcpClient(poller) { } RtmpPlayer::~RtmpPlayer() { - DebugL << endl; + DebugL << endl; } void RtmpPlayer::teardown() { - if (alive()) { - shutdown(SockException(Err_shutdown,"teardown")); - } - _strApp.clear(); - _strStream.clear(); - _strTcUrl.clear(); - _pBeatTimer.reset(); - _pPlayTimer.reset(); - _pMediaTimer.reset(); - _iSeekTo = 0; - RtmpProtocol::reset(); + if (alive()) { + shutdown(SockException(Err_shutdown,"teardown")); + } + _strApp.clear(); + _strStream.clear(); + _strTcUrl.clear(); + _pBeatTimer.reset(); + _pPlayTimer.reset(); + _pMediaTimer.reset(); + _iSeekTo = 0; + RtmpProtocol::reset(); - CLEAR_ARR(_aiFistStamp); - CLEAR_ARR(_aiNowStamp); + CLEAR_ARR(_aiFistStamp); + CLEAR_ARR(_aiNowStamp); - lock_guard lck(_mtxOnResultCB); - _mapOnResultCB.clear(); - lock_guard lck2(_mtxOnStatusCB); - _dqOnStatusCB.clear(); + lock_guard lck(_mtxOnResultCB); + _mapOnResultCB.clear(); + lock_guard lck2(_mtxOnStatusCB); + _dqOnStatusCB.clear(); } void RtmpPlayer::play(const string &strUrl) { - teardown(); - string strHost = FindField(strUrl.data(), "://", "/"); - _strApp = FindField(strUrl.data(), (strHost + "/").data(), "/"); + teardown(); + string strHost = FindField(strUrl.data(), "://", "/"); + _strApp = FindField(strUrl.data(), (strHost + "/").data(), "/"); _strStream = FindField(strUrl.data(), (strHost + "/" + _strApp + "/").data(), NULL); _strTcUrl = string("rtmp://") + strHost + "/" + _strApp; @@ -74,48 +74,48 @@ void RtmpPlayer::play(const string &strUrl) { onPlayResult_l(SockException(Err_other,"rtmp url非法"),false); return; } - DebugL << strHost << " " << _strApp << " " << _strStream; + DebugL << strHost << " " << _strApp << " " << _strStream; - auto iPort = atoi(FindField(strHost.data(), ":", NULL).data()); - if (iPort <= 0) { + auto iPort = atoi(FindField(strHost.data(), ":", NULL).data()); + if (iPort <= 0) { //rtmp 默认端口1935 - iPort = 1935; - } else { + iPort = 1935; + } else { //服务器域名 - strHost = FindField(strHost.data(), NULL, ":"); - } - if(!(*this)[kNetAdapter].empty()){ - setNetAdapter((*this)[kNetAdapter]); - } + strHost = FindField(strHost.data(), NULL, ":"); + } + if(!(*this)[kNetAdapter].empty()){ + setNetAdapter((*this)[kNetAdapter]); + } - weak_ptr weakSelf= dynamic_pointer_cast(shared_from_this()); - float playTimeOutSec = (*this)[kTimeoutMS].as() / 1000.0; - _pPlayTimer.reset( new Timer(playTimeOutSec, [weakSelf]() { - auto strongSelf=weakSelf.lock(); - if(!strongSelf) { - return false; - } - strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtmp timeout"),false); - return false; - },getPoller())); + weak_ptr weakSelf= dynamic_pointer_cast(shared_from_this()); + float playTimeOutSec = (*this)[kTimeoutMS].as() / 1000.0; + _pPlayTimer.reset( new Timer(playTimeOutSec, [weakSelf]() { + auto strongSelf=weakSelf.lock(); + if(!strongSelf) { + return false; + } + strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtmp timeout"),false); + return false; + },getPoller())); - _metadata_got = false; - startConnect(strHost, iPort , playTimeOutSec); + _metadata_got = false; + startConnect(strHost, iPort , playTimeOutSec); } void RtmpPlayer::onErr(const SockException &ex){ //定时器_pPlayTimer为空后表明握手结束了 - onPlayResult_l(ex, !_pPlayTimer); + onPlayResult_l(ex, !_pPlayTimer); } void RtmpPlayer::onPlayResult_l(const SockException &ex , bool handshakeCompleted) { - WarnL << ex.getErrCode() << " " << ex.what(); + WarnL << ex.getErrCode() << " " << ex.what(); if(!ex){ //播放成功,恢复rtmp接收超时定时器 _mediaTicker.resetTime(); weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); int timeoutMS = (*this)[kMediaTimeoutMS].as(); - //创建rtmp数据接收超时检测定时器 + //创建rtmp数据接收超时检测定时器 _pMediaTimer.reset( new Timer(timeoutMS / 2000.0, [weakSelf,timeoutMS]() { auto strongSelf=weakSelf.lock(); if(!strongSelf) { @@ -130,110 +130,110 @@ void RtmpPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete },getPoller())); } - if (!handshakeCompleted) { - //开始播放阶段 - _pPlayTimer.reset(); - onPlayResult(ex); - } else if (ex) { - //播放成功后异常断开回调 - onShutdown(ex); - } else { - //恢复播放 - onResume(); - } + if (!handshakeCompleted) { + //开始播放阶段 + _pPlayTimer.reset(); + onPlayResult(ex); + } else if (ex) { + //播放成功后异常断开回调 + onShutdown(ex); + } else { + //恢复播放 + onResume(); + } - if(ex){ - teardown(); - } + if(ex){ + teardown(); + } } void RtmpPlayer::onConnect(const SockException &err){ - if(err.getErrCode() != Err_success) { - onPlayResult_l(err, false); - return; - } - weak_ptr weakSelf= dynamic_pointer_cast(shared_from_this()); - startClientSession([weakSelf](){ + if(err.getErrCode() != Err_success) { + onPlayResult_l(err, false); + return; + } + weak_ptr weakSelf= dynamic_pointer_cast(shared_from_this()); + startClientSession([weakSelf](){ auto strongSelf=weakSelf.lock(); - if(!strongSelf) { + if(!strongSelf) { return; } - strongSelf->send_connect(); - }); + strongSelf->send_connect(); + }); } void RtmpPlayer::onRecv(const Buffer::Ptr &pBuf){ - try { - onParseRtmp(pBuf->data(), pBuf->size()); - } catch (exception &e) { - SockException ex(Err_other, e.what()); + try { + onParseRtmp(pBuf->data(), pBuf->size()); + } catch (exception &e) { + SockException ex(Err_other, e.what()); //定时器_pPlayTimer为空后表明握手结束了 - onPlayResult_l(ex, !_pPlayTimer); - } + onPlayResult_l(ex, !_pPlayTimer); + } } void RtmpPlayer::pause(bool bPause) { - send_pause(bPause); + send_pause(bPause); } inline void RtmpPlayer::send_connect() { - AMFValue obj(AMF_OBJECT); - obj.set("app", _strApp); - obj.set("tcUrl", _strTcUrl); - //未使用代理 - obj.set("fpad", false); - //参考librtmp,什么作用? - obj.set("capabilities", 15); - //SUPPORT_VID_CLIENT_SEEK 支持seek - obj.set("videoFunction", 1); + AMFValue obj(AMF_OBJECT); + obj.set("app", _strApp); + obj.set("tcUrl", _strTcUrl); + //未使用代理 + obj.set("fpad", false); + //参考librtmp,什么作用? + obj.set("capabilities", 15); + //SUPPORT_VID_CLIENT_SEEK 支持seek + obj.set("videoFunction", 1); //只支持aac obj.set("audioCodecs", (double)(0x0400)); //只支持H264 obj.set("videoCodecs", (double)(0x0080)); - sendInvoke("connect", obj); - addOnResultCB([this](AMFDecoder &dec){ - //TraceL << "connect result"; - dec.load(); - auto val = dec.load(); - auto level = val["level"].as_string(); - auto code = val["code"].as_string(); - if(level != "status"){ - throw std::runtime_error(StrPrinter <<"connect 失败:" << level << " " << code << endl); - } - send_createStream(); - }); + sendInvoke("connect", obj); + addOnResultCB([this](AMFDecoder &dec){ + //TraceL << "connect result"; + dec.load(); + auto val = dec.load(); + auto level = val["level"].as_string(); + auto code = val["code"].as_string(); + if(level != "status"){ + throw std::runtime_error(StrPrinter <<"connect 失败:" << level << " " << code << endl); + } + send_createStream(); + }); } inline void RtmpPlayer::send_createStream() { - AMFValue obj(AMF_NULL); - sendInvoke("createStream", obj); - addOnResultCB([this](AMFDecoder &dec){ - //TraceL << "createStream result"; - dec.load(); - _ui32StreamId = dec.load(); - send_play(); - }); + AMFValue obj(AMF_NULL); + sendInvoke("createStream", obj); + addOnResultCB([this](AMFDecoder &dec){ + //TraceL << "createStream result"; + dec.load(); + _ui32StreamId = dec.load(); + send_play(); + }); } inline void RtmpPlayer::send_play() { - AMFEncoder enc; - enc << "play" << ++_iReqID << nullptr << _strStream << (double)_ui32StreamId; - sendRequest(MSG_CMD, enc.data()); - auto fun = [this](AMFValue &val){ - //TraceL << "play onStatus"; - auto level = val["level"].as_string(); - auto code = val["code"].as_string(); - if(level != "status"){ - throw std::runtime_error(StrPrinter <<"play 失败:" << level << " " << code << endl); - } - }; - addOnStatusCB(fun); - addOnStatusCB(fun); + AMFEncoder enc; + enc << "play" << ++_iReqID << nullptr << _strStream << (double)_ui32StreamId; + sendRequest(MSG_CMD, enc.data()); + auto fun = [this](AMFValue &val){ + //TraceL << "play onStatus"; + auto level = val["level"].as_string(); + auto code = val["code"].as_string(); + if(level != "status"){ + throw std::runtime_error(StrPrinter <<"play 失败:" << level << " " << code << endl); + } + }; + addOnStatusCB(fun); + addOnStatusCB(fun); } inline void RtmpPlayer::send_pause(bool bPause) { - AMFEncoder enc; - enc << "pause" << ++_iReqID << nullptr << bPause; - sendRequest(MSG_CMD, enc.data()); - auto fun = [this,bPause](AMFValue &val){ + AMFEncoder enc; + enc << "pause" << ++_iReqID << nullptr << bPause; + sendRequest(MSG_CMD, enc.data()); + auto fun = [this,bPause](AMFValue &val){ //TraceL << "pause onStatus"; auto level = val["level"].as_string(); auto code = val["code"].as_string(); @@ -250,147 +250,147 @@ inline void RtmpPlayer::send_pause(bool bPause) { _pMediaTimer.reset(); } } - }; - addOnStatusCB(fun); + }; + addOnStatusCB(fun); - _pBeatTimer.reset(); - if(bPause){ - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - _pBeatTimer.reset(new Timer((*this)[kBeatIntervalMS].as() / 1000.0,[weakSelf](){ - auto strongSelf = weakSelf.lock(); - if (!strongSelf){ - return false; - } - uint32_t timeStamp = ::time(NULL); - strongSelf->sendUserControl(CONTROL_PING_REQUEST, timeStamp); - return true; - },getPoller())); - } + _pBeatTimer.reset(); + if(bPause){ + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + _pBeatTimer.reset(new Timer((*this)[kBeatIntervalMS].as() / 1000.0,[weakSelf](){ + auto strongSelf = weakSelf.lock(); + if (!strongSelf){ + return false; + } + uint32_t timeStamp = ::time(NULL); + strongSelf->sendUserControl(CONTROL_PING_REQUEST, timeStamp); + return true; + },getPoller())); + } } void RtmpPlayer::onCmd_result(AMFDecoder &dec){ - auto iReqId = dec.load(); - lock_guard lck(_mtxOnResultCB); - auto it = _mapOnResultCB.find(iReqId); - if(it != _mapOnResultCB.end()){ - it->second(dec); - _mapOnResultCB.erase(it); - }else{ - WarnL << "unhandled _result"; - } + auto iReqId = dec.load(); + lock_guard lck(_mtxOnResultCB); + auto it = _mapOnResultCB.find(iReqId); + if(it != _mapOnResultCB.end()){ + it->second(dec); + _mapOnResultCB.erase(it); + }else{ + WarnL << "unhandled _result"; + } } void RtmpPlayer::onCmd_onStatus(AMFDecoder &dec) { - AMFValue val; - while(true){ - val = dec.load(); - if(val.type() == AMF_OBJECT){ - break; - } - } - if(val.type() != AMF_OBJECT){ - throw std::runtime_error("onStatus:the result object was not found"); - } + AMFValue val; + while(true){ + val = dec.load(); + if(val.type() == AMF_OBJECT){ + break; + } + } + if(val.type() != AMF_OBJECT){ + throw std::runtime_error("onStatus:the result object was not found"); + } lock_guard lck(_mtxOnStatusCB); - if(_dqOnStatusCB.size()){ - _dqOnStatusCB.front()(val); - _dqOnStatusCB.pop_front(); - }else{ - auto level = val["level"]; - auto code = val["code"].as_string(); - if(level.type() == AMF_STRING){ - if(level.as_string() != "status"){ - throw std::runtime_error(StrPrinter <<"onStatus 失败:" << level.as_string() << " " << code << endl); - } - } - //WarnL << "unhandled onStatus:" << code; + if(_dqOnStatusCB.size()){ + _dqOnStatusCB.front()(val); + _dqOnStatusCB.pop_front(); + }else{ + auto level = val["level"]; + auto code = val["code"].as_string(); + if(level.type() == AMF_STRING){ + if(level.as_string() != "status"){ + throw std::runtime_error(StrPrinter <<"onStatus 失败:" << level.as_string() << " " << code << endl); + } + } + //WarnL << "unhandled onStatus:" << code; } } void RtmpPlayer::onCmd_onMetaData(AMFDecoder &dec) { - //TraceL; - auto val = dec.load(); - if(!onCheckMeta(val)){ - throw std::runtime_error("onCheckMeta failed"); - } - _metadata_got = true; + //TraceL; + auto val = dec.load(); + if(!onCheckMeta(val)){ + throw std::runtime_error("onCheckMeta failed"); + } + _metadata_got = true; } void RtmpPlayer::onStreamDry(uint32_t ui32StreamId) { - //TraceL << ui32StreamId; - onPlayResult_l(SockException(Err_other,"rtmp stream dry"), true); + //TraceL << ui32StreamId; + onPlayResult_l(SockException(Err_other,"rtmp stream dry"), true); } void RtmpPlayer::onMediaData_l(const RtmpPacket::Ptr &packet) { - _mediaTicker.resetTime(); - if(!_pPlayTimer){ - //已经触发了onPlayResult事件,直接触发onMediaData事件 - onMediaData(packet); - return; - } + _mediaTicker.resetTime(); + if(!_pPlayTimer){ + //已经触发了onPlayResult事件,直接触发onMediaData事件 + onMediaData(packet); + return; + } - if(packet->isCfgFrame()){ - //输入配置帧以便初始化完成各个track - onMediaData(packet); - }else{ - //先触发onPlayResult事件,这个时候解码器才能初始化完毕 - onPlayResult_l(SockException(Err_success,"play rtmp success"), false); - //触发onPlayResult事件后,再把帧数据输入到解码器 - onMediaData(packet); - } + if(packet->isCfgFrame()){ + //输入配置帧以便初始化完成各个track + onMediaData(packet); + }else{ + //先触发onPlayResult事件,这个时候解码器才能初始化完毕 + onPlayResult_l(SockException(Err_success,"play rtmp success"), false); + //触发onPlayResult事件后,再把帧数据输入到解码器 + onMediaData(packet); + } } void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) { - typedef void (RtmpPlayer::*rtmp_func_ptr)(AMFDecoder &dec); - static unordered_map s_func_map; - static onceToken token([]() { - s_func_map.emplace("_error",&RtmpPlayer::onCmd_result); - s_func_map.emplace("_result",&RtmpPlayer::onCmd_result); - s_func_map.emplace("onStatus",&RtmpPlayer::onCmd_onStatus); - s_func_map.emplace("onMetaData",&RtmpPlayer::onCmd_onMetaData); - }, []() {}); + typedef void (RtmpPlayer::*rtmp_func_ptr)(AMFDecoder &dec); + static unordered_map s_func_map; + static onceToken token([]() { + s_func_map.emplace("_error",&RtmpPlayer::onCmd_result); + s_func_map.emplace("_result",&RtmpPlayer::onCmd_result); + s_func_map.emplace("onStatus",&RtmpPlayer::onCmd_onStatus); + s_func_map.emplace("onMetaData",&RtmpPlayer::onCmd_onMetaData); + }, []() {}); - switch (chunkData.typeId) { - case MSG_CMD: - case MSG_CMD3: - case MSG_DATA: - case MSG_DATA3: { - AMFDecoder dec(chunkData.strBuf, 0); - std::string type = dec.load(); - auto it = s_func_map.find(type); - if(it != s_func_map.end()){ - auto fun = it->second; - (this->*fun)(dec); - }else{ - WarnL << "can not support cmd:" << type; - } - } - break; - case MSG_AUDIO: - case MSG_VIDEO: { + switch (chunkData.typeId) { + case MSG_CMD: + case MSG_CMD3: + case MSG_DATA: + case MSG_DATA3: { + AMFDecoder dec(chunkData.strBuf, 0); + std::string type = dec.load(); + auto it = s_func_map.find(type); + if(it != s_func_map.end()){ + auto fun = it->second; + (this->*fun)(dec); + }else{ + WarnL << "can not support cmd:" << type; + } + } + break; + case MSG_AUDIO: + case MSG_VIDEO: { auto idx = chunkData.typeId%2; if (_aNowStampTicker[idx].elapsedTime() > 500) { - //计算播放进度时间轴用 + //计算播放进度时间轴用 _aiNowStamp[idx] = chunkData.timeStamp; } - if(!_metadata_got){ - if(!onCheckMeta(TitleMeta().getMetadata())){ - throw std::runtime_error("onCheckMeta failed"); - } - _metadata_got = true; - } - onMediaData_l(std::make_shared(std::move(chunkData))); - } - break; - default: - //WarnL << "unhandled message:" << (int) chunkData.typeId << hexdump(chunkData.strBuf.data(), chunkData.strBuf.size()); - break; - } + if(!_metadata_got){ + if(!onCheckMeta(TitleMeta().getMetadata())){ + throw std::runtime_error("onCheckMeta failed"); + } + _metadata_got = true; + } + onMediaData_l(std::make_shared(std::move(chunkData))); + } + break; + default: + //WarnL << "unhandled message:" << (int) chunkData.typeId << hexdump(chunkData.strBuf.data(), chunkData.strBuf.size()); + break; + } } uint32_t RtmpPlayer::getProgressMilliSecond() const{ - uint32_t iTime[2] = {0,0}; + uint32_t iTime[2] = {0,0}; for(auto i = 0 ;i < 2 ;i++){ iTime[i] = _aiNowStamp[i] - _aiFistStamp[i]; } @@ -407,7 +407,7 @@ void RtmpPlayer::seekToMilliSecond(uint32_t seekMS){ //TraceL << "seek result"; _aNowStampTicker[0].resetTime(); _aNowStampTicker[1].resetTime(); - int iTimeInc = seekMS - getProgressMilliSecond(); + int iTimeInc = seekMS - getProgressMilliSecond(); for(auto i = 0 ;i < 2 ;i++){ _aiFistStamp[i] = _aiNowStamp[i] + iTimeInc; _aiNowStamp[i] = _aiFistStamp[i]; diff --git a/src/Rtmp/RtmpPlayer.h b/src/Rtmp/RtmpPlayer.h index 10bc8ff1..c6d778e2 100644 --- a/src/Rtmp/RtmpPlayer.h +++ b/src/Rtmp/RtmpPlayer.h @@ -47,77 +47,77 @@ namespace mediakit { //实现了rtmp播放器协议部分的功能,及数据接收功能 class RtmpPlayer:public PlayerBase, public TcpClient, public RtmpProtocol{ public: - typedef std::shared_ptr Ptr; - RtmpPlayer(const EventPoller::Ptr &poller); - virtual ~RtmpPlayer(); + typedef std::shared_ptr Ptr; + RtmpPlayer(const EventPoller::Ptr &poller); + virtual ~RtmpPlayer(); - void play(const string &strUrl) override; - void pause(bool bPause) override; - void teardown() override; + void play(const string &strUrl) override; + void pause(bool bPause) override; + void teardown() override; protected: - virtual bool onCheckMeta(const AMFValue &val) =0; - virtual void onMediaData(const RtmpPacket::Ptr &chunkData) =0; - uint32_t getProgressMilliSecond() const; - void seekToMilliSecond(uint32_t ms); + virtual bool onCheckMeta(const AMFValue &val) =0; + virtual void onMediaData(const RtmpPacket::Ptr &chunkData) =0; + uint32_t getProgressMilliSecond() const; + void seekToMilliSecond(uint32_t ms); protected: - void onMediaData_l(const RtmpPacket::Ptr &chunkData); - //在获取config帧后才触发onPlayResult_l(而不是收到play命令回复),所以此时所有track都初始化完毕了 - void onPlayResult_l(const SockException &ex, bool handshakeCompleted); + void onMediaData_l(const RtmpPacket::Ptr &chunkData); + //在获取config帧后才触发onPlayResult_l(而不是收到play命令回复),所以此时所有track都初始化完毕了 + void onPlayResult_l(const SockException &ex, bool handshakeCompleted); - //form Tcpclient - void onRecv(const Buffer::Ptr &pBuf) override; - void onConnect(const SockException &err) override; - void onErr(const SockException &ex) override; - //from RtmpProtocol - void onRtmpChunk(RtmpPacket &chunkData) override; - void onStreamDry(uint32_t ui32StreamId) override; + //form Tcpclient + void onRecv(const Buffer::Ptr &pBuf) override; + void onConnect(const SockException &err) override; + void onErr(const SockException &ex) override; + //from RtmpProtocol + void onRtmpChunk(RtmpPacket &chunkData) override; + void onStreamDry(uint32_t ui32StreamId) override; void onSendRawData(const Buffer::Ptr &buffer) override{ send(buffer); } - template - inline void addOnResultCB(const FUN &fun) { - lock_guard lck(_mtxOnResultCB); - _mapOnResultCB.emplace(_iReqID, fun); - } - template - inline void addOnStatusCB(const FUN &fun) { - lock_guard lck(_mtxOnStatusCB); - _dqOnStatusCB.emplace_back(fun); - } + template + inline void addOnResultCB(const FUN &fun) { + lock_guard lck(_mtxOnResultCB); + _mapOnResultCB.emplace(_iReqID, fun); + } + template + inline void addOnStatusCB(const FUN &fun) { + lock_guard lck(_mtxOnStatusCB); + _dqOnStatusCB.emplace_back(fun); + } - void onCmd_result(AMFDecoder &dec); - void onCmd_onStatus(AMFDecoder &dec); - void onCmd_onMetaData(AMFDecoder &dec); + void onCmd_result(AMFDecoder &dec); + void onCmd_onStatus(AMFDecoder &dec); + void onCmd_onMetaData(AMFDecoder &dec); - inline void send_connect(); - inline void send_createStream(); - inline void send_play(); - inline void send_pause(bool bPause); + inline void send_connect(); + inline void send_createStream(); + inline void send_play(); + inline void send_pause(bool bPause); private: - string _strApp; - string _strStream; - string _strTcUrl; - bool _bPaused = false; + string _strApp; + string _strStream; + string _strTcUrl; + bool _bPaused = false; - unordered_map > _mapOnResultCB; - recursive_mutex _mtxOnResultCB; - deque > _dqOnStatusCB; - recursive_mutex _mtxOnStatusCB; + unordered_map > _mapOnResultCB; + recursive_mutex _mtxOnResultCB; + deque > _dqOnStatusCB; + recursive_mutex _mtxOnStatusCB; - //超时功能实现 - Ticker _mediaTicker; - std::shared_ptr _pMediaTimer; - std::shared_ptr _pPlayTimer; - //心跳定时器 - std::shared_ptr _pBeatTimer; + //超时功能实现 + Ticker _mediaTicker; + std::shared_ptr _pMediaTimer; + std::shared_ptr _pPlayTimer; + //心跳定时器 + std::shared_ptr _pBeatTimer; - //播放进度控制 - uint32_t _iSeekTo = 0; - uint32_t _aiFistStamp[2] = { 0, 0 }; - uint32_t _aiNowStamp[2] = { 0, 0 }; - Ticker _aNowStampTicker[2]; - bool _metadata_got = false; + //播放进度控制 + uint32_t _iSeekTo = 0; + uint32_t _aiFistStamp[2] = { 0, 0 }; + uint32_t _aiNowStamp[2] = { 0, 0 }; + Ticker _aNowStampTicker[2]; + bool _metadata_got = false; }; } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpPlayerImp.h b/src/Rtmp/RtmpPlayerImp.h index e90acc43..0dc367de 100644 --- a/src/Rtmp/RtmpPlayerImp.h +++ b/src/Rtmp/RtmpPlayerImp.h @@ -73,7 +73,7 @@ private: return true; } void onMediaData(const RtmpPacket::Ptr &chunkData) override { - if(_pRtmpMediaSrc){ + if(_pRtmpMediaSrc){ if(!_set_meta_data && !chunkData->isCfgFrame()){ _set_meta_data = true; _pRtmpMediaSrc->setMetaData(TitleMeta().getMetadata()); @@ -81,7 +81,7 @@ private: _pRtmpMediaSrc->onWrite(chunkData); } if(!_delegate){ - //这个流没有metadata + //这个流没有metadata _delegate.reset(new RtmpDemuxer()); } _delegate->inputRtmp(chunkData); diff --git a/src/Rtmp/RtmpProtocol.cpp b/src/Rtmp/RtmpProtocol.cpp index 4de21a47..03e30cc9 100644 --- a/src/Rtmp/RtmpProtocol.cpp +++ b/src/Rtmp/RtmpProtocol.cpp @@ -36,28 +36,28 @@ using namespace toolkit; #include static string openssl_HMACsha256(const void *key,unsigned int key_len, - const void *data,unsigned int data_len){ - std::shared_ptr out(new char[32],[](char *ptr){delete [] ptr;}); - unsigned int out_len; + const void *data,unsigned int data_len){ + std::shared_ptr out(new char[32],[](char *ptr){delete [] ptr;}); + unsigned int out_len; #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L) //openssl 1.1.0新增api,老版本api作废 - HMAC_CTX *ctx = HMAC_CTX_new(); - HMAC_CTX_reset(ctx); - HMAC_Init_ex(ctx, key, key_len, EVP_sha256(), NULL); - HMAC_Update(ctx, (unsigned char*)data, data_len); - HMAC_Final(ctx, (unsigned char *)out.get(), &out_len); - HMAC_CTX_reset(ctx); - HMAC_CTX_free(ctx); + HMAC_CTX *ctx = HMAC_CTX_new(); + HMAC_CTX_reset(ctx); + HMAC_Init_ex(ctx, key, key_len, EVP_sha256(), NULL); + HMAC_Update(ctx, (unsigned char*)data, data_len); + HMAC_Final(ctx, (unsigned char *)out.get(), &out_len); + HMAC_CTX_reset(ctx); + HMAC_CTX_free(ctx); #else - HMAC_CTX ctx; - HMAC_CTX_init(&ctx); - HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL); - HMAC_Update(&ctx, (unsigned char*)data, data_len); - HMAC_Final(&ctx, (unsigned char *)out.get(), &out_len); - HMAC_CTX_cleanup(&ctx); + HMAC_CTX ctx; + HMAC_CTX_init(&ctx); + HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL); + HMAC_Update(&ctx, (unsigned char*)data, data_len); + HMAC_Final(&ctx, (unsigned char *)out.get(), &out_len); + HMAC_CTX_cleanup(&ctx); #endif //defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L) - return string(out.get(),out_len); + return string(out.get(),out_len); } #endif //ENABLE_OPENSSL @@ -74,117 +74,117 @@ static string openssl_HMACsha256(const void *key,unsigned int key_len, namespace mediakit { RtmpProtocol::RtmpProtocol() { - _nextHandle = [this](){ - handle_C0C1(); - }; + _nextHandle = [this](){ + handle_C0C1(); + }; } RtmpProtocol::~RtmpProtocol() { - reset(); + reset(); } void RtmpProtocol::reset() { - ////////////ChunkSize//////////// - _iChunkLenIn = DEFAULT_CHUNK_LEN; - _iChunkLenOut = DEFAULT_CHUNK_LEN; - ////////////Acknowledgement//////////// - _ui32ByteSent = 0; - _ui32LastSent = 0; - _ui32WinSize = 0; - ///////////PeerBandwidth/////////// - _ui32Bandwidth = 2500000; - _ui8LimitType = 2; - ////////////Chunk//////////// - _mapChunkData.clear(); - _iNowStreamID = 0; - _iNowChunkID = 0; - //////////Invoke Request////////// - _iReqID = 0; - //////////Rtmp parser////////// - _strRcvBuf.clear(); - _ui32StreamId = STREAM_CONTROL; - _nextHandle = [this]() { - handle_C0C1(); - }; + ////////////ChunkSize//////////// + _iChunkLenIn = DEFAULT_CHUNK_LEN; + _iChunkLenOut = DEFAULT_CHUNK_LEN; + ////////////Acknowledgement//////////// + _ui32ByteSent = 0; + _ui32LastSent = 0; + _ui32WinSize = 0; + ///////////PeerBandwidth/////////// + _ui32Bandwidth = 2500000; + _ui8LimitType = 2; + ////////////Chunk//////////// + _mapChunkData.clear(); + _iNowStreamID = 0; + _iNowChunkID = 0; + //////////Invoke Request////////// + _iReqID = 0; + //////////Rtmp parser////////// + _strRcvBuf.clear(); + _ui32StreamId = STREAM_CONTROL; + _nextHandle = [this]() { + handle_C0C1(); + }; } void RtmpProtocol::sendAcknowledgement(uint32_t ui32Size) { - std::string control; - uint32_t stream = htonl(ui32Size); - control.append((char *) &stream, 4); - sendRequest(MSG_ACK, control); + std::string control; + uint32_t stream = htonl(ui32Size); + control.append((char *) &stream, 4); + sendRequest(MSG_ACK, control); } void RtmpProtocol::sendAcknowledgementSize(uint32_t ui32Size) { - uint32_t windowSize = htonl(ui32Size); - std::string set_windowSize((char *) &windowSize, 4); - sendRequest(MSG_WIN_SIZE, set_windowSize); + uint32_t windowSize = htonl(ui32Size); + std::string set_windowSize((char *) &windowSize, 4); + sendRequest(MSG_WIN_SIZE, set_windowSize); } void RtmpProtocol::sendPeerBandwidth(uint32_t ui32Size) { - uint32_t peerBandwidth = htonl(ui32Size); - std::string set_peerBandwidth((char *) &peerBandwidth, 4); - set_peerBandwidth.push_back((char) 0x02); - sendRequest(MSG_SET_PEER_BW, set_peerBandwidth); + uint32_t peerBandwidth = htonl(ui32Size); + std::string set_peerBandwidth((char *) &peerBandwidth, 4); + set_peerBandwidth.push_back((char) 0x02); + sendRequest(MSG_SET_PEER_BW, set_peerBandwidth); } void RtmpProtocol::sendChunkSize(uint32_t ui32Size) { - uint32_t len = htonl(ui32Size); - std::string set_chunk((char *) &len, 4); - sendRequest(MSG_SET_CHUNK, set_chunk); - _iChunkLenOut = ui32Size; + uint32_t len = htonl(ui32Size); + std::string set_chunk((char *) &len, 4); + sendRequest(MSG_SET_CHUNK, set_chunk); + _iChunkLenOut = ui32Size; } void RtmpProtocol::sendPingRequest(uint32_t ui32TimeStamp) { - sendUserControl(CONTROL_PING_REQUEST, ui32TimeStamp); + sendUserControl(CONTROL_PING_REQUEST, ui32TimeStamp); } void RtmpProtocol::sendPingResponse(uint32_t ui32TimeStamp) { - sendUserControl(CONTROL_PING_RESPONSE, ui32TimeStamp); + sendUserControl(CONTROL_PING_RESPONSE, ui32TimeStamp); } void RtmpProtocol::sendSetBufferLength(uint32_t ui32StreamId, - uint32_t ui32Length) { - std::string control; - ui32StreamId = htonl(ui32StreamId); - control.append((char *) &ui32StreamId, 4); - ui32Length = htonl(ui32Length); - control.append((char *) &ui32Length, 4); - sendUserControl(CONTROL_SETBUFFER, control); + uint32_t ui32Length) { + std::string control; + ui32StreamId = htonl(ui32StreamId); + control.append((char *) &ui32StreamId, 4); + ui32Length = htonl(ui32Length); + control.append((char *) &ui32Length, 4); + sendUserControl(CONTROL_SETBUFFER, control); } void RtmpProtocol::sendUserControl(uint16_t ui16EventType, - uint32_t ui32EventData) { - std::string control; - uint16_t type = htons(ui16EventType); - control.append((char *) &type, 2); - uint32_t stream = htonl(ui32EventData); - control.append((char *) &stream, 4); - sendRequest(MSG_USER_CONTROL, control); + uint32_t ui32EventData) { + std::string control; + uint16_t type = htons(ui16EventType); + control.append((char *) &type, 2); + uint32_t stream = htonl(ui32EventData); + control.append((char *) &stream, 4); + sendRequest(MSG_USER_CONTROL, control); } void RtmpProtocol::sendUserControl(uint16_t ui16EventType, - const string& strEventData) { - std::string control; - uint16_t type = htons(ui16EventType); - control.append((char *) &type, 2); - control.append(strEventData); - sendRequest(MSG_USER_CONTROL, control); + const string& strEventData) { + std::string control; + uint16_t type = htons(ui16EventType); + control.append((char *) &type, 2); + control.append(strEventData); + sendRequest(MSG_USER_CONTROL, control); } void RtmpProtocol::sendResponse(int iType, const string& str) { - if(!_bDataStarted && (iType == MSG_DATA)){ - _bDataStarted = true; - } - sendRtmp(iType, _iNowStreamID, str, 0, _bDataStarted ? CHUNK_CLIENT_REQUEST_AFTER : CHUNK_CLIENT_REQUEST_BEFORE); + if(!_bDataStarted && (iType == MSG_DATA)){ + _bDataStarted = true; + } + sendRtmp(iType, _iNowStreamID, str, 0, _bDataStarted ? CHUNK_CLIENT_REQUEST_AFTER : CHUNK_CLIENT_REQUEST_BEFORE); } void RtmpProtocol::sendInvoke(const string& strCmd, const AMFValue& val) { - AMFEncoder enc; - enc << strCmd << ++_iReqID << val; - sendRequest(MSG_CMD, enc.data()); + AMFEncoder enc; + enc << strCmd << ++_iReqID << val; + sendRequest(MSG_CMD, enc.data()); } void RtmpProtocol::sendRequest(int iCmd, const string& str) { - sendRtmp(iCmd, _ui32StreamId, str, 0, CHUNK_SERVER_REQUEST); + sendRtmp(iCmd, _ui32StreamId, str, 0, CHUNK_SERVER_REQUEST); } class BufferPartial : public Buffer { @@ -220,15 +220,15 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, auto strErr = StrPrinter << "不支持发送该类型的块流 ID:" << iChunkId << endl; throw std::runtime_error(strErr); } - //是否有扩展时间戳 + //是否有扩展时间戳 bool bExtStamp = ui32TimeStamp >= 0xFFFFFF; //rtmp头 - BufferRaw::Ptr bufferHeader = obtainBuffer(); - bufferHeader->setCapacity(sizeof(RtmpHeader)); - bufferHeader->setSize(sizeof(RtmpHeader)); - //对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题 - RtmpHeader *header = (RtmpHeader*) bufferHeader->data(); + BufferRaw::Ptr bufferHeader = obtainBuffer(); + bufferHeader->setCapacity(sizeof(RtmpHeader)); + bufferHeader->setSize(sizeof(RtmpHeader)); + //对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题 + RtmpHeader *header = (RtmpHeader*) bufferHeader->data(); header->flags = (iChunkId & 0x3f) | (0 << 6); header->typeId = ui8Type; set_be24(header->timeStamp, bExtStamp ? 0xFFFFFF : ui32TimeStamp); @@ -238,23 +238,23 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, onSendRawData(bufferHeader); //扩展时间戳字段 - BufferRaw::Ptr bufferExtStamp; + BufferRaw::Ptr bufferExtStamp; if (bExtStamp) { //生成扩展时间戳 - bufferExtStamp = obtainBuffer(); - bufferExtStamp->setCapacity(4); - bufferExtStamp->setSize(4); - set_be32(bufferExtStamp->data(), ui32TimeStamp); - } + bufferExtStamp = obtainBuffer(); + bufferExtStamp->setCapacity(4); + bufferExtStamp->setSize(4); + set_be32(bufferExtStamp->data(), ui32TimeStamp); + } - //生成一个字节的flag,标明是什么chunkId - BufferRaw::Ptr bufferFlags = obtainBuffer(); - bufferFlags->setCapacity(1); - bufferFlags->setSize(1); - bufferFlags->data()[0] = (iChunkId & 0x3f) | (3 << 6); + //生成一个字节的flag,标明是什么chunkId + BufferRaw::Ptr bufferFlags = obtainBuffer(); + bufferFlags->setCapacity(1); + bufferFlags->setSize(1); + bufferFlags->data()[0] = (iChunkId & 0x3f) | (3 << 6); size_t offset = 0; - uint32_t totalSize = sizeof(RtmpHeader); + uint32_t totalSize = sizeof(RtmpHeader); while (offset < buf->size()) { if (offset) { onSendRawData(bufferFlags); @@ -279,122 +279,122 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, void RtmpProtocol::onParseRtmp(const char *pcRawData, int iSize) { - _strRcvBuf.append(pcRawData, iSize); - auto cb = _nextHandle; - cb(); + _strRcvBuf.append(pcRawData, iSize); + auto cb = _nextHandle; + cb(); } ////for client//// void RtmpProtocol::startClientSession(const function &callBack) { - //发送 C0C1 - char handshake_head = HANDSHAKE_PLAINTEXT; - onSendRawData(obtainBuffer(&handshake_head, 1)); - RtmpHandshake c1(0); - onSendRawData(obtainBuffer((char *) (&c1), sizeof(c1))); - _nextHandle = [this,callBack]() { - //等待 S0+S1+S2 - handle_S0S1S2(callBack); - }; + //发送 C0C1 + char handshake_head = HANDSHAKE_PLAINTEXT; + onSendRawData(obtainBuffer(&handshake_head, 1)); + RtmpHandshake c1(0); + onSendRawData(obtainBuffer((char *) (&c1), sizeof(c1))); + _nextHandle = [this,callBack]() { + //等待 S0+S1+S2 + handle_S0S1S2(callBack); + }; } void RtmpProtocol::handle_S0S1S2(const function &callBack) { - if (_strRcvBuf.size() < 1 + 2 * C1_HANDSHARK_SIZE) { - //数据不够 - return; - } - if (_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) { - throw std::runtime_error("only plaintext[0x03] handshake supported"); - } - //发送 C2 - const char *pcC2 = _strRcvBuf.data() + 1; - onSendRawData(obtainBuffer(pcC2, C1_HANDSHARK_SIZE)); - _strRcvBuf.erase(0, 1 + 2 * C1_HANDSHARK_SIZE); - //握手结束 - _nextHandle = [this]() { - //握手结束并且开始进入解析命令模式 - handle_rtmp(); - }; - callBack(); + if (_strRcvBuf.size() < 1 + 2 * C1_HANDSHARK_SIZE) { + //数据不够 + return; + } + if (_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) { + throw std::runtime_error("only plaintext[0x03] handshake supported"); + } + //发送 C2 + const char *pcC2 = _strRcvBuf.data() + 1; + onSendRawData(obtainBuffer(pcC2, C1_HANDSHARK_SIZE)); + _strRcvBuf.erase(0, 1 + 2 * C1_HANDSHARK_SIZE); + //握手结束 + _nextHandle = [this]() { + //握手结束并且开始进入解析命令模式 + handle_rtmp(); + }; + callBack(); } ////for server //// void RtmpProtocol::handle_C0C1() { - if (_strRcvBuf.size() < 1 + C1_HANDSHARK_SIZE) { - //need more data! - return; - } - if (_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) { - throw std::runtime_error("only plaintext[0x03] handshake supported"); - } - if(memcmp(_strRcvBuf.data() + 5,"\x00\x00\x00\x00",4) ==0 ){ - //simple handsharke - handle_C1_simple(); - }else{ + if (_strRcvBuf.size() < 1 + C1_HANDSHARK_SIZE) { + //need more data! + return; + } + if (_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) { + throw std::runtime_error("only plaintext[0x03] handshake supported"); + } + if(memcmp(_strRcvBuf.data() + 5,"\x00\x00\x00\x00",4) ==0 ){ + //simple handsharke + handle_C1_simple(); + }else{ #ifdef ENABLE_OPENSSL - //complex handsharke - handle_C1_complex(); + //complex handsharke + handle_C1_complex(); #else - WarnL << "未打开ENABLE_OPENSSL宏,复杂握手采用简单方式处理,flash播放器可能无法播放!"; - handle_C1_simple(); + WarnL << "未打开ENABLE_OPENSSL宏,复杂握手采用简单方式处理,flash播放器可能无法播放!"; + handle_C1_simple(); #endif//ENABLE_OPENSSL - } - _strRcvBuf.erase(0, 1 + C1_HANDSHARK_SIZE); + } + _strRcvBuf.erase(0, 1 + C1_HANDSHARK_SIZE); } void RtmpProtocol::handle_C1_simple(){ - //发送S0 - char handshake_head = HANDSHAKE_PLAINTEXT; - onSendRawData(obtainBuffer(&handshake_head, 1)); - //发送S1 - RtmpHandshake s1(0); - onSendRawData(obtainBuffer((char *) &s1, C1_HANDSHARK_SIZE)); - //发送S2 - onSendRawData(obtainBuffer(_strRcvBuf.data() + 1, C1_HANDSHARK_SIZE)); - //等待C2 - _nextHandle = [this]() { - handle_C2(); - }; + //发送S0 + char handshake_head = HANDSHAKE_PLAINTEXT; + onSendRawData(obtainBuffer(&handshake_head, 1)); + //发送S1 + RtmpHandshake s1(0); + onSendRawData(obtainBuffer((char *) &s1, C1_HANDSHARK_SIZE)); + //发送S2 + onSendRawData(obtainBuffer(_strRcvBuf.data() + 1, C1_HANDSHARK_SIZE)); + //等待C2 + _nextHandle = [this]() { + handle_C2(); + }; } #ifdef ENABLE_OPENSSL void RtmpProtocol::handle_C1_complex(){ - //参考自:http://blog.csdn.net/win_lin/article/details/13006803 - //skip c0,time,version - const char *c1_start = _strRcvBuf.data() + 1; - const char *schema_start = c1_start + 8; - char *digest_start; - try{ - /* c1s1 schema0 - time: 4bytes - version: 4bytes - key: 764bytes - digest: 764bytes - */ - auto digest = get_C1_digest((uint8_t *)schema_start + C1_SCHEMA_SIZE,&digest_start); - string c1_joined(c1_start,C1_HANDSHARK_SIZE); - c1_joined.erase(digest_start - c1_start , C1_DIGEST_SIZE ); - check_C1_Digest(digest,c1_joined); + //参考自:http://blog.csdn.net/win_lin/article/details/13006803 + //skip c0,time,version + const char *c1_start = _strRcvBuf.data() + 1; + const char *schema_start = c1_start + 8; + char *digest_start; + try{ + /* c1s1 schema0 + time: 4bytes + version: 4bytes + key: 764bytes + digest: 764bytes + */ + auto digest = get_C1_digest((uint8_t *)schema_start + C1_SCHEMA_SIZE,&digest_start); + string c1_joined(c1_start,C1_HANDSHARK_SIZE); + c1_joined.erase(digest_start - c1_start , C1_DIGEST_SIZE ); + check_C1_Digest(digest,c1_joined); - send_complex_S0S1S2(0,digest); + send_complex_S0S1S2(0,digest); // InfoL << "schema0"; - }catch(std::exception &ex){ - //貌似flash从来都不用schema1 + }catch(std::exception &ex){ + //貌似flash从来都不用schema1 // WarnL << "try rtmp complex schema0 failed:" << ex.what(); - try{ - /* c1s1 schema1 - time: 4bytes - version: 4bytes - digest: 764bytes - key: 764bytes - */ - auto digest = get_C1_digest((uint8_t *)schema_start,&digest_start); - string c1_joined(c1_start,C1_HANDSHARK_SIZE); - c1_joined.erase(digest_start - c1_start , C1_DIGEST_SIZE ); - check_C1_Digest(digest,c1_joined); + try{ + /* c1s1 schema1 + time: 4bytes + version: 4bytes + digest: 764bytes + key: 764bytes + */ + auto digest = get_C1_digest((uint8_t *)schema_start,&digest_start); + string c1_joined(c1_start,C1_HANDSHARK_SIZE); + c1_joined.erase(digest_start - c1_start , C1_DIGEST_SIZE ); + check_C1_Digest(digest,c1_joined); - send_complex_S0S1S2(1,digest); + send_complex_S0S1S2(1,digest); // InfoL << "schema1"; - }catch(std::exception &ex){ + }catch(std::exception &ex){ // WarnL << "try rtmp complex schema1 failed:" << ex.what(); - handle_C1_simple(); - } - } + handle_C1_simple(); + } + } } #if !defined(u_int8_t) @@ -424,353 +424,353 @@ static u_int8_t FPKey[] = { 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE }; // 62 void RtmpProtocol::check_C1_Digest(const string &digest,const string &data){ - auto sha256 = openssl_HMACsha256(FPKey,C1_FPKEY_SIZE,data.data(),data.size()); - if(sha256 != digest){ - throw std::runtime_error("digest mismatched"); - }else{ - InfoL << "check rtmp complex handshark success!"; - } + auto sha256 = openssl_HMACsha256(FPKey,C1_FPKEY_SIZE,data.data(),data.size()); + if(sha256 != digest){ + throw std::runtime_error("digest mismatched"); + }else{ + InfoL << "check rtmp complex handshark success!"; + } } string RtmpProtocol::get_C1_digest(const uint8_t *ptr,char **digestPos){ - /* 764bytes digest结构 - offset: 4bytes - random-data: (offset)bytes - digest-data: 32bytes - random-data: (764-4-offset-32)bytes - */ - int offset = 0; - for(int i=0;i> 6]; - _iNowChunkID = flags & 0x3f; - switch (_iNowChunkID) { - case 0: { - //0 值表示二字节形式,并且 ID 范围 64 - 319 - //(第二个字节 + 64)。 - if (_strRcvBuf.size() < 2) { - //need more data - return; - } - _iNowChunkID = 64 + (uint8_t) (_strRcvBuf[1]); - iOffset = 1; - } - break; - case 1: { - //1 值表示三字节形式,并且 ID 范围为 64 - 65599 - //((第三个字节) * 256 + 第二个字节 + 64)。 - if (_strRcvBuf.size() < 3) { - //need more data - return; - } - _iNowChunkID = 64 + ((uint8_t) (_strRcvBuf[2]) << 8) + (uint8_t) (_strRcvBuf[1]); - iOffset = 2; - } - break; - default: - //带有 2 值的块流 ID 被保留,用于下层协议控制消息和命令。 - break; - } + while (!_strRcvBuf.empty()) { + uint8_t flags = _strRcvBuf[0]; + int iOffset = 0; + static const size_t HEADER_LENGTH[] = { 12, 8, 4, 1 }; + size_t iHeaderLen = HEADER_LENGTH[flags >> 6]; + _iNowChunkID = flags & 0x3f; + switch (_iNowChunkID) { + case 0: { + //0 值表示二字节形式,并且 ID 范围 64 - 319 + //(第二个字节 + 64)。 + if (_strRcvBuf.size() < 2) { + //need more data + return; + } + _iNowChunkID = 64 + (uint8_t) (_strRcvBuf[1]); + iOffset = 1; + } + break; + case 1: { + //1 值表示三字节形式,并且 ID 范围为 64 - 65599 + //((第三个字节) * 256 + 第二个字节 + 64)。 + if (_strRcvBuf.size() < 3) { + //need more data + return; + } + _iNowChunkID = 64 + ((uint8_t) (_strRcvBuf[2]) << 8) + (uint8_t) (_strRcvBuf[1]); + iOffset = 2; + } + break; + default: + //带有 2 值的块流 ID 被保留,用于下层协议控制消息和命令。 + break; + } - if (_strRcvBuf.size() < iHeaderLen + iOffset) { - //need more data - return; - } - RtmpHeader &header = *((RtmpHeader *) (_strRcvBuf.data() + iOffset)); - auto &chunkData = _mapChunkData[_iNowChunkID]; - chunkData.chunkId = _iNowChunkID; - switch (iHeaderLen) { - case 12: + if (_strRcvBuf.size() < iHeaderLen + iOffset) { + //need more data + return; + } + RtmpHeader &header = *((RtmpHeader *) (_strRcvBuf.data() + iOffset)); + auto &chunkData = _mapChunkData[_iNowChunkID]; + chunkData.chunkId = _iNowChunkID; + switch (iHeaderLen) { + case 12: chunkData.hasAbsStamp = true; - chunkData.streamId = load_le32(header.streamId); - case 8: - chunkData.bodySize = load_be24(header.bodySize); - chunkData.typeId = header.typeId; - case 4: - chunkData.deltaStamp = load_be24(header.timeStamp); + chunkData.streamId = load_le32(header.streamId); + case 8: + chunkData.bodySize = load_be24(header.bodySize); + chunkData.typeId = header.typeId; + case 4: + chunkData.deltaStamp = load_be24(header.timeStamp); chunkData.hasExtStamp = chunkData.deltaStamp == 0xFFFFFF; - } - + } + if (chunkData.hasExtStamp) { - if (_strRcvBuf.size() < iHeaderLen + iOffset + 4) { - //need more data - return; - } + if (_strRcvBuf.size() < iHeaderLen + iOffset + 4) { + //need more data + return; + } chunkData.deltaStamp = load_be32(_strRcvBuf.data() + iOffset + iHeaderLen); - iOffset += 4; - } - + iOffset += 4; + } + if (chunkData.bodySize < chunkData.strBuf.size()) { - throw std::runtime_error("非法的bodySize"); - } + throw std::runtime_error("非法的bodySize"); + } + + auto iMore = min(_iChunkLenIn, chunkData.bodySize - chunkData.strBuf.size()); + if (_strRcvBuf.size() < iHeaderLen + iOffset + iMore) { + //need more data + return; + } - auto iMore = min(_iChunkLenIn, chunkData.bodySize - chunkData.strBuf.size()); - if (_strRcvBuf.size() < iHeaderLen + iOffset + iMore) { - //need more data - return; - } - chunkData.strBuf.append(_strRcvBuf, iHeaderLen + iOffset, iMore); - _strRcvBuf.erase(0, iHeaderLen + iOffset + iMore); + _strRcvBuf.erase(0, iHeaderLen + iOffset + iMore); - if (chunkData.strBuf.size() == chunkData.bodySize) { + if (chunkData.strBuf.size() == chunkData.bodySize) { //frame is ready _iNowStreamID = chunkData.streamId; chunkData.timeStamp = chunkData.deltaStamp + (chunkData.hasAbsStamp ? 0 : chunkData.timeStamp); - if(chunkData.bodySize){ - handle_rtmpChunk(chunkData); - } - chunkData.strBuf.clear(); + if(chunkData.bodySize){ + handle_rtmpChunk(chunkData); + } + chunkData.strBuf.clear(); chunkData.hasAbsStamp = false; chunkData.hasExtStamp = false; chunkData.deltaStamp = 0; - } - } + } + } } void RtmpProtocol::handle_rtmpChunk(RtmpPacket& chunkData) { - switch (chunkData.typeId) { - case MSG_ACK: { - if (chunkData.strBuf.size() < 4) { - throw std::runtime_error("MSG_ACK: Not enough data"); - } - //auto bytePeerRecv = load_be32(&chunkData.strBuf[0]); - //TraceL << "MSG_ACK:" << bytePeerRecv; - } - break; - case MSG_SET_CHUNK: { - if (chunkData.strBuf.size() < 4) { - throw std::runtime_error("MSG_SET_CHUNK :Not enough data"); - } - _iChunkLenIn = load_be32(&chunkData.strBuf[0]); - TraceL << "MSG_SET_CHUNK:" << _iChunkLenIn; - } - break; - case MSG_USER_CONTROL: { - //user control message - if (chunkData.strBuf.size() < 2) { - throw std::runtime_error("MSG_USER_CONTROL: Not enough data."); - } - uint16_t event_type = load_be16(&chunkData.strBuf[0]); - chunkData.strBuf.erase(0, 2); - switch (event_type) { - case CONTROL_PING_REQUEST: { - if (chunkData.strBuf.size() < 4) { - throw std::runtime_error("CONTROL_PING_REQUEST: Not enough data."); - } - uint32_t timeStamp = load_be32(&chunkData.strBuf[0]); - //TraceL << "CONTROL_PING_REQUEST:" << timeStamp; - sendUserControl(CONTROL_PING_RESPONSE, timeStamp); - } - break; - case CONTROL_PING_RESPONSE: { - if (chunkData.strBuf.size() < 4) { - throw std::runtime_error("CONTROL_PING_RESPONSE: Not enough data."); - } - //uint32_t timeStamp = load_be32(&chunkData.strBuf[0]); - //TraceL << "CONTROL_PING_RESPONSE:" << timeStamp; - } - break; - case CONTROL_STREAM_BEGIN: { - //开始播放 - if (chunkData.strBuf.size() < 4) { - throw std::runtime_error("CONTROL_STREAM_BEGIN: Not enough data."); - } - uint32_t stramId = load_be32(&chunkData.strBuf[0]); - onStreamBegin(stramId); - TraceL << "CONTROL_STREAM_BEGIN:" << stramId; - } - break; + switch (chunkData.typeId) { + case MSG_ACK: { + if (chunkData.strBuf.size() < 4) { + throw std::runtime_error("MSG_ACK: Not enough data"); + } + //auto bytePeerRecv = load_be32(&chunkData.strBuf[0]); + //TraceL << "MSG_ACK:" << bytePeerRecv; + } + break; + case MSG_SET_CHUNK: { + if (chunkData.strBuf.size() < 4) { + throw std::runtime_error("MSG_SET_CHUNK :Not enough data"); + } + _iChunkLenIn = load_be32(&chunkData.strBuf[0]); + TraceL << "MSG_SET_CHUNK:" << _iChunkLenIn; + } + break; + case MSG_USER_CONTROL: { + //user control message + if (chunkData.strBuf.size() < 2) { + throw std::runtime_error("MSG_USER_CONTROL: Not enough data."); + } + uint16_t event_type = load_be16(&chunkData.strBuf[0]); + chunkData.strBuf.erase(0, 2); + switch (event_type) { + case CONTROL_PING_REQUEST: { + if (chunkData.strBuf.size() < 4) { + throw std::runtime_error("CONTROL_PING_REQUEST: Not enough data."); + } + uint32_t timeStamp = load_be32(&chunkData.strBuf[0]); + //TraceL << "CONTROL_PING_REQUEST:" << timeStamp; + sendUserControl(CONTROL_PING_RESPONSE, timeStamp); + } + break; + case CONTROL_PING_RESPONSE: { + if (chunkData.strBuf.size() < 4) { + throw std::runtime_error("CONTROL_PING_RESPONSE: Not enough data."); + } + //uint32_t timeStamp = load_be32(&chunkData.strBuf[0]); + //TraceL << "CONTROL_PING_RESPONSE:" << timeStamp; + } + break; + case CONTROL_STREAM_BEGIN: { + //开始播放 + if (chunkData.strBuf.size() < 4) { + throw std::runtime_error("CONTROL_STREAM_BEGIN: Not enough data."); + } + uint32_t stramId = load_be32(&chunkData.strBuf[0]); + onStreamBegin(stramId); + TraceL << "CONTROL_STREAM_BEGIN:" << stramId; + } + break; - case CONTROL_STREAM_EOF: { - //暂停 - if (chunkData.strBuf.size() < 4) { - throw std::runtime_error("CONTROL_STREAM_EOF: Not enough data."); - } - uint32_t stramId = load_be32(&chunkData.strBuf[0]); - onStreamEof(stramId); - TraceL << "CONTROL_STREAM_EOF:" << stramId; - } - break; - case CONTROL_STREAM_DRY: { - //停止播放 - if (chunkData.strBuf.size() < 4) { - throw std::runtime_error("CONTROL_STREAM_DRY: Not enough data."); - } - uint32_t stramId = load_be32(&chunkData.strBuf[0]); - onStreamDry(stramId); - TraceL << "CONTROL_STREAM_DRY:" << stramId; - } - break; - default: - //WarnL << "unhandled user control:" << event_type; - break; - } - } - break; + case CONTROL_STREAM_EOF: { + //暂停 + if (chunkData.strBuf.size() < 4) { + throw std::runtime_error("CONTROL_STREAM_EOF: Not enough data."); + } + uint32_t stramId = load_be32(&chunkData.strBuf[0]); + onStreamEof(stramId); + TraceL << "CONTROL_STREAM_EOF:" << stramId; + } + break; + case CONTROL_STREAM_DRY: { + //停止播放 + if (chunkData.strBuf.size() < 4) { + throw std::runtime_error("CONTROL_STREAM_DRY: Not enough data."); + } + uint32_t stramId = load_be32(&chunkData.strBuf[0]); + onStreamDry(stramId); + TraceL << "CONTROL_STREAM_DRY:" << stramId; + } + break; + default: + //WarnL << "unhandled user control:" << event_type; + break; + } + } + break; - case MSG_WIN_SIZE: { - _ui32WinSize = load_be32(&chunkData.strBuf[0]); - TraceL << "MSG_WIN_SIZE:" << _ui32WinSize; - } - break; - case MSG_SET_PEER_BW: { - _ui32Bandwidth = load_be32(&chunkData.strBuf[0]); - _ui8LimitType = chunkData.strBuf[4]; - TraceL << "MSG_SET_PEER_BW:" << _ui32WinSize; - } - break; - case MSG_AGGREGATE: { - auto ptr = (uint8_t*)chunkData.strBuf.data(); - auto ptr_tail = ptr + chunkData.strBuf.length() ; - while(ptr + 8 + 3 < ptr_tail){ - auto type = *ptr; - ptr += 1; - auto size = load_be24(ptr); - ptr += 3; - auto ts = load_be24(ptr); - ptr += 3; - ts |= (*ptr << 24); - ptr += 1; + case MSG_WIN_SIZE: { + _ui32WinSize = load_be32(&chunkData.strBuf[0]); + TraceL << "MSG_WIN_SIZE:" << _ui32WinSize; + } + break; + case MSG_SET_PEER_BW: { + _ui32Bandwidth = load_be32(&chunkData.strBuf[0]); + _ui8LimitType = chunkData.strBuf[4]; + TraceL << "MSG_SET_PEER_BW:" << _ui32WinSize; + } + break; + case MSG_AGGREGATE: { + auto ptr = (uint8_t*)chunkData.strBuf.data(); + auto ptr_tail = ptr + chunkData.strBuf.length() ; + while(ptr + 8 + 3 < ptr_tail){ + auto type = *ptr; + ptr += 1; + auto size = load_be24(ptr); + ptr += 3; + auto ts = load_be24(ptr); + ptr += 3; + ts |= (*ptr << 24); + ptr += 1; - //参考ffmpeg忽略了3个字节 - /** - * while (next - pkt->data < pkt->size - RTMP_HEADER) { - type = bytestream_get_byte(&next); - size = bytestream_get_be24(&next); - cts = bytestream_get_be24(&next); - cts |= bytestream_get_byte(&next) << 24; - if (!pts) - pts = cts; - ts += cts - pts; - pts = cts; - if (size + 3 + 4 > pkt->data + pkt->size - next) - break; - bytestream_put_byte(&p, type); - bytestream_put_be24(&p, size); - bytestream_put_be24(&p, ts); - bytestream_put_byte(&p, ts >> 24); - memcpy(p, next, size + 3 + 4); - p += size + 3; - bytestream_put_be32(&p, size + RTMP_HEADER); - next += size + 3 + 4; - } - */ - ptr += 3; - //参考FFmpeg多拷贝了4个字节 - size += 4; - if(ptr + size > ptr_tail){ + //参考ffmpeg忽略了3个字节 + /** + * while (next - pkt->data < pkt->size - RTMP_HEADER) { + type = bytestream_get_byte(&next); + size = bytestream_get_be24(&next); + cts = bytestream_get_be24(&next); + cts |= bytestream_get_byte(&next) << 24; + if (!pts) + pts = cts; + ts += cts - pts; + pts = cts; + if (size + 3 + 4 > pkt->data + pkt->size - next) + break; + bytestream_put_byte(&p, type); + bytestream_put_be24(&p, size); + bytestream_put_be24(&p, ts); + bytestream_put_byte(&p, ts >> 24); + memcpy(p, next, size + 3 + 4); + p += size + 3; + bytestream_put_be32(&p, size + RTMP_HEADER); + next += size + 3 + 4; + } + */ + ptr += 3; + //参考FFmpeg多拷贝了4个字节 + size += 4; + if(ptr + size > ptr_tail){ // ErrorL << ptr + size << " " << ptr_tail << " " << ptr_tail - ptr - size; - break; - } + break; + } // DebugL << (int)type << " " << size << " " << ts << " " << chunkData.timeStamp << " " << ptr_tail - ptr; - RtmpPacket sub_packet ; - sub_packet.strBuf.resize(size); - memcpy((char *)sub_packet.strBuf.data(),ptr,size); - sub_packet.typeId = type; - sub_packet.bodySize = size; - sub_packet.timeStamp = ts; - sub_packet.streamId = chunkData.streamId; - sub_packet.chunkId = chunkData.chunkId; - handle_rtmpChunk(sub_packet); - ptr += size; - } + RtmpPacket sub_packet ; + sub_packet.strBuf.resize(size); + memcpy((char *)sub_packet.strBuf.data(),ptr,size); + sub_packet.typeId = type; + sub_packet.bodySize = size; + sub_packet.timeStamp = ts; + sub_packet.streamId = chunkData.streamId; + sub_packet.chunkId = chunkData.chunkId; + handle_rtmpChunk(sub_packet); + ptr += size; + } // InfoL << ptr_tail - ptr; - } - break; - default: - onRtmpChunk(chunkData); - break; - } + } + break; + default: + onRtmpChunk(chunkData); + break; + } } BufferRaw::Ptr RtmpProtocol::obtainBuffer() { @@ -778,9 +778,9 @@ BufferRaw::Ptr RtmpProtocol::obtainBuffer() { } BufferRaw::Ptr RtmpProtocol::obtainBuffer(const void *data, int len) { - auto buffer = obtainBuffer(); - buffer->assign((const char *)data,len); - return buffer; + auto buffer = obtainBuffer(); + buffer->assign((const char *)data,len); + return buffer; } } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpProtocol.h b/src/Rtmp/RtmpProtocol.h index d9632975..b22cec26 100644 --- a/src/Rtmp/RtmpProtocol.h +++ b/src/Rtmp/RtmpProtocol.h @@ -45,77 +45,77 @@ namespace mediakit { class RtmpProtocol { public: - RtmpProtocol(); - virtual ~RtmpProtocol(); - //作为客户端发送c0c1,等待s0s1s2并且回调 - void startClientSession(const function &cb); - void onParseRtmp(const char *pcRawData,int iSize); - void reset(); + RtmpProtocol(); + virtual ~RtmpProtocol(); + //作为客户端发送c0c1,等待s0s1s2并且回调 + void startClientSession(const function &cb); + void onParseRtmp(const char *pcRawData,int iSize); + void reset(); protected: - virtual void onSendRawData(const Buffer::Ptr &buffer) = 0; - virtual void onRtmpChunk(RtmpPacket &chunkData) = 0; - virtual void onStreamBegin(uint32_t ui32StreamId){ - _ui32StreamId = ui32StreamId; - } - virtual void onStreamEof(uint32_t ui32StreamId){}; - virtual void onStreamDry(uint32_t ui32StreamId){}; + virtual void onSendRawData(const Buffer::Ptr &buffer) = 0; + virtual void onRtmpChunk(RtmpPacket &chunkData) = 0; + virtual void onStreamBegin(uint32_t ui32StreamId){ + _ui32StreamId = ui32StreamId; + } + virtual void onStreamEof(uint32_t ui32StreamId){}; + virtual void onStreamDry(uint32_t ui32StreamId){}; protected: - void sendAcknowledgement(uint32_t ui32Size); - void sendAcknowledgementSize(uint32_t ui32Size); - void sendPeerBandwidth(uint32_t ui32Size); - void sendChunkSize(uint32_t ui32Size); - void sendPingRequest(uint32_t ui32TimeStamp = ::time(NULL)); - void sendPingResponse(uint32_t ui32TimeStamp = ::time(NULL)); - void sendSetBufferLength(uint32_t ui32StreamId, uint32_t ui32Length); - void sendUserControl(uint16_t ui16EventType, uint32_t ui32EventData); - void sendUserControl(uint16_t ui16EventType, const string &strEventData); + void sendAcknowledgement(uint32_t ui32Size); + void sendAcknowledgementSize(uint32_t ui32Size); + void sendPeerBandwidth(uint32_t ui32Size); + void sendChunkSize(uint32_t ui32Size); + void sendPingRequest(uint32_t ui32TimeStamp = ::time(NULL)); + void sendPingResponse(uint32_t ui32TimeStamp = ::time(NULL)); + void sendSetBufferLength(uint32_t ui32StreamId, uint32_t ui32Length); + void sendUserControl(uint16_t ui16EventType, uint32_t ui32EventData); + void sendUserControl(uint16_t ui16EventType, const string &strEventData); - void sendInvoke(const string &strCmd, const AMFValue &val); - void sendRequest(int iCmd, 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 Buffer::Ptr &buffer, uint32_t ui32TimeStamp, int iChunkID); + void sendInvoke(const string &strCmd, const AMFValue &val); + void sendRequest(int iCmd, 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 Buffer::Ptr &buffer, uint32_t ui32TimeStamp, int iChunkID); protected: - int _iReqID = 0; - uint32_t _ui32StreamId = STREAM_CONTROL; - int _iNowStreamID = 0; - int _iNowChunkID = 0; - bool _bDataStarted = false; - inline BufferRaw::Ptr obtainBuffer(); - inline BufferRaw::Ptr obtainBuffer(const void *data, int len); - //ResourcePool _bufferPool; + int _iReqID = 0; + uint32_t _ui32StreamId = STREAM_CONTROL; + int _iNowStreamID = 0; + int _iNowChunkID = 0; + bool _bDataStarted = false; + inline BufferRaw::Ptr obtainBuffer(); + inline BufferRaw::Ptr obtainBuffer(const void *data, int len); + //ResourcePool _bufferPool; private: - void handle_S0S1S2(const function &cb); - void handle_C0C1(); - void handle_C1_simple(); + void handle_S0S1S2(const function &cb); + void handle_C0C1(); + void handle_C1_simple(); #ifdef ENABLE_OPENSSL - void handle_C1_complex(); - string get_C1_digest(const uint8_t *ptr,char **digestPos); - string get_C1_key(const uint8_t *ptr); - void check_C1_Digest(const string &digest,const string &data); - void send_complex_S0S1S2(int schemeType,const string &digest); + void handle_C1_complex(); + string get_C1_digest(const uint8_t *ptr,char **digestPos); + string get_C1_key(const uint8_t *ptr); + void check_C1_Digest(const string &digest,const string &data); + void send_complex_S0S1S2(int schemeType,const string &digest); #endif //ENABLE_OPENSSL - void handle_C2(); - void handle_rtmp(); - void handle_rtmpChunk(RtmpPacket &chunkData); + void handle_C2(); + void handle_rtmp(); + void handle_rtmpChunk(RtmpPacket &chunkData); private: - ////////////ChunkSize//////////// - size_t _iChunkLenIn = DEFAULT_CHUNK_LEN; - size_t _iChunkLenOut = DEFAULT_CHUNK_LEN; - ////////////Acknowledgement//////////// - uint32_t _ui32ByteSent = 0; - uint32_t _ui32LastSent = 0; - uint32_t _ui32WinSize = 0; - ///////////PeerBandwidth/////////// - uint32_t _ui32Bandwidth = 2500000; - uint8_t _ui8LimitType = 2; - ////////////Chunk//////////// - unordered_map _mapChunkData; - //////////Rtmp parser////////// - string _strRcvBuf; - function _nextHandle; + ////////////ChunkSize//////////// + size_t _iChunkLenIn = DEFAULT_CHUNK_LEN; + size_t _iChunkLenOut = DEFAULT_CHUNK_LEN; + ////////////Acknowledgement//////////// + uint32_t _ui32ByteSent = 0; + uint32_t _ui32LastSent = 0; + uint32_t _ui32WinSize = 0; + ///////////PeerBandwidth/////////// + uint32_t _ui32Bandwidth = 2500000; + uint8_t _ui8LimitType = 2; + ////////////Chunk//////////// + unordered_map _mapChunkData; + //////////Rtmp parser////////// + string _strRcvBuf; + function _nextHandle; }; } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpPusher.cpp b/src/Rtmp/RtmpPusher.cpp index ea2ebca8..29ca0cfe 100644 --- a/src/Rtmp/RtmpPusher.cpp +++ b/src/Rtmp/RtmpPusher.cpp @@ -34,55 +34,55 @@ using namespace mediakit::Client; namespace mediakit { RtmpPusher::RtmpPusher(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &src) : TcpClient(poller){ - _pMediaSrc=src; + _pMediaSrc=src; } RtmpPusher::~RtmpPusher() { - teardown(); - DebugL << endl; + teardown(); + DebugL << endl; } void RtmpPusher::teardown() { - if (alive()) { - _strApp.clear(); - _strStream.clear(); - _strTcUrl.clear(); - { - lock_guard lck(_mtxOnResultCB); - _mapOnResultCB.clear(); - } + if (alive()) { + _strApp.clear(); + _strStream.clear(); + _strTcUrl.clear(); + { + lock_guard lck(_mtxOnResultCB); + _mapOnResultCB.clear(); + } { lock_guard lck(_mtxOnStatusCB); _dqOnStatusCB.clear(); } - _pPublishTimer.reset(); + _pPublishTimer.reset(); reset(); shutdown(SockException(Err_shutdown,"teardown")); - } + } } void RtmpPusher::onPublishResult(const SockException &ex,bool handshakeCompleted) { - if(!handshakeCompleted){ - //播放结果回调 - _pPublishTimer.reset(); - if(_onPublished){ - _onPublished(ex); - } - } else { - //播放成功后异常断开回调 - if(_onShutdown){ - _onShutdown(ex); - } - } + if(!handshakeCompleted){ + //播放结果回调 + _pPublishTimer.reset(); + if(_onPublished){ + _onPublished(ex); + } + } else { + //播放成功后异常断开回调 + if(_onShutdown){ + _onShutdown(ex); + } + } - if(ex){ - teardown(); - } + if(ex){ + teardown(); + } } void RtmpPusher::publish(const string &strUrl) { - teardown(); - string strHost = FindField(strUrl.data(), "://", "/"); - _strApp = FindField(strUrl.data(), (strHost + "/").data(), "/"); + teardown(); + string strHost = FindField(strUrl.data(), "://", "/"); + _strApp = FindField(strUrl.data(), (strHost + "/").data(), "/"); _strStream = FindField(strUrl.data(), (strHost + "/" + _strApp + "/").data(), NULL); _strTcUrl = string("rtmp://") + strHost + "/" + _strApp; @@ -90,16 +90,16 @@ void RtmpPusher::publish(const string &strUrl) { onPublishResult(SockException(Err_other,"rtmp url非法"),false); return; } - DebugL << strHost << " " << _strApp << " " << _strStream; + DebugL << strHost << " " << _strApp << " " << _strStream; - auto iPort = atoi(FindField(strHost.data(), ":", NULL).data()); - if (iPort <= 0) { + auto iPort = atoi(FindField(strHost.data(), ":", NULL).data()); + if (iPort <= 0) { //rtmp 默认端口1935 - iPort = 1935; - } else { + iPort = 1935; + } else { //服务器域名 - strHost = FindField(strHost.data(), NULL, ":"); - } + strHost = FindField(strHost.data(), NULL, ":"); + } weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); float publishTimeOutSec = (*this)[kTimeoutMS].as() / 1000.0; @@ -116,23 +116,23 @@ void RtmpPusher::publish(const string &strUrl) { setNetAdapter((*this)[kNetAdapter]); } - startConnect(strHost, iPort); + startConnect(strHost, iPort); } void RtmpPusher::onErr(const SockException &ex){ - //定时器_pPublishTimer为空后表明握手结束了 - onPublishResult(ex,!_pPublishTimer); + //定时器_pPublishTimer为空后表明握手结束了 + onPublishResult(ex,!_pPublishTimer); } void RtmpPusher::onConnect(const SockException &err){ - if(err) { - onPublishResult(err,false); - return; - } - //推流器不需要多大的接收缓存,节省内存占用 - _sock->setReadBuffer(std::make_shared(1 * 1024)); + if(err) { + onPublishResult(err,false); + return; + } + //推流器不需要多大的接收缓存,节省内存占用 + _sock->setReadBuffer(std::make_shared(1 * 1024)); - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - startClientSession([weakSelf](){ + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + startClientSession([weakSelf](){ auto strongSelf=weakSelf.lock(); if(!strongSelf) { return; @@ -140,63 +140,63 @@ void RtmpPusher::onConnect(const SockException &err){ strongSelf->sendChunkSize(60000); strongSelf->send_connect(); - }); + }); } void RtmpPusher::onRecv(const Buffer::Ptr &pBuf){ - try { - onParseRtmp(pBuf->data(), pBuf->size()); - } catch (exception &e) { - SockException ex(Err_other, e.what()); - //定时器_pPublishTimer为空后表明握手结束了 - onPublishResult(ex,!_pPublishTimer); - } + try { + onParseRtmp(pBuf->data(), pBuf->size()); + } catch (exception &e) { + SockException ex(Err_other, e.what()); + //定时器_pPublishTimer为空后表明握手结束了 + onPublishResult(ex,!_pPublishTimer); + } } inline void RtmpPusher::send_connect() { - AMFValue obj(AMF_OBJECT); - obj.set("app", _strApp); - obj.set("type", "nonprivate"); - obj.set("tcUrl", _strTcUrl); - obj.set("swfUrl", _strTcUrl); - sendInvoke("connect", obj); - addOnResultCB([this](AMFDecoder &dec){ - //TraceL << "connect result"; - dec.load(); - auto val = dec.load(); - auto level = val["level"].as_string(); - auto code = val["code"].as_string(); - if(level != "status"){ - throw std::runtime_error(StrPrinter <<"connect 失败:" << level << " " << code << endl); - } - send_createStream(); - }); + AMFValue obj(AMF_OBJECT); + obj.set("app", _strApp); + obj.set("type", "nonprivate"); + obj.set("tcUrl", _strTcUrl); + obj.set("swfUrl", _strTcUrl); + sendInvoke("connect", obj); + addOnResultCB([this](AMFDecoder &dec){ + //TraceL << "connect result"; + dec.load(); + auto val = dec.load(); + auto level = val["level"].as_string(); + auto code = val["code"].as_string(); + if(level != "status"){ + throw std::runtime_error(StrPrinter <<"connect 失败:" << level << " " << code << endl); + } + send_createStream(); + }); } inline void RtmpPusher::send_createStream() { - AMFValue obj(AMF_NULL); - sendInvoke("createStream", obj); - addOnResultCB([this](AMFDecoder &dec){ - //TraceL << "createStream result"; - dec.load(); - _ui32StreamId = dec.load(); - send_publish(); - }); + AMFValue obj(AMF_NULL); + sendInvoke("createStream", obj); + addOnResultCB([this](AMFDecoder &dec){ + //TraceL << "createStream result"; + dec.load(); + _ui32StreamId = dec.load(); + send_publish(); + }); } inline void RtmpPusher::send_publish() { - AMFEncoder enc; - enc << "publish" << ++_iReqID << nullptr << _strStream << _strApp ; - sendRequest(MSG_CMD, enc.data()); + AMFEncoder enc; + enc << "publish" << ++_iReqID << nullptr << _strStream << _strApp ; + sendRequest(MSG_CMD, enc.data()); - addOnStatusCB([this](AMFValue &val) { - auto level = val["level"].as_string(); - auto code = val["code"].as_string(); - if(level != "status") { - throw std::runtime_error(StrPrinter <<"publish 失败:" << level << " " << code << endl); - } - //start send media - send_metaData(); - }); + addOnStatusCB([this](AMFValue &val) { + auto level = val["level"].as_string(); + auto code = val["code"].as_string(); + if(level != "status") { + throw std::runtime_error(StrPrinter <<"publish 失败:" << level << " " << code << endl); + } + //start send media + send_metaData(); + }); } inline void RtmpPusher::send_metaData(){ @@ -216,11 +216,11 @@ inline void RtmpPusher::send_metaData(){ _pRtmpReader = src->getRing()->attach(getPoller()); weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); _pRtmpReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt){ - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } - strongSelf->sendRtmp(pkt->typeId, strongSelf->_ui32StreamId, pkt, pkt->timeStamp, pkt->chunkId); + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } + strongSelf->sendRtmp(pkt->typeId, strongSelf->_ui32StreamId, pkt, pkt->timeStamp, pkt->chunkId); }); _pRtmpReader->setDetachCB([weakSelf](){ auto strongSelf = weakSelf.lock(); @@ -229,84 +229,84 @@ inline void RtmpPusher::send_metaData(){ } }); onPublishResult(SockException(Err_success,"success"), false); - //提升发送性能 - setSocketFlags(); + //提升发送性能 + setSocketFlags(); } void RtmpPusher::setSocketFlags(){ - GET_CONFIG(bool,ultraLowDelay,General::kUltraLowDelay); - if(!ultraLowDelay) { + GET_CONFIG(bool,ultraLowDelay,General::kUltraLowDelay); + if(!ultraLowDelay) { //提高发送性能 (*this) << SocketFlags(SOCKET_DEFAULE_FLAGS | FLAG_MORE); SockUtil::setNoDelay(_sock->rawFD(), false); - } + } } void RtmpPusher::onCmd_result(AMFDecoder &dec){ - auto iReqId = dec.load(); - lock_guard lck(_mtxOnResultCB); - auto it = _mapOnResultCB.find(iReqId); - if(it != _mapOnResultCB.end()){ - it->second(dec); - _mapOnResultCB.erase(it); - }else{ - WarnL << "unhandled _result"; - } + auto iReqId = dec.load(); + lock_guard lck(_mtxOnResultCB); + auto it = _mapOnResultCB.find(iReqId); + if(it != _mapOnResultCB.end()){ + it->second(dec); + _mapOnResultCB.erase(it); + }else{ + WarnL << "unhandled _result"; + } } void RtmpPusher::onCmd_onStatus(AMFDecoder &dec) { - AMFValue val; - while(true){ - val = dec.load(); - if(val.type() == AMF_OBJECT){ - break; - } - } - if(val.type() != AMF_OBJECT){ - throw std::runtime_error("onStatus:the result object was not found"); - } + AMFValue val; + while(true){ + val = dec.load(); + if(val.type() == AMF_OBJECT){ + break; + } + } + if(val.type() != AMF_OBJECT){ + throw std::runtime_error("onStatus:the result object was not found"); + } lock_guard lck(_mtxOnStatusCB); - if(_dqOnStatusCB.size()){ - _dqOnStatusCB.front()(val); - _dqOnStatusCB.pop_front(); - }else{ - auto level = val["level"]; - auto code = val["code"].as_string(); - if(level.type() == AMF_STRING){ - if(level.as_string() != "status"){ - throw std::runtime_error(StrPrinter <<"onStatus 失败:" << level.as_string() << " " << code << endl); - } - } + if(_dqOnStatusCB.size()){ + _dqOnStatusCB.front()(val); + _dqOnStatusCB.pop_front(); + }else{ + auto level = val["level"]; + auto code = val["code"].as_string(); + if(level.type() == AMF_STRING){ + if(level.as_string() != "status"){ + throw std::runtime_error(StrPrinter <<"onStatus 失败:" << level.as_string() << " " << code << endl); + } + } } } void RtmpPusher::onRtmpChunk(RtmpPacket &chunkData) { - switch (chunkData.typeId) { - case MSG_CMD: - case MSG_CMD3: { - typedef void (RtmpPusher::*rtmpCMDHandle)(AMFDecoder &dec); - static unordered_map g_mapCmd; - static onceToken token([]() { - g_mapCmd.emplace("_error",&RtmpPusher::onCmd_result); - g_mapCmd.emplace("_result",&RtmpPusher::onCmd_result); - g_mapCmd.emplace("onStatus",&RtmpPusher::onCmd_onStatus); - }, []() {}); + switch (chunkData.typeId) { + case MSG_CMD: + case MSG_CMD3: { + typedef void (RtmpPusher::*rtmpCMDHandle)(AMFDecoder &dec); + static unordered_map g_mapCmd; + static onceToken token([]() { + g_mapCmd.emplace("_error",&RtmpPusher::onCmd_result); + g_mapCmd.emplace("_result",&RtmpPusher::onCmd_result); + g_mapCmd.emplace("onStatus",&RtmpPusher::onCmd_onStatus); + }, []() {}); - AMFDecoder dec(chunkData.strBuf, 0); - std::string type = dec.load(); - auto it = g_mapCmd.find(type); - if(it != g_mapCmd.end()){ - auto fun = it->second; - (this->*fun)(dec); - }else{ - WarnL << "can not support cmd:" << type; - } - } - break; - default: - //WarnL << "unhandled message:" << (int) chunkData.typeId << hexdump(chunkData.strBuf.data(), chunkData.strBuf.size()); - break; - } + AMFDecoder dec(chunkData.strBuf, 0); + std::string type = dec.load(); + auto it = g_mapCmd.find(type); + if(it != g_mapCmd.end()){ + auto fun = it->second; + (this->*fun)(dec); + }else{ + WarnL << "can not support cmd:" << type; + } + } + break; + default: + //WarnL << "unhandled message:" << (int) chunkData.typeId << hexdump(chunkData.strBuf.data(), chunkData.strBuf.size()); + break; + } } diff --git a/src/Rtmp/RtmpPusher.h b/src/Rtmp/RtmpPusher.h index 9be06f37..15ade09e 100644 --- a/src/Rtmp/RtmpPusher.h +++ b/src/Rtmp/RtmpPusher.h @@ -36,66 +36,66 @@ namespace mediakit { class RtmpPusher: public RtmpProtocol , public TcpClient , public PusherBase{ public: - typedef std::shared_ptr Ptr; - RtmpPusher(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &src); - virtual ~RtmpPusher(); + typedef std::shared_ptr Ptr; + RtmpPusher(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &src); + 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 { - _onPublished = cb; - } + void setOnPublished(const Event &cb) override { + _onPublished = cb; + } - void setOnShutdown(const Event &cb) override{ - _onShutdown = cb; - } + void setOnShutdown(const Event &cb) override{ + _onShutdown = cb; + } protected: - //for Tcpclient override - void onRecv(const Buffer::Ptr &pBuf) override; - void onConnect(const SockException &err) override; - void onErr(const SockException &ex) override; + //for Tcpclient override + void onRecv(const Buffer::Ptr &pBuf) override; + void onConnect(const SockException &err) override; + void onErr(const SockException &ex) override; - //for RtmpProtocol override - void onRtmpChunk(RtmpPacket &chunkData) override; - void onSendRawData(const Buffer::Ptr &buffer) override{ - send(buffer); - } + //for RtmpProtocol override + void onRtmpChunk(RtmpPacket &chunkData) override; + void onSendRawData(const Buffer::Ptr &buffer) override{ + send(buffer); + } private: - void onPublishResult(const SockException &ex,bool handshakeCompleted); + void onPublishResult(const SockException &ex,bool handshakeCompleted); - template - inline void addOnResultCB(const FUN &fun) { - lock_guard lck(_mtxOnResultCB); - _mapOnResultCB.emplace(_iReqID, fun); - } - template - inline void addOnStatusCB(const FUN &fun) { - lock_guard lck(_mtxOnStatusCB); - _dqOnStatusCB.emplace_back(fun); - } + template + inline void addOnResultCB(const FUN &fun) { + lock_guard lck(_mtxOnResultCB); + _mapOnResultCB.emplace(_iReqID, fun); + } + template + inline void addOnStatusCB(const FUN &fun) { + lock_guard lck(_mtxOnStatusCB); + _dqOnStatusCB.emplace_back(fun); + } - void onCmd_result(AMFDecoder &dec); - void onCmd_onStatus(AMFDecoder &dec); - void onCmd_onMetaData(AMFDecoder &dec); + void onCmd_result(AMFDecoder &dec); + void onCmd_onStatus(AMFDecoder &dec); + void onCmd_onMetaData(AMFDecoder &dec); - inline void send_connect(); - inline void send_createStream(); - inline void send_publish(); - inline void send_metaData(); - void setSocketFlags(); + inline void send_connect(); + inline void send_createStream(); + inline void send_publish(); + inline void send_metaData(); + void setSocketFlags(); private: - string _strApp; - string _strStream; - string _strTcUrl; + string _strApp; + string _strStream; + string _strTcUrl; - unordered_map > _mapOnResultCB; - recursive_mutex _mtxOnResultCB; - deque > _dqOnStatusCB; - recursive_mutex _mtxOnStatusCB; - //超时功能实现 - std::shared_ptr _pPublishTimer; + unordered_map > _mapOnResultCB; + recursive_mutex _mtxOnResultCB; + deque > _dqOnStatusCB; + recursive_mutex _mtxOnStatusCB; + //超时功能实现 + std::shared_ptr _pPublishTimer; //源 std::weak_ptr _pMediaSrc; RtmpMediaSource::RingType::RingReader::Ptr _pRtmpReader; diff --git a/src/Rtmp/RtmpSession.cpp b/src/Rtmp/RtmpSession.cpp index 15e4342f..27cfcbd3 100644 --- a/src/Rtmp/RtmpSession.cpp +++ b/src/Rtmp/RtmpSession.cpp @@ -32,7 +32,7 @@ namespace mediakit { RtmpSession::RtmpSession(const Socket::Ptr &pSock) : TcpSession(pSock) { - DebugP(this); + DebugP(this); GET_CONFIG(uint32_t,keep_alive_sec,Rtmp::kKeepAliveSecond); pSock->setSendTimeOutSecond(keep_alive_sec); //起始接收buffer缓存设置为4K,节省内存 @@ -65,42 +65,42 @@ void RtmpSession::onManager() { GET_CONFIG(uint32_t,handshake_sec,Rtmp::kHandshakeSecond); GET_CONFIG(uint32_t,keep_alive_sec,Rtmp::kKeepAliveSecond); - if (_ticker.createdTime() > handshake_sec * 1000) { - if (!_pRingReader && !_pPublisherSrc) { - shutdown(SockException(Err_timeout,"illegal connection")); - } - } - if (_pPublisherSrc) { - //publisher - if (_ticker.elapsedTime() > keep_alive_sec * 1000) { - shutdown(SockException(Err_timeout,"recv data from rtmp pusher timeout")); - } - } + if (_ticker.createdTime() > handshake_sec * 1000) { + if (!_pRingReader && !_pPublisherSrc) { + shutdown(SockException(Err_timeout,"illegal connection")); + } + } + if (_pPublisherSrc) { + //publisher + if (_ticker.elapsedTime() > keep_alive_sec * 1000) { + shutdown(SockException(Err_timeout,"recv data from rtmp pusher timeout")); + } + } } void RtmpSession::onRecv(const Buffer::Ptr &pBuf) { - _ticker.resetTime(); - try { + _ticker.resetTime(); + try { _ui64TotalBytes += pBuf->size(); - onParseRtmp(pBuf->data(), pBuf->size()); - } catch (exception &e) { - shutdown(SockException(Err_shutdown, e.what())); - } + onParseRtmp(pBuf->data(), pBuf->size()); + } catch (exception &e) { + shutdown(SockException(Err_shutdown, e.what())); + } } void RtmpSession::onCmd_connect(AMFDecoder &dec) { - auto params = dec.load(); - double amfVer = 0; - AMFValue objectEncoding = params["objectEncoding"]; - if(objectEncoding){ - amfVer = objectEncoding.as_number(); - } - ///////////set chunk size//////////////// - sendChunkSize(60000); - ////////////window Acknowledgement size///// - sendAcknowledgementSize(5000000); - ///////////set peerBandwidth//////////////// - sendPeerBandwidth(5000000); + auto params = dec.load(); + double amfVer = 0; + AMFValue objectEncoding = params["objectEncoding"]; + if(objectEncoding){ + amfVer = objectEncoding.as_number(); + } + ///////////set chunk size//////////////// + sendChunkSize(60000); + ////////////window Acknowledgement size///// + sendAcknowledgementSize(5000000); + ///////////set peerBandwidth//////////////// + sendPeerBandwidth(5000000); _mediaInfo._app = params["app"].as_string(); _strTcUrl = params["tcUrl"].as_string(); @@ -108,27 +108,27 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) { //defaultVhost:默认vhost _strTcUrl = string(RTMP_SCHEMA) + "://" + DEFAULT_VHOST + "/" + _mediaInfo._app; } - bool ok = true; //(app == APP_NAME); - AMFValue version(AMF_OBJECT); - version.set("fmsVer", "FMS/3,0,1,123"); - version.set("capabilities", 31.0); - AMFValue status(AMF_OBJECT); - status.set("level", ok ? "status" : "error"); - status.set("code", ok ? "NetConnection.Connect.Success" : "NetConnection.Connect.InvalidApp"); - status.set("description", ok ? "Connection succeeded." : "InvalidApp."); - status.set("objectEncoding", amfVer); - sendReply(ok ? "_result" : "_error", version, status); - if (!ok) { - throw std::runtime_error("Unsupported application: " + _mediaInfo._app); - } + bool ok = true; //(app == APP_NAME); + AMFValue version(AMF_OBJECT); + version.set("fmsVer", "FMS/3,0,1,123"); + version.set("capabilities", 31.0); + AMFValue status(AMF_OBJECT); + status.set("level", ok ? "status" : "error"); + status.set("code", ok ? "NetConnection.Connect.Success" : "NetConnection.Connect.InvalidApp"); + status.set("description", ok ? "Connection succeeded." : "InvalidApp."); + status.set("objectEncoding", amfVer); + sendReply(ok ? "_result" : "_error", version, status); + if (!ok) { + throw std::runtime_error("Unsupported application: " + _mediaInfo._app); + } - AMFEncoder invoke; - invoke << "onBWDone" << 0.0 << nullptr; - sendResponse(MSG_CMD, invoke.data()); + AMFEncoder invoke; + invoke << "onBWDone" << 0.0 << nullptr; + sendResponse(MSG_CMD, invoke.data()); } void RtmpSession::onCmd_createStream(AMFDecoder &dec) { - sendReply("_result", nullptr, double(STREAM_MEDIA)); + sendReply("_result", nullptr, double(STREAM_MEDIA)); } void RtmpSession::onCmd_publish(AMFDecoder &dec) { @@ -140,7 +140,7 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) { DebugP(strongSelf.get()) << "publish 回复时间:" << pTicker->elapsedTime() << "ms"; } })); - dec.load();/* NULL */ + dec.load();/* NULL */ _mediaInfo.parse(_strTcUrl + "/" + getStreamId(dec.load())); _mediaInfo._schema = RTMP_SCHEMA; @@ -203,12 +203,12 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) { } void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) { - AMFValue status(AMF_OBJECT); - status.set("level", "status"); - status.set("code", "NetStream.Unpublish.Success"); - status.set("description", "Stop publishing."); - sendReply("onStatus", nullptr, status); - throw std::runtime_error(StrPrinter << "Stop publishing" << endl); + AMFValue status(AMF_OBJECT); + status.set("level", "status"); + status.set("code", "NetStream.Unpublish.Success"); + status.set("description", "Stop publishing."); + sendReply("onStatus", nullptr, status); + throw std::runtime_error(StrPrinter << "Stop publishing" << endl); } @@ -355,7 +355,7 @@ void RtmpSession::doPlay(AMFDecoder &dec){ } } void RtmpSession::onCmd_play2(AMFDecoder &dec) { - doPlay(dec); + doPlay(dec); } string RtmpSession::getStreamId(const string &str){ @@ -390,49 +390,49 @@ string RtmpSession::getStreamId(const string &str){ } void RtmpSession::onCmd_play(AMFDecoder &dec) { - dec.load();/* NULL */ + dec.load();/* NULL */ _mediaInfo.parse(_strTcUrl + "/" + getStreamId(dec.load())); _mediaInfo._schema = RTMP_SCHEMA; - doPlay(dec); + doPlay(dec); } void RtmpSession::onCmd_pause(AMFDecoder &dec) { - dec.load();/* NULL */ - bool paused = dec.load(); - TraceP(this) << paused; - AMFValue status(AMF_OBJECT); - status.set("level", "status"); - status.set("code", paused ? "NetStream.Pause.Notify" : "NetStream.Unpause.Notify"); - status.set("description", paused ? "Paused stream." : "Unpaused stream."); - sendReply("onStatus", nullptr, status); + dec.load();/* NULL */ + bool paused = dec.load(); + TraceP(this) << paused; + AMFValue status(AMF_OBJECT); + status.set("level", "status"); + status.set("code", paused ? "NetStream.Pause.Notify" : "NetStream.Unpause.Notify"); + status.set("description", paused ? "Paused stream." : "Unpaused stream."); + sendReply("onStatus", nullptr, status); //streamBegin - sendUserControl(paused ? CONTROL_STREAM_EOF : CONTROL_STREAM_BEGIN, - STREAM_MEDIA); - if (!_pRingReader) { - throw std::runtime_error("Rtmp not started yet!"); - } - if (paused) { - _pRingReader->setReadCB(nullptr); - } else { - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - _pRingReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt) { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } + sendUserControl(paused ? CONTROL_STREAM_EOF : CONTROL_STREAM_BEGIN, + STREAM_MEDIA); + if (!_pRingReader) { + throw std::runtime_error("Rtmp not started yet!"); + } + if (paused) { + _pRingReader->setReadCB(nullptr); + } else { + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + _pRingReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt) { + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } strongSelf->onSendMedia(pkt); - }); - } + }); + } } void RtmpSession::setMetaData(AMFDecoder &dec) { - if (!_pPublisherSrc) { - throw std::runtime_error("not a publisher"); - } - std::string type = dec.load(); - if (type != "onMetaData") { - throw std::runtime_error("can only set metadata"); - } + if (!_pPublisherSrc) { + throw std::runtime_error("not a publisher"); + } + std::string type = dec.load(); + if (type != "onMetaData") { + throw std::runtime_error("can only set metadata"); + } auto metadata = dec.load(); // dumpMetadata(metadata); _pPublisherSrc->setMetaData(metadata); @@ -453,42 +453,42 @@ void RtmpSession::onProcessCmd(AMFDecoder &dec) { s_cmd_functions.emplace("pause",&RtmpSession::onCmd_pause);}, []() {}); std::string method = dec.load(); - auto it = s_cmd_functions.find(method); - if (it == s_cmd_functions.end()) { + auto it = s_cmd_functions.find(method); + if (it == s_cmd_functions.end()) { // TraceP(this) << "can not support cmd:" << method; - return; - } - _dNowReqID = dec.load(); - auto fun = it->second; - (this->*fun)(dec); + return; + } + _dNowReqID = dec.load(); + auto fun = it->second; + (this->*fun)(dec); } void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) { - switch (chunkData.typeId) { - case MSG_CMD: - case MSG_CMD3: { - AMFDecoder dec(chunkData.strBuf, chunkData.typeId == MSG_CMD3 ? 1 : 0); - onProcessCmd(dec); - } - break; + switch (chunkData.typeId) { + case MSG_CMD: + case MSG_CMD3: { + AMFDecoder dec(chunkData.strBuf, chunkData.typeId == MSG_CMD3 ? 1 : 0); + onProcessCmd(dec); + } + break; - case MSG_DATA: - case MSG_DATA3: { - AMFDecoder dec(chunkData.strBuf, chunkData.typeId == MSG_CMD3 ? 1 : 0); - std::string type = dec.load(); - if (type == "@setDataFrame") { - setMetaData(dec); - }else{ + case MSG_DATA: + case MSG_DATA3: { + AMFDecoder dec(chunkData.strBuf, chunkData.typeId == MSG_CMD3 ? 1 : 0); + std::string type = dec.load(); + if (type == "@setDataFrame") { + setMetaData(dec); + }else{ TraceP(this) << "unknown notify:" << type; } - } - break; - case MSG_AUDIO: - case MSG_VIDEO: { - if (!_pPublisherSrc) { - throw std::runtime_error("Not a rtmp publisher!"); - } - GET_CONFIG(bool,rtmp_modify_stamp,Rtmp::kModifyStamp); + } + break; + case MSG_AUDIO: + case MSG_VIDEO: { + if (!_pPublisherSrc) { + throw std::runtime_error("Not a rtmp publisher!"); + } + GET_CONFIG(bool,rtmp_modify_stamp,Rtmp::kModifyStamp); if(rtmp_modify_stamp){ int64_t dts_out; _stamp[chunkData.typeId % 2].revise(chunkData.timeStamp, chunkData.timeStamp, dts_out, dts_out, true); @@ -500,12 +500,12 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) { _pPublisherSrc->setMetaData(TitleMeta().getMetadata()); } _pPublisherSrc->onWrite(std::make_shared(std::move(chunkData))); - } - break; - default: - WarnP(this) << "unhandled message:" << (int) chunkData.typeId << hexdump(chunkData.strBuf.data(), chunkData.strBuf.size()); - break; - } + } + break; + default: + WarnP(this) << "unhandled message:" << (int) chunkData.typeId << hexdump(chunkData.strBuf.data(), chunkData.strBuf.size()); + break; + } } void RtmpSession::onCmd_seek(AMFDecoder &dec) { @@ -518,12 +518,12 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) { _stamp[1].setPlayBack(); stongSrc->seekTo(milliSeconds); } - AMFValue status(AMF_OBJECT); - AMFEncoder invoke; - status.set("level", "status"); - status.set("code", "NetStream.Seek.Notify"); - status.set("description", "Seeking."); - sendReply("onStatus", nullptr, status); + AMFValue status(AMF_OBJECT); + AMFEncoder invoke; + status.set("level", "status"); + status.set("code", "NetStream.Seek.Notify"); + status.set("description", "Seeking."); + sendReply("onStatus", nullptr, status); } void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) { diff --git a/src/Rtmp/RtmpSession.h b/src/Rtmp/RtmpSession.h index f5b6df79..63f9d877 100644 --- a/src/Rtmp/RtmpSession.h +++ b/src/Rtmp/RtmpSession.h @@ -45,65 +45,65 @@ namespace mediakit { class RtmpSession: public TcpSession ,public RtmpProtocol , public MediaSourceEvent{ public: - typedef std::shared_ptr Ptr; - RtmpSession(const Socket::Ptr &_sock); - virtual ~RtmpSession(); - void onRecv(const Buffer::Ptr &pBuf) override; - void onError(const SockException &err) override; - void onManager() override; + typedef std::shared_ptr Ptr; + RtmpSession(const Socket::Ptr &_sock); + virtual ~RtmpSession(); + void onRecv(const Buffer::Ptr &pBuf) override; + void onError(const SockException &err) override; + void onManager() override; private: - void onProcessCmd(AMFDecoder &dec); - void onCmd_connect(AMFDecoder &dec); - void onCmd_createStream(AMFDecoder &dec); + void onProcessCmd(AMFDecoder &dec); + void onCmd_connect(AMFDecoder &dec); + void onCmd_createStream(AMFDecoder &dec); - void onCmd_publish(AMFDecoder &dec); - void onCmd_deleteStream(AMFDecoder &dec); + void onCmd_publish(AMFDecoder &dec); + void onCmd_deleteStream(AMFDecoder &dec); - void onCmd_play(AMFDecoder &dec); - void onCmd_play2(AMFDecoder &dec); - void doPlay(AMFDecoder &dec); - void doPlayResponse(const string &err,const std::function &cb); - void sendPlayResponse(const string &err,const RtmpMediaSource::Ptr &src); + void onCmd_play(AMFDecoder &dec); + void onCmd_play2(AMFDecoder &dec); + void doPlay(AMFDecoder &dec); + void doPlayResponse(const string &err,const std::function &cb); + void sendPlayResponse(const string &err,const RtmpMediaSource::Ptr &src); - void onCmd_seek(AMFDecoder &dec); - void onCmd_pause(AMFDecoder &dec); - void setMetaData(AMFDecoder &dec); + void onCmd_seek(AMFDecoder &dec); + void onCmd_pause(AMFDecoder &dec); + void setMetaData(AMFDecoder &dec); - void onSendMedia(const RtmpPacket::Ptr &pkt); - void onSendRawData(const Buffer::Ptr &buffer) override{ + void onSendMedia(const RtmpPacket::Ptr &pkt); + void onSendRawData(const Buffer::Ptr &buffer) override{ _ui64TotalBytes += buffer->size(); - send(buffer); - } - void onRtmpChunk(RtmpPacket &chunkData) override; + send(buffer); + } + void onRtmpChunk(RtmpPacket &chunkData) override; - template - inline void sendReply(const char *str, const first &reply, const second &status) { - AMFEncoder invoke; - invoke << str << _dNowReqID << reply << status; - sendResponse(MSG_CMD, invoke.data()); - } + template + inline void sendReply(const char *str, const first &reply, const second &status) { + AMFEncoder invoke; + invoke << str << _dNowReqID << reply << status; + sendResponse(MSG_CMD, invoke.data()); + } - //MediaSourceEvent override - bool close(MediaSource &sender,bool force) override ; + //MediaSourceEvent override + bool close(MediaSource &sender,bool force) override ; void onNoneReader(MediaSource &sender) override; - int totalReaderCount(MediaSource &sender) override; + int totalReaderCount(MediaSource &sender) override; - void setSocketFlags(); - string getStreamId(const string &str); - void dumpMetadata(const AMFValue &metadata); + void setSocketFlags(); + string getStreamId(const string &str); + void dumpMetadata(const AMFValue &metadata); private: - std::string _strTcUrl; - MediaInfo _mediaInfo; - double _dNowReqID = 0; - bool _set_meta_data = false; - Ticker _ticker;//数据接收时间 - RingBuffer::RingReader::Ptr _pRingReader; - std::shared_ptr _pPublisherSrc; - std::weak_ptr _pPlayerSrc; - //时间戳修整器 - Stamp _stamp[2]; - //消耗的总流量 - uint64_t _ui64TotalBytes = 0; + std::string _strTcUrl; + MediaInfo _mediaInfo; + double _dNowReqID = 0; + bool _set_meta_data = false; + Ticker _ticker;//数据接收时间 + RingBuffer::RingReader::Ptr _pRingReader; + std::shared_ptr _pPublisherSrc; + std::weak_ptr _pPlayerSrc; + //时间戳修整器 + Stamp _stamp[2]; + //消耗的总流量 + uint64_t _ui64TotalBytes = 0; }; diff --git a/src/Rtmp/amf.cpp b/src/Rtmp/amf.cpp index 2478cc10..0f45b95f 100644 --- a/src/Rtmp/amf.cpp +++ b/src/Rtmp/amf.cpp @@ -35,130 +35,130 @@ using namespace toolkit; /////////////////////AMFValue///////////////////////////// inline void AMFValue::destroy() { - switch (_type) { - case AMF_STRING: - if (_value.string) { - delete _value.string; - _value.string = nullptr; - } - break; - case AMF_OBJECT: - case AMF_ECMA_ARRAY: - if (_value.object) { - delete _value.object; - _value.object = nullptr; - } - break; - case AMF_STRICT_ARRAY: - if (_value.array) { - delete _value.array; - _value.array = nullptr; - } - break; - default: - break; - } + switch (_type) { + case AMF_STRING: + if (_value.string) { + delete _value.string; + _value.string = nullptr; + } + break; + case AMF_OBJECT: + case AMF_ECMA_ARRAY: + if (_value.object) { + delete _value.object; + _value.object = nullptr; + } + break; + case AMF_STRICT_ARRAY: + if (_value.array) { + delete _value.array; + _value.array = nullptr; + } + break; + default: + break; + } } inline void AMFValue::init() { - switch (_type) { - case AMF_OBJECT: - case AMF_ECMA_ARRAY: - _value.object = new mapType; - break; - case AMF_STRING: - _value.string = new std::string; - break; - case AMF_STRICT_ARRAY: - _value.array = new arrayType; - break; + switch (_type) { + case AMF_OBJECT: + case AMF_ECMA_ARRAY: + _value.object = new mapType; + break; + case AMF_STRING: + _value.string = new std::string; + break; + case AMF_STRICT_ARRAY: + _value.array = new arrayType; + break; - default: - break; - } + default: + break; + } } AMFValue::AMFValue(AMFType type) : - _type(type) { - init(); + _type(type) { + init(); } AMFValue::~AMFValue() { - destroy(); + destroy(); } AMFValue::AMFValue(const char *s) : - _type(AMF_STRING) { - init(); - *_value.string = s; + _type(AMF_STRING) { + init(); + *_value.string = s; } AMFValue::AMFValue(const std::string &s) : - _type(AMF_STRING) { - init(); - *_value.string = s; + _type(AMF_STRING) { + init(); + *_value.string = s; } AMFValue::AMFValue(double n) : - _type(AMF_NUMBER) { - init(); - _value.number = n; + _type(AMF_NUMBER) { + init(); + _value.number = n; } AMFValue::AMFValue(int i) : - _type(AMF_INTEGER) { - init(); - _value.integer = i; + _type(AMF_INTEGER) { + init(); + _value.integer = i; } AMFValue::AMFValue(bool b) : - _type(AMF_BOOLEAN) { - init(); - _value.boolean = b; + _type(AMF_BOOLEAN) { + init(); + _value.boolean = b; } AMFValue::AMFValue(const AMFValue &from) : - _type(AMF_NULL) { - *this = from; + _type(AMF_NULL) { + *this = from; } AMFValue::AMFValue(AMFValue &&from) { - *this = std::forward(from); + *this = std::forward(from); } AMFValue& AMFValue::operator =(const AMFValue &from) { - return *this = const_cast(from); + return *this = const_cast(from); } AMFValue& AMFValue::operator =(AMFValue &&from) { - destroy(); - _type = from._type; - init(); - switch (_type) { - case AMF_STRING: - *_value.string = (*from._value.string); - break; - case AMF_OBJECT: - case AMF_ECMA_ARRAY: - *_value.object = (*from._value.object); - break; - case AMF_STRICT_ARRAY: - *_value.array = (*from._value.array); - break; - case AMF_NUMBER: - _value.number = from._value.number; - break; - case AMF_INTEGER: - _value.integer = from._value.integer; - break; - case AMF_BOOLEAN: - _value.boolean = from._value.boolean; - break; - default: - break; - } - return *this; + destroy(); + _type = from._type; + init(); + switch (_type) { + case AMF_STRING: + *_value.string = (*from._value.string); + break; + case AMF_OBJECT: + case AMF_ECMA_ARRAY: + *_value.object = (*from._value.object); + break; + case AMF_STRICT_ARRAY: + *_value.array = (*from._value.array); + break; + case AMF_NUMBER: + _value.number = from._value.number; + break; + case AMF_INTEGER: + _value.integer = from._value.integer; + break; + case AMF_BOOLEAN: + _value.boolean = from._value.boolean; + break; + default: + break; + } + return *this; } @@ -305,156 +305,156 @@ const AMFValue::arrayType &AMFValue::getArr() const { /////////////////////////////////////////////////////////////////////////// enum { - AMF0_NUMBER, - AMF0_BOOLEAN, - AMF0_STRING, - AMF0_OBJECT, - AMF0_MOVIECLIP, - AMF0_NULL, - AMF0_UNDEFINED, - AMF0_REFERENCE, - AMF0_ECMA_ARRAY, - AMF0_OBJECT_END, - AMF0_STRICT_ARRAY, - AMF0_DATE, - AMF0_LONG_STRING, - AMF0_UNSUPPORTED, - AMF0_RECORD_SET, - AMF0_XML_OBJECT, - AMF0_TYPED_OBJECT, - AMF0_SWITCH_AMF3, + AMF0_NUMBER, + AMF0_BOOLEAN, + AMF0_STRING, + AMF0_OBJECT, + AMF0_MOVIECLIP, + AMF0_NULL, + AMF0_UNDEFINED, + AMF0_REFERENCE, + AMF0_ECMA_ARRAY, + AMF0_OBJECT_END, + AMF0_STRICT_ARRAY, + AMF0_DATE, + AMF0_LONG_STRING, + AMF0_UNSUPPORTED, + AMF0_RECORD_SET, + AMF0_XML_OBJECT, + AMF0_TYPED_OBJECT, + AMF0_SWITCH_AMF3, }; enum { - AMF3_UNDEFINED, - AMF3_NULL, - AMF3_FALSE, - AMF3_TRUE, - AMF3_INTEGER, - AMF3_NUMBER, - AMF3_STRING, - AMF3_LEGACY_XML, - AMF3_DATE, - AMF3_ARRAY, - AMF3_OBJECT, - AMF3_XML, - AMF3_BYTE_ARRAY, + AMF3_UNDEFINED, + AMF3_NULL, + AMF3_FALSE, + AMF3_TRUE, + AMF3_INTEGER, + AMF3_NUMBER, + AMF3_STRING, + AMF3_LEGACY_XML, + AMF3_DATE, + AMF3_ARRAY, + AMF3_OBJECT, + AMF3_XML, + AMF3_BYTE_ARRAY, }; ////////////////////////////////Encoder////////////////////////////////////////// AMFEncoder & AMFEncoder::operator <<(const char *s) { - if (s) { - buf += char(AMF0_STRING); - uint16_t str_len = htons(strlen(s)); - buf.append((char *) &str_len, 2); - buf += s; - } else { - buf += char(AMF0_NULL); - } - return *this; + if (s) { + buf += char(AMF0_STRING); + uint16_t str_len = htons(strlen(s)); + buf.append((char *) &str_len, 2); + buf += s; + } else { + buf += char(AMF0_NULL); + } + return *this; } AMFEncoder & AMFEncoder::operator <<(const std::string &s) { - if (!s.empty()) { - buf += char(AMF0_STRING); - uint16_t str_len = htons(s.size()); - buf.append((char *) &str_len, 2); - buf += s; - } else { - buf += char(AMF0_NULL); - } - return *this; + if (!s.empty()) { + buf += char(AMF0_STRING); + uint16_t str_len = htons(s.size()); + buf.append((char *) &str_len, 2); + buf += s; + } else { + buf += char(AMF0_NULL); + } + return *this; } AMFEncoder & AMFEncoder::operator <<(std::nullptr_t) { - buf += char(AMF0_NULL); - return *this; + buf += char(AMF0_NULL); + return *this; } AMFEncoder & AMFEncoder::write_undefined() { - buf += char(AMF0_UNDEFINED); - return *this; + buf += char(AMF0_UNDEFINED); + return *this; } AMFEncoder & AMFEncoder::operator <<(const int n){ - return (*this) << (double)n; + return (*this) << (double)n; } AMFEncoder & AMFEncoder::operator <<(const double n) { - buf += char(AMF0_NUMBER); - uint64_t encoded = 0; - memcpy(&encoded, &n, 8); - uint32_t val = htonl(encoded >> 32); - buf.append((char *) &val, 4); - val = htonl(encoded); - buf.append((char *) &val, 4); - return *this; + buf += char(AMF0_NUMBER); + uint64_t encoded = 0; + memcpy(&encoded, &n, 8); + uint32_t val = htonl(encoded >> 32); + buf.append((char *) &val, 4); + val = htonl(encoded); + buf.append((char *) &val, 4); + return *this; } AMFEncoder & AMFEncoder::operator <<(const bool b) { - buf += char(AMF0_BOOLEAN); - buf += char(b); - return *this; + buf += char(AMF0_BOOLEAN); + buf += char(b); + return *this; } AMFEncoder & AMFEncoder::operator <<(const AMFValue& value) { - switch ((int) value.type()) { - case AMF_STRING: - *this << value.as_string(); - break; - case AMF_NUMBER: - *this << value.as_number(); - break; - case AMF_INTEGER: - *this << value.as_integer(); - break; - case AMF_BOOLEAN: - *this << value.as_boolean(); - break; - case AMF_OBJECT: { - buf += char(AMF0_OBJECT); - for (auto &pr : value.getMap()) { - write_key(pr.first); - *this << pr.second; - } - write_key(""); - buf += char(AMF0_OBJECT_END); - } - break; - case AMF_ECMA_ARRAY: { - buf += char(AMF0_ECMA_ARRAY); - uint32_t sz = htonl(value.getMap().size()); - buf.append((char *) &sz, 4); - for (auto &pr : value.getMap()) { - write_key(pr.first); - *this << pr.second; - } - write_key(""); - buf += char(AMF0_OBJECT_END); - } - break; - case AMF_NULL: - *this << nullptr; - break; - case AMF_UNDEFINED: - this->write_undefined(); - break; - case AMF_STRICT_ARRAY: { - buf += char(AMF0_STRICT_ARRAY); - uint32_t sz = htonl(value.getArr().size()); - buf.append((char *) &sz, 4); - for (auto &val : value.getArr()) { - *this << val; - } - //write_key(""); - //buf += char(AMF0_OBJECT_END); - } - break; - } - return *this; + switch ((int) value.type()) { + case AMF_STRING: + *this << value.as_string(); + break; + case AMF_NUMBER: + *this << value.as_number(); + break; + case AMF_INTEGER: + *this << value.as_integer(); + break; + case AMF_BOOLEAN: + *this << value.as_boolean(); + break; + case AMF_OBJECT: { + buf += char(AMF0_OBJECT); + for (auto &pr : value.getMap()) { + write_key(pr.first); + *this << pr.second; + } + write_key(""); + buf += char(AMF0_OBJECT_END); + } + break; + case AMF_ECMA_ARRAY: { + buf += char(AMF0_ECMA_ARRAY); + uint32_t sz = htonl(value.getMap().size()); + buf.append((char *) &sz, 4); + for (auto &pr : value.getMap()) { + write_key(pr.first); + *this << pr.second; + } + write_key(""); + buf += char(AMF0_OBJECT_END); + } + break; + case AMF_NULL: + *this << nullptr; + break; + case AMF_UNDEFINED: + this->write_undefined(); + break; + case AMF_STRICT_ARRAY: { + buf += char(AMF0_STRICT_ARRAY); + uint32_t sz = htonl(value.getArr().size()); + buf.append((char *) &sz, 4); + for (auto &val : value.getArr()) { + *this << val; + } + //write_key(""); + //buf += char(AMF0_OBJECT_END); + } + break; + } + return *this; } void AMFEncoder::write_key(const std::string& s) { - uint16_t str_len = htons(s.size()); - buf.append((char *) &str_len, 2); - buf += s; + uint16_t str_len = htons(s.size()); + buf.append((char *) &str_len, 2); + buf += s; } void AMFEncoder::clear() { @@ -468,237 +468,237 @@ const std::string& AMFEncoder::data() const { //////////////////Decoder////////////////// uint8_t AMFDecoder::front() { - if (pos >= buf.size()) { - throw std::runtime_error("Not enough data"); - } - return uint8_t(buf[pos]); + if (pos >= buf.size()) { + throw std::runtime_error("Not enough data"); + } + return uint8_t(buf[pos]); } uint8_t AMFDecoder::pop_front() { - if (version == 0 && front() == AMF0_SWITCH_AMF3) { - InfoL << "entering AMF3 mode"; - pos++; - version = 3; - } + if (version == 0 && front() == AMF0_SWITCH_AMF3) { + InfoL << "entering AMF3 mode"; + pos++; + version = 3; + } - if (pos >= buf.size()) { - throw std::runtime_error("Not enough data"); - } - return uint8_t(buf[pos++]); + if (pos >= buf.size()) { + throw std::runtime_error("Not enough data"); + } + return uint8_t(buf[pos++]); } template<> double AMFDecoder::load() { - if (pop_front() != AMF0_NUMBER) { - throw std::runtime_error("Expected a number"); - } - if (pos + 8 > buf.size()) { - throw std::runtime_error("Not enough data"); - } - uint64_t val = ((uint64_t) load_be32(&buf[pos]) << 32) - | load_be32(&buf[pos + 4]); - double n = 0; - memcpy(&n, &val, 8); - pos += 8; - return n; + if (pop_front() != AMF0_NUMBER) { + throw std::runtime_error("Expected a number"); + } + if (pos + 8 > buf.size()) { + throw std::runtime_error("Not enough data"); + } + uint64_t val = ((uint64_t) load_be32(&buf[pos]) << 32) + | load_be32(&buf[pos + 4]); + double n = 0; + memcpy(&n, &val, 8); + pos += 8; + return n; } template<> bool AMFDecoder::load() { - if (pop_front() != AMF0_BOOLEAN) { - throw std::runtime_error("Expected a boolean"); - } - return pop_front() != 0; + if (pop_front() != AMF0_BOOLEAN) { + throw std::runtime_error("Expected a boolean"); + } + return pop_front() != 0; } template<> unsigned int AMFDecoder::load() { - unsigned int value = 0; - for (int i = 0; i < 4; ++i) { - uint8_t b = pop_front(); - if (i == 3) { - /* use all bits from 4th byte */ - value = (value << 8) | b; - break; - } - value = (value << 7) | (b & 0x7f); - if ((b & 0x80) == 0) - break; - } - return value; + unsigned int value = 0; + for (int i = 0; i < 4; ++i) { + uint8_t b = pop_front(); + if (i == 3) { + /* use all bits from 4th byte */ + value = (value << 8) | b; + break; + } + value = (value << 7) | (b & 0x7f); + if ((b & 0x80) == 0) + break; + } + return value; } template<> int AMFDecoder::load() { - if (version == 3) { - return load(); - } else { - return load(); - } + if (version == 3) { + return load(); + } else { + return load(); + } } template<> std::string AMFDecoder::load() { - size_t str_len = 0; - uint8_t type = pop_front(); - if (version == 3) { - if (type != AMF3_STRING) { - throw std::runtime_error("Expected a string"); - } - str_len = load() / 2; + size_t str_len = 0; + uint8_t type = pop_front(); + if (version == 3) { + if (type != AMF3_STRING) { + throw std::runtime_error("Expected a string"); + } + str_len = load() / 2; - } else { - if (type != AMF0_STRING) { - throw std::runtime_error("Expected a string"); - } - if (pos + 2 > buf.size()) { - throw std::runtime_error("Not enough data"); - } - str_len = load_be16(&buf[pos]); - pos += 2; - } - if (pos + str_len > buf.size()) { - throw std::runtime_error("Not enough data"); - } - std::string s(buf, pos, str_len); - pos += str_len; - return s; + } else { + if (type != AMF0_STRING) { + throw std::runtime_error("Expected a string"); + } + if (pos + 2 > buf.size()) { + throw std::runtime_error("Not enough data"); + } + str_len = load_be16(&buf[pos]); + pos += 2; + } + if (pos + str_len > buf.size()) { + throw std::runtime_error("Not enough data"); + } + std::string s(buf, pos, str_len); + pos += str_len; + return s; } template<> AMFValue AMFDecoder::load() { - uint8_t type = front(); - if (version == 3) { - switch (type) { - case AMF3_STRING: - return load(); - case AMF3_NUMBER: - return load(); - case AMF3_INTEGER: - return load(); - case AMF3_FALSE: - pos++; - return false; - case AMF3_TRUE: - pos++; - return true; - case AMF3_OBJECT: - return load_object(); - case AMF3_ARRAY: - return load_ecma(); - case AMF3_NULL: - pos++; - return AMF_NULL; - case AMF3_UNDEFINED: - pos++; - return AMF_UNDEFINED; - default: - throw std::runtime_error( - StrPrinter << "Unsupported AMF3 type:" << (int) type << endl); - } - } else { - switch (type) { - case AMF0_STRING: - return load(); - case AMF0_NUMBER: - return load(); - case AMF0_BOOLEAN: - return load(); - case AMF0_OBJECT: - return load_object(); - case AMF0_ECMA_ARRAY: - return load_ecma(); - case AMF0_NULL: - pos++; - return AMF_NULL; - case AMF0_UNDEFINED: - pos++; - return AMF_UNDEFINED; - case AMF0_STRICT_ARRAY: - return load_arr(); - default: - throw std::runtime_error( - StrPrinter << "Unsupported AMF type:" << (int) type << endl); - } - } + uint8_t type = front(); + if (version == 3) { + switch (type) { + case AMF3_STRING: + return load(); + case AMF3_NUMBER: + return load(); + case AMF3_INTEGER: + return load(); + case AMF3_FALSE: + pos++; + return false; + case AMF3_TRUE: + pos++; + return true; + case AMF3_OBJECT: + return load_object(); + case AMF3_ARRAY: + return load_ecma(); + case AMF3_NULL: + pos++; + return AMF_NULL; + case AMF3_UNDEFINED: + pos++; + return AMF_UNDEFINED; + default: + throw std::runtime_error( + StrPrinter << "Unsupported AMF3 type:" << (int) type << endl); + } + } else { + switch (type) { + case AMF0_STRING: + return load(); + case AMF0_NUMBER: + return load(); + case AMF0_BOOLEAN: + return load(); + case AMF0_OBJECT: + return load_object(); + case AMF0_ECMA_ARRAY: + return load_ecma(); + case AMF0_NULL: + pos++; + return AMF_NULL; + case AMF0_UNDEFINED: + pos++; + return AMF_UNDEFINED; + case AMF0_STRICT_ARRAY: + return load_arr(); + default: + throw std::runtime_error( + StrPrinter << "Unsupported AMF type:" << (int) type << endl); + } + } } std::string AMFDecoder::load_key() { - if (pos + 2 > buf.size()) { - throw std::runtime_error("Not enough data"); - } - size_t str_len = load_be16(&buf[pos]); - pos += 2; - if (pos + str_len > buf.size()) { - throw std::runtime_error("Not enough data"); - } - std::string s(buf, pos, str_len); - pos += str_len; - return s; + if (pos + 2 > buf.size()) { + throw std::runtime_error("Not enough data"); + } + size_t str_len = load_be16(&buf[pos]); + pos += 2; + if (pos + str_len > buf.size()) { + throw std::runtime_error("Not enough data"); + } + std::string s(buf, pos, str_len); + pos += str_len; + return s; } AMFValue AMFDecoder::load_object() { - AMFValue object(AMF_OBJECT); - if (pop_front() != AMF0_OBJECT) { - throw std::runtime_error("Expected an object"); - } - while (1) { - std::string key = load_key(); - if (key.empty()) - break; - AMFValue value = load(); - object.set(key, value); - } - if (pop_front() != AMF0_OBJECT_END) { - throw std::runtime_error("expected object end"); - } - return object; + AMFValue object(AMF_OBJECT); + if (pop_front() != AMF0_OBJECT) { + throw std::runtime_error("Expected an object"); + } + while (1) { + std::string key = load_key(); + if (key.empty()) + break; + AMFValue value = load(); + object.set(key, value); + } + if (pop_front() != AMF0_OBJECT_END) { + throw std::runtime_error("expected object end"); + } + return object; } AMFValue AMFDecoder::load_ecma() { - /* ECMA array is the same as object, with 4 extra zero bytes */ - AMFValue object(AMF_ECMA_ARRAY); - if (pop_front() != AMF0_ECMA_ARRAY) { - throw std::runtime_error("Expected an ECMA array"); - } - if (pos + 4 > buf.size()) { - throw std::runtime_error("Not enough data"); - } - pos += 4; - while (1) { - std::string key = load_key(); - if (key.empty()) - break; - AMFValue value = load(); - object.set(key, value); - } - if (pop_front() != AMF0_OBJECT_END) { - throw std::runtime_error("expected object end"); - } - return object; + /* ECMA array is the same as object, with 4 extra zero bytes */ + AMFValue object(AMF_ECMA_ARRAY); + if (pop_front() != AMF0_ECMA_ARRAY) { + throw std::runtime_error("Expected an ECMA array"); + } + if (pos + 4 > buf.size()) { + throw std::runtime_error("Not enough data"); + } + pos += 4; + while (1) { + std::string key = load_key(); + if (key.empty()) + break; + AMFValue value = load(); + object.set(key, value); + } + if (pop_front() != AMF0_OBJECT_END) { + throw std::runtime_error("expected object end"); + } + return object; } AMFValue AMFDecoder::load_arr() { - /* ECMA array is the same as object, with 4 extra zero bytes */ - AMFValue object(AMF_STRICT_ARRAY); - if (pop_front() != AMF0_STRICT_ARRAY) { - throw std::runtime_error("Expected an STRICT array"); - } - if (pos + 4 > buf.size()) { - throw std::runtime_error("Not enough data"); - } - int arrSize = load_be32(&buf[pos]); - pos += 4; - while (arrSize--) { - AMFValue value = load(); - object.add(value); - } - /*pos += 2; - if (pop_front() != AMF0_OBJECT_END) { - throw std::runtime_error("expected object end"); - }*/ - return object; + /* ECMA array is the same as object, with 4 extra zero bytes */ + AMFValue object(AMF_STRICT_ARRAY); + if (pop_front() != AMF0_STRICT_ARRAY) { + throw std::runtime_error("Expected an STRICT array"); + } + if (pos + 4 > buf.size()) { + throw std::runtime_error("Not enough data"); + } + int arrSize = load_be32(&buf[pos]); + pos += 4; + while (arrSize--) { + AMFValue value = load(); + object.add(value); + } + /*pos += 2; + if (pop_front() != AMF0_OBJECT_END) { + throw std::runtime_error("expected object end"); + }*/ + return object; } AMFDecoder::AMFDecoder(const std::string &buf_in, size_t pos_in, int version_in) : diff --git a/src/Rtmp/amf.h b/src/Rtmp/amf.h index da299b41..fbcfaf02 100644 --- a/src/Rtmp/amf.h +++ b/src/Rtmp/amf.h @@ -36,15 +36,15 @@ using namespace std; enum AMFType { - AMF_NUMBER, - AMF_INTEGER, - AMF_BOOLEAN, - AMF_STRING, - AMF_OBJECT, - AMF_NULL, - AMF_UNDEFINED, - AMF_ECMA_ARRAY, - AMF_STRICT_ARRAY, + AMF_NUMBER, + AMF_INTEGER, + AMF_BOOLEAN, + AMF_STRING, + AMF_OBJECT, + AMF_NULL, + AMF_UNDEFINED, + AMF_ECMA_ARRAY, + AMF_STRICT_ARRAY, }; class AMFValue; @@ -55,79 +55,79 @@ public: typedef std::map mapType; typedef std::vector arrayType; - AMFValue(AMFType type = AMF_NULL); - AMFValue(const char *s); - AMFValue(const std::string &s); - AMFValue(double n); - AMFValue(int i); - AMFValue(bool b); - AMFValue(const AMFValue &from); - AMFValue(AMFValue &&from); - AMFValue &operator =(const AMFValue &from); - AMFValue &operator =(AMFValue &&from); - ~AMFValue(); + AMFValue(AMFType type = AMF_NULL); + AMFValue(const char *s); + AMFValue(const std::string &s); + AMFValue(double n); + AMFValue(int i); + AMFValue(bool b); + AMFValue(const AMFValue &from); + AMFValue(AMFValue &&from); + AMFValue &operator =(const AMFValue &from); + AMFValue &operator =(AMFValue &&from); + ~AMFValue(); - void clear(); - AMFType type() const ; - const std::string &as_string() const; - double as_number() const; - int as_integer() const; + void clear(); + AMFType type() const ; + const std::string &as_string() const; + double as_number() const; + int as_integer() const; bool as_boolean() const; - string to_string() const; - const AMFValue &operator[](const char *str) const; - void object_for_each(const function &fun) const ; - operator bool() const; - void set(const std::string &s, const AMFValue &val); - void add(const AMFValue &val); + string to_string() const; + const AMFValue &operator[](const char *str) const; + void object_for_each(const function &fun) const ; + operator bool() const; + void set(const std::string &s, const AMFValue &val); + void add(const AMFValue &val); private: const mapType &getMap() const; const arrayType &getArr() const; void destroy(); void init(); private: - AMFType _type; - union { - std::string *string; - double number; - int integer; - bool boolean; - mapType *object; - arrayType *array; - } _value; + AMFType _type; + union { + std::string *string; + double number; + int integer; + bool boolean; + mapType *object; + arrayType *array; + } _value; }; class AMFDecoder { public: - AMFDecoder(const std::string &buf, size_t pos, int version = 0); - template - TP load(); + AMFDecoder(const std::string &buf, size_t pos, int version = 0); + template + TP load(); private: - std::string load_key(); - AMFValue load_object(); - AMFValue load_ecma(); - AMFValue load_arr(); - uint8_t front(); - uint8_t pop_front(); + std::string load_key(); + AMFValue load_object(); + AMFValue load_ecma(); + AMFValue load_arr(); + uint8_t front(); + uint8_t pop_front(); private: - const std::string &buf; - size_t pos; - int version; + const std::string &buf; + size_t pos; + int version; }; class AMFEncoder { public: - AMFEncoder & operator <<(const char *s); - AMFEncoder & operator <<(const std::string &s); - AMFEncoder & operator <<(std::nullptr_t); - AMFEncoder & operator <<(const int n); - AMFEncoder & operator <<(const double n); - AMFEncoder & operator <<(const bool b); - AMFEncoder & operator <<(const AMFValue &value); - const std::string& data() const ; - void clear() ; + AMFEncoder & operator <<(const char *s); + AMFEncoder & operator <<(const std::string &s); + AMFEncoder & operator <<(std::nullptr_t); + AMFEncoder & operator <<(const int n); + AMFEncoder & operator <<(const double n); + AMFEncoder & operator <<(const bool b); + AMFEncoder & operator <<(const AMFValue &value); + const std::string& data() const ; + void clear() ; private: - void write_key(const std::string &s); - AMFEncoder &write_undefined(); + void write_key(const std::string &s); + AMFEncoder &write_undefined(); private: std::string buf; }; diff --git a/src/Rtmp/utils.cpp b/src/Rtmp/utils.cpp index d9a668eb..3f3f93ae 100644 --- a/src/Rtmp/utils.cpp +++ b/src/Rtmp/utils.cpp @@ -38,54 +38,54 @@ using namespace toolkit; */ uint32_t load_be32(const void *p) { - uint32_t val; - memcpy(&val, p, sizeof val); - return ntohl(val); + uint32_t val; + memcpy(&val, p, sizeof val); + return ntohl(val); } uint16_t load_be16(const void *p) { - uint16_t val; - memcpy(&val, p, sizeof val); - return ntohs(val); + uint16_t val; + memcpy(&val, p, sizeof val); + return ntohs(val); } uint32_t load_le32(const void *p) { - const uint8_t *data = (const uint8_t *) p; - return data[0] | ((uint32_t) data[1] << 8) | - ((uint32_t) data[2] << 16) | ((uint32_t) data[3] << 24); + const uint8_t *data = (const uint8_t *) p; + return data[0] | ((uint32_t) data[1] << 8) | + ((uint32_t) data[2] << 16) | ((uint32_t) data[3] << 24); } uint32_t load_be24(const void *p) { - const uint8_t *data = (const uint8_t *) p; - return data[2] | ((uint32_t) data[1] << 8) | ((uint32_t) data[0] << 16); + const uint8_t *data = (const uint8_t *) p; + return data[2] | ((uint32_t) data[1] << 8) | ((uint32_t) data[0] << 16); } void set_be24(void *p, uint32_t val) { - uint8_t *data = (uint8_t *) p; - data[0] = val >> 16; - data[1] = val >> 8; - data[2] = val; + uint8_t *data = (uint8_t *) p; + data[0] = val >> 16; + data[1] = val >> 8; + data[2] = val; } void set_le32(void *p, uint32_t val) { - uint8_t *data = (uint8_t *) p; - data[0] = val; - data[1] = val >> 8; - data[2] = val >> 16; - data[3] = val >> 24; + uint8_t *data = (uint8_t *) p; + data[0] = val; + data[1] = val >> 8; + data[2] = val >> 16; + data[3] = val >> 24; } void set_be32(void *p, uint32_t val) { - uint8_t *data = (uint8_t *) p; - data[3] = val; - data[2] = val >> 8; - data[1] = val >> 16; - data[0] = val >> 24; + uint8_t *data = (uint8_t *) p; + data[3] = val; + data[2] = val >> 8; + data[1] = val >> 16; + data[0] = val >> 24; } diff --git a/src/Rtsp/RtpMultiCaster.cpp b/src/Rtsp/RtpMultiCaster.cpp index 1de5bcfe..8c98fc32 100644 --- a/src/Rtsp/RtpMultiCaster.cpp +++ b/src/Rtsp/RtpMultiCaster.cpp @@ -37,47 +37,47 @@ using namespace toolkit; namespace mediakit{ MultiCastAddressMaker &MultiCastAddressMaker::Instance() { - static MultiCastAddressMaker instance; - return instance; + static MultiCastAddressMaker instance; + return instance; } static uint32_t addressToInt(const string &ip){ struct in_addr 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); } std::shared_ptr MultiCastAddressMaker::obtain(uint32_t iTry) { - lock_guard lck(_mtx); + lock_guard lck(_mtx); GET_CONFIG(string,addrMinStr,MultiCast::kAddrMin); GET_CONFIG(string,addrMaxStr,MultiCast::kAddrMax); uint32_t addrMin = addressToInt(addrMinStr); - uint32_t addrMax = addressToInt(addrMaxStr); + uint32_t addrMax = addressToInt(addrMaxStr); - if(_iAddr > addrMax || _iAddr == 0){ - _iAddr = addrMin; - } - auto iGotAddr = _iAddr++; - if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){ - //已经分配过了 - if(iTry){ - return obtain(--iTry); - } - //分配完了,应该不可能到这里 - ErrorL; - return nullptr; - } - _setBadAddr.emplace(iGotAddr); - std::shared_ptr ret(new uint32_t(iGotAddr),[](uint32_t *ptr){ - MultiCastAddressMaker::Instance().release(*ptr); - delete ptr; - }); - return ret; + if(_iAddr > addrMax || _iAddr == 0){ + _iAddr = addrMin; + } + auto iGotAddr = _iAddr++; + if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){ + //已经分配过了 + if(iTry){ + return obtain(--iTry); + } + //分配完了,应该不可能到这里 + ErrorL; + return nullptr; + } + _setBadAddr.emplace(iGotAddr); + std::shared_ptr ret(new uint32_t(iGotAddr),[](uint32_t *ptr){ + MultiCastAddressMaker::Instance().release(*ptr); + delete ptr; + }); + return ret; } void MultiCastAddressMaker::release(uint32_t iAddr){ - lock_guard lck(_mtx); - _setBadAddr.erase(iAddr); + lock_guard lck(_mtx); + _setBadAddr.erase(iAddr); } @@ -85,106 +85,106 @@ recursive_mutex RtpMultiCaster::g_mtx; unordered_map > RtpMultiCaster::g_mapBroadCaster; void RtpMultiCaster::setDetachCB(void* listener, const onDetach& cb) { - lock_guard lck(_mtx); - if(cb){ - _mapDetach.emplace(listener,cb); - }else{ - _mapDetach.erase(listener); - } + lock_guard lck(_mtx); + if(cb){ + _mapDetach.emplace(listener,cb); + }else{ + _mapDetach.erase(listener); + } } RtpMultiCaster::~RtpMultiCaster() { - _pReader->setReadCB(nullptr); - _pReader->setDetachCB(nullptr); - DebugL; + _pReader->setReadCB(nullptr); + _pReader->setDetachCB(nullptr); + DebugL; } RtpMultiCaster::RtpMultiCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) { - auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream)); - if(!src){ - auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl; - throw std::runtime_error(strErr); - } - _multiAddr = MultiCastAddressMaker::Instance().obtain(); - for(auto i = 0; i < 2; i++){ - _apUdpSock[i].reset(new Socket(poller)); - if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){ - auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl; - throw std::runtime_error(strErr); - } - auto fd = _apUdpSock[i]->rawFD(); + auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream)); + if(!src){ + auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl; + throw std::runtime_error(strErr); + } + _multiAddr = MultiCastAddressMaker::Instance().obtain(); + for(auto i = 0; i < 2; i++){ + _apUdpSock[i].reset(new Socket(poller)); + if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){ + auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl; + throw std::runtime_error(strErr); + } + auto fd = _apUdpSock[i]->rawFD(); GET_CONFIG(uint32_t,udpTTL,MultiCast::kUdpTTL); SockUtil::setMultiTTL(fd, udpTTL); - SockUtil::setMultiLOOP(fd, false); - SockUtil::setMultiIF(fd, strLocalIp.data()); + SockUtil::setMultiLOOP(fd, false); + SockUtil::setMultiIF(fd, strLocalIp.data()); - struct sockaddr_in &peerAddr = _aPeerUdpAddr[i]; - peerAddr.sin_family = AF_INET; - peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port()); - peerAddr.sin_addr.s_addr = htonl(*_multiAddr); - bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero); - _apUdpSock[i]->setSendPeerAddr((struct sockaddr *)&peerAddr); - } - _pReader = src->getRing()->attach(poller); - _pReader->setReadCB([this](const RtpPacket::Ptr &pkt){ - int i = (int)(pkt->type); - auto &pSock = _apUdpSock[i]; - auto &peerAddr = _aPeerUdpAddr[i]; + struct sockaddr_in &peerAddr = _aPeerUdpAddr[i]; + peerAddr.sin_family = AF_INET; + peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port()); + peerAddr.sin_addr.s_addr = htonl(*_multiAddr); + bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero); + _apUdpSock[i]->setSendPeerAddr((struct sockaddr *)&peerAddr); + } + _pReader = src->getRing()->attach(poller); + _pReader->setReadCB([this](const RtpPacket::Ptr &pkt){ + int i = (int)(pkt->type); + auto &pSock = _apUdpSock[i]; + auto &peerAddr = _aPeerUdpAddr[i]; BufferRtp::Ptr buffer(new BufferRtp(pkt,4)); - pSock->send(buffer); - }); - _pReader->setDetachCB([this](){ - unordered_map _mapDetach_copy; - { - lock_guard lck(_mtx); - _mapDetach_copy = std::move(_mapDetach); - } - for(auto &pr : _mapDetach_copy){ - pr.second(); - } - }); - DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " " - << _apUdpSock[0]->get_local_port() << " " - << _apUdpSock[1]->get_local_port() << " " + pSock->send(buffer); + }); + _pReader->setDetachCB([this](){ + unordered_map _mapDetach_copy; + { + lock_guard lck(_mtx); + _mapDetach_copy = std::move(_mapDetach); + } + for(auto &pr : _mapDetach_copy){ + pr.second(); + } + }); + DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " " + << _apUdpSock[0]->get_local_port() << " " + << _apUdpSock[1]->get_local_port() << " " << strVhost << " " - << strApp << " " << strStream; + << strApp << " " << strStream; } uint16_t RtpMultiCaster::getPort(TrackType trackType){ - return _apUdpSock[trackType]->get_local_port(); + return _apUdpSock[trackType]->get_local_port(); } 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){ - try{ - auto ret = Ptr(new RtpMultiCaster(poller,strLocalIp,strVhost,strApp,strStream),[poller](RtpMultiCaster *ptr){ + try{ + auto ret = Ptr(new RtpMultiCaster(poller,strLocalIp,strVhost,strApp,strStream),[poller](RtpMultiCaster *ptr){ poller->async([ptr]() { delete ptr; }); - }); - lock_guard lck(g_mtx); - string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl; - weak_ptr weakPtr = ret; - g_mapBroadCaster.emplace(strKey,weakPtr); - return ret; - }catch (std::exception &ex) { - WarnL << ex.what(); - return nullptr; - } + }); + lock_guard lck(g_mtx); + string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl; + weak_ptr weakPtr = ret; + g_mapBroadCaster.emplace(strKey,weakPtr); + return ret; + }catch (std::exception &ex) { + WarnL << ex.what(); + return nullptr; + } } 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; - lock_guard lck(g_mtx); - auto it = g_mapBroadCaster.find(strKey); - if (it == g_mapBroadCaster.end()) { - return make(poller,strLocalIp,strVhost,strApp, strStream); - } - auto ret = it->second.lock(); - if (!ret) { - g_mapBroadCaster.erase(it); - return make(poller,strLocalIp,strVhost,strApp, strStream); - } - return ret; + string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl; + lock_guard lck(g_mtx); + auto it = g_mapBroadCaster.find(strKey); + if (it == g_mapBroadCaster.end()) { + return make(poller,strLocalIp,strVhost,strApp, strStream); + } + auto ret = it->second.lock(); + if (!ret) { + g_mapBroadCaster.erase(it); + return make(poller,strLocalIp,strVhost,strApp, strStream); + } + return ret; } diff --git a/src/Rtsp/RtpMultiCaster.h b/src/Rtsp/RtpMultiCaster.h index e95802b1..4c15e14a 100644 --- a/src/Rtsp/RtpMultiCaster.h +++ b/src/Rtsp/RtpMultiCaster.h @@ -45,48 +45,48 @@ namespace mediakit{ class MultiCastAddressMaker { public: - static MultiCastAddressMaker &Instance(); + static MultiCastAddressMaker &Instance(); - static bool isMultiCastAddress(uint32_t iAddr){ - static uint32_t addrMin = mINI::Instance()[MultiCast::kAddrMin].as(); - static uint32_t addrMax = mINI::Instance()[MultiCast::kAddrMax].as(); - return iAddr >= addrMin && iAddr <= addrMax; - } - static string toString(uint32_t iAddr){ - iAddr = htonl(iAddr); - return ::inet_ntoa((struct in_addr &)(iAddr)); - } - virtual ~MultiCastAddressMaker(){} - std::shared_ptr obtain(uint32_t iTry = 10); + static bool isMultiCastAddress(uint32_t iAddr){ + static uint32_t addrMin = mINI::Instance()[MultiCast::kAddrMin].as(); + static uint32_t addrMax = mINI::Instance()[MultiCast::kAddrMax].as(); + return iAddr >= addrMin && iAddr <= addrMax; + } + static string toString(uint32_t iAddr){ + iAddr = htonl(iAddr); + return ::inet_ntoa((struct in_addr &)(iAddr)); + } + virtual ~MultiCastAddressMaker(){} + std::shared_ptr obtain(uint32_t iTry = 10); private: - MultiCastAddressMaker(){}; - void release(uint32_t iAddr); - uint32_t _iAddr = 0; - recursive_mutex _mtx; - unordered_set _setBadAddr; + MultiCastAddressMaker(){}; + void release(uint32_t iAddr); + uint32_t _iAddr = 0; + recursive_mutex _mtx; + unordered_set _setBadAddr; }; class RtpMultiCaster { public: - typedef std::shared_ptr Ptr; - typedef function onDetach; - virtual ~RtpMultiCaster(); - static Ptr get(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); - void setDetachCB(void *listener,const onDetach &cb); - uint16_t getPort(TrackType trackType); - string getIP(); + typedef std::shared_ptr Ptr; + typedef function onDetach; + virtual ~RtpMultiCaster(); + static Ptr get(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); + void setDetachCB(void *listener,const onDetach &cb); + uint16_t getPort(TrackType trackType); + string getIP(); private: - static recursive_mutex g_mtx; - static unordered_map > g_mapBroadCaster; - static Ptr make(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); + static recursive_mutex g_mtx; + static unordered_map > g_mapBroadCaster; + static Ptr make(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); - std::shared_ptr _multiAddr; - recursive_mutex _mtx; - unordered_map _mapDetach; - RtspMediaSource::RingType::RingReader::Ptr _pReader; - Socket::Ptr _apUdpSock[2]; - struct sockaddr_in _aPeerUdpAddr[2]; + std::shared_ptr _multiAddr; + recursive_mutex _mtx; + unordered_map _mapDetach; + RtspMediaSource::RingType::RingReader::Ptr _pReader; + Socket::Ptr _apUdpSock[2]; + struct sockaddr_in _aPeerUdpAddr[2]; - RtpMultiCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); + RtpMultiCaster(const EventPoller::Ptr &poller,const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); }; diff --git a/src/Rtsp/RtpReceiver.cpp b/src/Rtsp/RtpReceiver.cpp index f2ff31f7..e73f150c 100644 --- a/src/Rtsp/RtpReceiver.cpp +++ b/src/Rtsp/RtpReceiver.cpp @@ -28,9 +28,9 @@ #include "RtpReceiver.h" #define POP_HEAD(trackidx) \ - auto it = _rtp_sort_cache_map[trackidx].begin(); \ - onRtpSorted(it->second, trackidx); \ - _rtp_sort_cache_map[trackidx].erase(it); + auto it = _rtp_sort_cache_map[trackidx].begin(); \ + onRtpSorted(it->second, trackidx); \ + _rtp_sort_cache_map[trackidx].erase(it); #define AV_RB16(x) \ ((((const uint8_t*)(x))[0] << 8) | \ diff --git a/src/Rtsp/Rtsp.cpp b/src/Rtsp/Rtsp.cpp index d6d95258..13203199 100644 --- a/src/Rtsp/Rtsp.cpp +++ b/src/Rtsp/Rtsp.cpp @@ -31,176 +31,176 @@ namespace mediakit{ static void getAttrSdp(const map &attr, _StrPrinter &printer){ - const map::value_type *ptr = nullptr; - for(auto &pr : attr){ - if(pr.first == "control"){ - ptr = ≺ - continue; - } - if(pr.second.empty()){ - printer << "a=" << pr.first << "\r\n"; - }else{ - printer << "a=" << pr.first << ":" << pr.second << "\r\n"; - } - } - if(ptr){ - printer << "a=" << ptr->first << ":" << ptr->second << "\r\n"; - } + const map::value_type *ptr = nullptr; + for(auto &pr : attr){ + if(pr.first == "control"){ + ptr = ≺ + continue; + } + if(pr.second.empty()){ + printer << "a=" << pr.first << "\r\n"; + }else{ + printer << "a=" << pr.first << ":" << pr.second << "\r\n"; + } + } + if(ptr){ + printer << "a=" << ptr->first << ":" << ptr->second << "\r\n"; + } } string SdpTrack::toString() const { - _StrPrinter _printer; - switch (_type){ - case TrackTitle:{ - _printer << "v=" << 0 << "\r\n"; - if(!_o.empty()){ - _printer << "o="<< _o << "\r\n"; - } - if(!_c.empty()){ - _printer << "c=" << _c << "\r\n"; - } - if(!_t.empty()){ - _printer << "t=" << _t << "\r\n"; - } + _StrPrinter _printer; + switch (_type){ + case TrackTitle:{ + _printer << "v=" << 0 << "\r\n"; + if(!_o.empty()){ + _printer << "o="<< _o << "\r\n"; + } + if(!_c.empty()){ + _printer << "c=" << _c << "\r\n"; + } + if(!_t.empty()){ + _printer << "t=" << _t << "\r\n"; + } - _printer << "s=RTSP Session, streamed by the ZLMediaKit\r\n"; - _printer << "i=ZLMediaKit Live Stream\r\n"; - getAttrSdp(_attr,_printer); - } - break; - case TrackAudio: - case TrackVideo:{ - if(_type == TrackAudio){ - _printer << "m=audio 0 RTP/AVP " << _pt << "\r\n"; - }else{ - _printer << "m=video 0 RTP/AVP " << _pt << "\r\n"; - } - if(!_b.empty()){ - _printer << "b=" <<_b << "\r\n"; - } - getAttrSdp(_attr,_printer); - } - break; - default: - break; - } - return _printer; + _printer << "s=RTSP Session, streamed by the ZLMediaKit\r\n"; + _printer << "i=ZLMediaKit Live Stream\r\n"; + getAttrSdp(_attr,_printer); + } + break; + case TrackAudio: + case TrackVideo:{ + if(_type == TrackAudio){ + _printer << "m=audio 0 RTP/AVP " << _pt << "\r\n"; + }else{ + _printer << "m=video 0 RTP/AVP " << _pt << "\r\n"; + } + if(!_b.empty()){ + _printer << "b=" <<_b << "\r\n"; + } + getAttrSdp(_attr,_printer); + } + break; + default: + break; + } + return _printer; } static TrackType toTrackType(const string &str) { - if (str == "") { - return TrackTitle; - } + if (str == "") { + return TrackTitle; + } - if (str == "video") { - return TrackVideo; - } + if (str == "video") { + return TrackVideo; + } - if (str == "audio") { - return TrackAudio; - } + if (str == "audio") { + return TrackAudio; + } - return TrackInvalid; + return TrackInvalid; } void SdpParser::load(const string &sdp) { - { - _track_vec.clear(); - string key; - SdpTrack::Ptr track = std::make_shared(); + { + _track_vec.clear(); + string key; + SdpTrack::Ptr track = std::make_shared(); - auto lines = split(sdp, "\n"); - for (auto &line : lines) { - trim(line); - if (line.size() < 2 || line[1] != '=') { - continue; - } - char opt = line[0]; - string opt_val = line.substr(2); - switch (opt) { - case 'o': - track->_o = opt_val; - break; - case 's': - track->_s = opt_val; - break; - case 'i': - track->_i = opt_val; - break; - case 'c': - track->_c = opt_val; - break; - case 't': - track->_t = opt_val; - break; - case 'b': - track->_b = opt_val; - break; - case 'm': { - track->_type = toTrackType(key); - _track_vec.emplace_back(track); - track = std::make_shared(); - key = FindField(opt_val.data(), nullptr, " "); - track->_m = opt_val; - } - break; - case 'a': { - string attr = FindField(opt_val.data(), nullptr, ":"); - if (attr.empty()) { - track->_attr[opt_val] = ""; - } else { - track->_attr[attr] = FindField(opt_val.data(), ":", nullptr); - } - } - break; - default: - track->_other[opt] = opt_val; - break; - } - } - track->_type = toTrackType(key); - _track_vec.emplace_back(track); - } + auto lines = split(sdp, "\n"); + for (auto &line : lines) { + trim(line); + if (line.size() < 2 || line[1] != '=') { + continue; + } + char opt = line[0]; + string opt_val = line.substr(2); + switch (opt) { + case 'o': + track->_o = opt_val; + break; + case 's': + track->_s = opt_val; + break; + case 'i': + track->_i = opt_val; + break; + case 'c': + track->_c = opt_val; + break; + case 't': + track->_t = opt_val; + break; + case 'b': + track->_b = opt_val; + break; + case 'm': { + track->_type = toTrackType(key); + _track_vec.emplace_back(track); + track = std::make_shared(); + key = FindField(opt_val.data(), nullptr, " "); + track->_m = opt_val; + } + break; + case 'a': { + string attr = FindField(opt_val.data(), nullptr, ":"); + if (attr.empty()) { + track->_attr[opt_val] = ""; + } else { + track->_attr[attr] = FindField(opt_val.data(), ":", nullptr); + } + } + break; + default: + track->_other[opt] = opt_val; + break; + } + } + track->_type = toTrackType(key); + _track_vec.emplace_back(track); + } - for (auto &track_ptr : _track_vec) { - auto &track = *track_ptr; - auto it = track._attr.find("range"); - if (it != track._attr.end()) { - char name[16] = {0}, start[16] = {0}, end[16] = {0}; - int ret = sscanf(it->second.data(), "%15[^=]=%15[^-]-%15s", name, start, end); - if (3 == ret || 2 == ret) { - if (strcmp(start, "now") == 0) { - strcpy(start, "0"); - } - track._start = atof(start); - track._end = atof(end); - track._duration = track._end - track._start; - } - } + for (auto &track_ptr : _track_vec) { + auto &track = *track_ptr; + auto it = track._attr.find("range"); + if (it != track._attr.end()) { + char name[16] = {0}, start[16] = {0}, end[16] = {0}; + int ret = sscanf(it->second.data(), "%15[^=]=%15[^-]-%15s", name, start, end); + if (3 == ret || 2 == ret) { + if (strcmp(start, "now") == 0) { + strcpy(start, "0"); + } + track._start = atof(start); + track._end = atof(end); + track._duration = track._end - track._start; + } + } - it = track._attr.find("rtpmap"); - if(it != track._attr.end()){ - auto rtpmap = it->second; - int pt, samplerate; - char codec[16] = {0}; - if (3 == sscanf(rtpmap.data(), "%d %15[^/]/%d", &pt, codec, &samplerate)) { - track._pt = pt; - track._codec = codec; - track._samplerate = samplerate; - } - } + it = track._attr.find("rtpmap"); + if(it != track._attr.end()){ + auto rtpmap = it->second; + int pt, samplerate; + char codec[16] = {0}; + if (3 == sscanf(rtpmap.data(), "%d %15[^/]/%d", &pt, codec, &samplerate)) { + track._pt = pt; + track._codec = codec; + track._samplerate = samplerate; + } + } - it = track._attr.find("fmtp"); - if(it != track._attr.end()) { - track._fmtp = it->second; - } + it = track._attr.find("fmtp"); + if(it != track._attr.end()) { + track._fmtp = it->second; + } - it = track._attr.find("control"); - if(it != track._attr.end()) { - track._control = it->second; - auto surffix = string("/") + track._control; - track._control_surffix = surffix.substr(1 + surffix.rfind('/')); - } - } + it = track._attr.find("control"); + if(it != track._attr.end()) { + track._control = it->second; + auto surffix = string("/") + track._control; + track._control_surffix = surffix.substr(1 + surffix.rfind('/')); + } + } } bool SdpParser::available() const { @@ -208,112 +208,112 @@ bool SdpParser::available() const { } SdpTrack::Ptr SdpParser::getTrack(TrackType type) const { - for (auto &track : _track_vec){ - if(track->_type == type){ - return track; - } - } - return nullptr; + for (auto &track : _track_vec){ + if(track->_type == type){ + return track; + } + } + return nullptr; } vector SdpParser::getAvailableTrack() const { - vector ret; - bool audio_added = false; - bool video_added = false; - for (auto &track : _track_vec){ - if(track->_type == TrackAudio ){ - if(!audio_added){ - ret.emplace_back(track); - audio_added = true; - } - continue; - } + vector ret; + bool audio_added = false; + bool video_added = false; + for (auto &track : _track_vec){ + if(track->_type == TrackAudio ){ + if(!audio_added){ + ret.emplace_back(track); + audio_added = true; + } + continue; + } - if(track->_type == TrackVideo ){ - if(!video_added){ - ret.emplace_back(track); - video_added = true; - } - continue; - } - } - return std::move(ret); + if(track->_type == TrackVideo ){ + if(!video_added){ + ret.emplace_back(track); + video_added = true; + } + continue; + } + } + return std::move(ret); } string SdpParser::toString() const { - string title,audio,video; - for(auto &track : _track_vec){ - switch (track->_type){ - case TrackTitle:{ - title = track->toString(); - } - break; - case TrackVideo:{ - video = track->toString(); - } - break; - case TrackAudio:{ - audio = track->toString(); - } - break; - default: - break; - } - } - return title + video + audio; + string title,audio,video; + for(auto &track : _track_vec){ + switch (track->_type){ + case TrackTitle:{ + title = track->toString(); + } + break; + case TrackVideo:{ + video = track->toString(); + } + break; + case TrackAudio:{ + audio = track->toString(); + } + break; + default: + break; + } + } + return title + video + audio; } bool RtspUrl::parse(const string &strUrl) { - auto schema = FindField(strUrl.data(), nullptr, "://"); - bool isSSL = strcasecmp(schema.data(), "rtsps") == 0; - //查找"://"与"/"之间的字符串,用于提取用户名密码 - auto middle_url = FindField(strUrl.data(), "://", "/"); - if (middle_url.empty()) { - middle_url = FindField(strUrl.data(), "://", nullptr); - } - auto pos = middle_url.rfind('@'); - if (pos == string::npos) { - //并没有用户名密码 - return setup(isSSL, strUrl, "", ""); - } + auto schema = FindField(strUrl.data(), nullptr, "://"); + bool isSSL = strcasecmp(schema.data(), "rtsps") == 0; + //查找"://"与"/"之间的字符串,用于提取用户名密码 + auto middle_url = FindField(strUrl.data(), "://", "/"); + if (middle_url.empty()) { + middle_url = FindField(strUrl.data(), "://", nullptr); + } + auto pos = middle_url.rfind('@'); + if (pos == string::npos) { + //并没有用户名密码 + return setup(isSSL, strUrl, "", ""); + } - //包含用户名密码 - auto user_pwd = middle_url.substr(0, pos); - auto suffix = strUrl.substr(schema.size() + 3 + pos + 1); - auto url = StrPrinter << "rtsp://" << suffix << endl; - if (user_pwd.find(":") == string::npos) { - return setup(isSSL, url, user_pwd, ""); - } - auto user = FindField(user_pwd.data(), nullptr, ":"); - auto pwd = FindField(user_pwd.data(), ":", nullptr); - return setup(isSSL, url, user, pwd); + //包含用户名密码 + auto user_pwd = middle_url.substr(0, pos); + auto suffix = strUrl.substr(schema.size() + 3 + pos + 1); + auto url = StrPrinter << "rtsp://" << suffix << endl; + if (user_pwd.find(":") == string::npos) { + return setup(isSSL, url, user_pwd, ""); + } + auto user = FindField(user_pwd.data(), nullptr, ":"); + auto pwd = FindField(user_pwd.data(), ":", nullptr); + return setup(isSSL, url, user, pwd); } bool RtspUrl::setup(bool isSSL, const string &strUrl, const string &strUser, const string &strPwd) { - auto ip = FindField(strUrl.data(), "://", "/"); - if (ip.empty()) { - ip = split(FindField(strUrl.data(), "://", NULL), "?")[0]; - } - auto port = atoi(FindField(ip.data(), ":", NULL).data()); - if (port <= 0 || port > UINT16_MAX) { - //rtsp 默认端口554 - port = isSSL ? 322 : 554; - } else { - //服务器域名 - ip = FindField(ip.data(), NULL, ":"); - } + auto ip = FindField(strUrl.data(), "://", "/"); + if (ip.empty()) { + ip = split(FindField(strUrl.data(), "://", NULL), "?")[0]; + } + auto port = atoi(FindField(ip.data(), ":", NULL).data()); + if (port <= 0 || port > UINT16_MAX) { + //rtsp 默认端口554 + port = isSSL ? 322 : 554; + } else { + //服务器域名 + ip = FindField(ip.data(), NULL, ":"); + } - if (ip.empty()) { - return false; - } + if (ip.empty()) { + return false; + } - _url = std::move(strUrl); - _user = std::move(strUser); - _passwd = std::move(strPwd); - _host = std::move(ip); - _port = port; - _is_ssl = isSSL; - return true; + _url = std::move(strUrl); + _user = std::move(strUser); + _passwd = std::move(strPwd); + _host = std::move(ip); + _port = port; + _is_ssl = isSSL; + return true; } }//namespace mediakit diff --git a/src/Rtsp/Rtsp.h b/src/Rtsp/Rtsp.h index 26e2a979..bafc81be 100644 --- a/src/Rtsp/Rtsp.h +++ b/src/Rtsp/Rtsp.h @@ -42,87 +42,87 @@ namespace mediakit { namespace Rtsp { typedef enum { - RTP_Invalid = -1, - RTP_TCP = 0, - RTP_UDP = 1, - RTP_MULTICAST = 2, + RTP_Invalid = -1, + RTP_TCP = 0, + RTP_UDP = 1, + RTP_MULTICAST = 2, } eRtpType; }; class RtpPacket : public BufferRaw{ public: - typedef std::shared_ptr Ptr; - uint8_t interleaved; - uint8_t PT; - bool mark; - //时间戳,单位毫秒 - uint32_t timeStamp; - uint16_t sequence; - uint32_t ssrc; - uint32_t offset; - TrackType type; + typedef std::shared_ptr Ptr; + uint8_t interleaved; + uint8_t PT; + bool mark; + //时间戳,单位毫秒 + uint32_t timeStamp; + uint16_t sequence; + uint32_t ssrc; + uint32_t offset; + TrackType type; }; class RtcpCounter { public: - uint32_t pktCnt = 0; - uint32_t octCount = 0; - //网络字节序 - uint32_t timeStamp = 0; - uint32_t lastTimeStamp = 0; + uint32_t pktCnt = 0; + uint32_t octCount = 0; + //网络字节序 + uint32_t timeStamp = 0; + uint32_t lastTimeStamp = 0; }; class SdpTrack { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - string _m; - string _o; - string _s; - string _i; - string _c; - string _t; - string _b; + string _m; + string _o; + string _s; + string _i; + string _c; + string _t; + string _b; - float _duration = 0; - float _start = 0; - float _end = 0; + float _duration = 0; + float _start = 0; + float _end = 0; - map _other; - map _attr; + map _other; + map _attr; - string toString() const; + string toString() const; public: - int _pt; - string _codec; - int _samplerate; - string _fmtp; - string _control; - string _control_surffix; - TrackType _type; + int _pt; + string _codec; + int _samplerate; + string _fmtp; + string _control; + string _control_surffix; + TrackType _type; public: - uint8_t _interleaved = 0; - bool _inited = false; - uint32_t _ssrc = 0; - uint16_t _seq = 0; - //时间戳,单位毫秒 - uint32_t _time_stamp = 0; + uint8_t _interleaved = 0; + bool _inited = false; + uint32_t _ssrc = 0; + uint16_t _seq = 0; + //时间戳,单位毫秒 + uint32_t _time_stamp = 0; }; class SdpParser { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - SdpParser() {} - SdpParser(const string &sdp) { load(sdp); } - ~SdpParser() {} - void load(const string &sdp); - bool available() const; - SdpTrack::Ptr getTrack(TrackType type) const; - vector getAvailableTrack() const; - string toString() const ; + SdpParser() {} + SdpParser(const string &sdp) { load(sdp); } + ~SdpParser() {} + void load(const string &sdp); + bool available() const; + SdpTrack::Ptr getTrack(TrackType type) const; + vector getAvailableTrack() const; + string toString() const ; private: - vector _track_vec; + vector _track_vec; }; /** @@ -130,18 +130,18 @@ private: */ class RtspUrl{ public: - string _url; - string _user; - string _passwd; - string _host; - uint16_t _port; - bool _is_ssl; + string _url; + string _user; + string _passwd; + string _host; + uint16_t _port; + bool _is_ssl; public: - RtspUrl() = default; - ~RtspUrl() = default; - bool parse(const string &url); + RtspUrl() = default; + ~RtspUrl() = default; + bool parse(const string &url); private: - bool setup(bool,const string &, const string &, const string &); + bool setup(bool,const string &, const string &, const string &); }; /** @@ -149,44 +149,44 @@ private: */ class Sdp : public CodecInfo{ public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - /** - * 构造sdp - * @param sample_rate 采样率 - * @param playload_type pt类型 - */ - Sdp(uint32_t sample_rate, uint8_t playload_type){ - _sample_rate = sample_rate; - _playload_type = playload_type; - } + /** + * 构造sdp + * @param sample_rate 采样率 + * @param playload_type pt类型 + */ + Sdp(uint32_t sample_rate, uint8_t playload_type){ + _sample_rate = sample_rate; + _playload_type = playload_type; + } - virtual ~Sdp(){} + virtual ~Sdp(){} - /** - * 获取sdp字符串 - * @return - */ - virtual string getSdp() const = 0; + /** + * 获取sdp字符串 + * @return + */ + virtual string getSdp() const = 0; - /** - * 获取pt - * @return - */ - uint8_t getPlayloadType() const{ - return _playload_type; - } + /** + * 获取pt + * @return + */ + uint8_t getPlayloadType() const{ + return _playload_type; + } - /** - * 获取采样率 - * @return - */ - uint32_t getSampleRate() const{ - return _sample_rate; - } + /** + * 获取采样率 + * @return + */ + uint32_t getSampleRate() const{ + return _sample_rate; + } private: - uint8_t _playload_type; - uint32_t _sample_rate; + uint8_t _playload_type; + uint32_t _sample_rate; }; /** @@ -195,56 +195,56 @@ private: class TitleSdp : public Sdp{ public: - /** - * 构造title类型sdp - * @param dur_sec rtsp点播时长,0代表直播,单位秒 - * @param header 自定义sdp描述 - * @param version sdp版本 - */ - TitleSdp(float dur_sec = 0, - const map &header = map(), - int version = 0) : Sdp(0,0){ - _printer << "v=" << version << "\r\n"; + /** + * 构造title类型sdp + * @param dur_sec rtsp点播时长,0代表直播,单位秒 + * @param header 自定义sdp描述 + * @param version sdp版本 + */ + TitleSdp(float dur_sec = 0, + const map &header = map(), + int version = 0) : Sdp(0,0){ + _printer << "v=" << version << "\r\n"; - if(!header.empty()){ - for (auto &pr : header){ - _printer << pr.first << "=" << pr.second << "\r\n"; - } - } else { - _printer << "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n"; - _printer << "s=RTSP Session, streamed by the ZLMediaKit\r\n"; - _printer << "i=ZLMediaKit Live Stream\r\n"; - _printer << "c=IN IP4 0.0.0.0\r\n"; - _printer << "t=0 0\r\n"; - } + if(!header.empty()){ + for (auto &pr : header){ + _printer << pr.first << "=" << pr.second << "\r\n"; + } + } else { + _printer << "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n"; + _printer << "s=RTSP Session, streamed by the ZLMediaKit\r\n"; + _printer << "i=ZLMediaKit Live Stream\r\n"; + _printer << "c=IN IP4 0.0.0.0\r\n"; + _printer << "t=0 0\r\n"; + } - if(dur_sec <= 0){ - _printer << "a=range:npt=0-\r\n"; - }else{ - _printer << "a=range:npt=0-" << dur_sec << "\r\n"; - } - _printer << "a=control:*\r\n"; - } - string getSdp() const override { - return _printer; - } - /** - * 返回音频或视频类型 - * @return - */ - TrackType getTrackType() const override { - return TrackTitle; - } + if(dur_sec <= 0){ + _printer << "a=range:npt=0-\r\n"; + }else{ + _printer << "a=range:npt=0-" << dur_sec << "\r\n"; + } + _printer << "a=control:*\r\n"; + } + string getSdp() const override { + return _printer; + } + /** + * 返回音频或视频类型 + * @return + */ + TrackType getTrackType() const override { + return TrackTitle; + } - /** - * 返回编码器id - * @return - */ - CodecId getCodecId() const override{ - return CodecInvalid; - } + /** + * 返回编码器id + * @return + */ + CodecId getCodecId() const override{ + return CodecInvalid; + } private: - _StrPrinter _printer; + _StrPrinter _printer; }; } //namespace mediakit diff --git a/src/Rtsp/RtspDemuxer.cpp b/src/Rtsp/RtspDemuxer.cpp index 950d2e12..4df26678 100644 --- a/src/Rtsp/RtspDemuxer.cpp +++ b/src/Rtsp/RtspDemuxer.cpp @@ -35,83 +35,83 @@ using namespace std; namespace mediakit { void RtspDemuxer::loadSdp(const string &sdp){ - loadSdp(SdpParser(sdp)); + loadSdp(SdpParser(sdp)); } void RtspDemuxer::loadSdp(const SdpParser &attr) { - auto tracks = attr.getAvailableTrack(); - for (auto &track : tracks){ - switch (track->_type) { - case TrackVideo: { - makeVideoTrack(track); - } - break; - case TrackAudio: { - makeAudioTrack(track); - } - break; - default: - break; - } - } - auto titleTrack = attr.getTrack(TrackTitle); - if(titleTrack){ - _fDuration = titleTrack->_duration; - } + auto tracks = attr.getAvailableTrack(); + for (auto &track : tracks){ + switch (track->_type) { + case TrackVideo: { + makeVideoTrack(track); + } + break; + case TrackAudio: { + makeAudioTrack(track); + } + break; + default: + break; + } + } + auto titleTrack = attr.getTrack(TrackTitle); + if(titleTrack){ + _fDuration = titleTrack->_duration; + } } bool RtspDemuxer::inputRtp(const RtpPacket::Ptr & rtp) { - switch (rtp->type) { - case TrackVideo:{ - if(_videoRtpDecoder){ - return _videoRtpDecoder->inputRtp(rtp, true); - } - return false; - } - case TrackAudio:{ - if(_audioRtpDecoder){ - _audioRtpDecoder->inputRtp(rtp, false); - return false; - } - return false; - } - default: - return false; - } + switch (rtp->type) { + case TrackVideo:{ + if(_videoRtpDecoder){ + return _videoRtpDecoder->inputRtp(rtp, true); + } + return false; + } + case TrackAudio:{ + if(_audioRtpDecoder){ + _audioRtpDecoder->inputRtp(rtp, false); + return false; + } + return false; + } + default: + return false; + } } void RtspDemuxer::makeAudioTrack(const SdpTrack::Ptr &audio) { - //生成Track对象 + //生成Track对象 _audioTrack = dynamic_pointer_cast(Factory::getTrackBySdp(audio)); if(_audioTrack){ - //生成RtpCodec对象以便解码rtp - _audioRtpDecoder = Factory::getRtpDecoderByTrack(_audioTrack); - if(_audioRtpDecoder){ - //设置rtp解码器代理,生成的frame写入该Track - _audioRtpDecoder->addDelegate(_audioTrack); - onAddTrack(_audioTrack); - } else{ - //找不到相应的rtp解码器,该track无效 - _audioTrack.reset(); - } + //生成RtpCodec对象以便解码rtp + _audioRtpDecoder = Factory::getRtpDecoderByTrack(_audioTrack); + if(_audioRtpDecoder){ + //设置rtp解码器代理,生成的frame写入该Track + _audioRtpDecoder->addDelegate(_audioTrack); + onAddTrack(_audioTrack); + } else{ + //找不到相应的rtp解码器,该track无效 + _audioTrack.reset(); + } } } void RtspDemuxer::makeVideoTrack(const SdpTrack::Ptr &video) { - //生成Track对象 - _videoTrack = dynamic_pointer_cast(Factory::getTrackBySdp(video)); - if(_videoTrack){ - //生成RtpCodec对象以便解码rtp - _videoRtpDecoder = Factory::getRtpDecoderByTrack(_videoTrack); - if(_videoRtpDecoder){ - //设置rtp解码器代理,生成的frame写入该Track - _videoRtpDecoder->addDelegate(_videoTrack); - onAddTrack(_videoTrack); - }else{ - //找不到相应的rtp解码器,该track无效 - _videoTrack.reset(); - } - } + //生成Track对象 + _videoTrack = dynamic_pointer_cast(Factory::getTrackBySdp(video)); + if(_videoTrack){ + //生成RtpCodec对象以便解码rtp + _videoRtpDecoder = Factory::getRtpDecoderByTrack(_videoTrack); + if(_videoRtpDecoder){ + //设置rtp解码器代理,生成的frame写入该Track + _videoRtpDecoder->addDelegate(_videoTrack); + onAddTrack(_videoTrack); + }else{ + //找不到相应的rtp解码器,该track无效 + _videoTrack.reset(); + } + } } } /* namespace mediakit */ diff --git a/src/Rtsp/RtspDemuxer.h b/src/Rtsp/RtspDemuxer.h index c864c19a..d4d8d915 100644 --- a/src/Rtsp/RtspDemuxer.h +++ b/src/Rtsp/RtspDemuxer.h @@ -39,8 +39,8 @@ namespace mediakit { class RtspDemuxer : public Demuxer{ public: - typedef std::shared_ptr Ptr; - RtspDemuxer() = default; + typedef std::shared_ptr Ptr; + RtspDemuxer() = default; virtual ~RtspDemuxer() = default; /** @@ -48,19 +48,19 @@ public: */ void loadSdp(const string &sdp); - /** - * 开始解复用 - * @param rtp rtp包 - * @return true 代表是i帧第一个rtp包 - */ - bool inputRtp(const RtpPacket::Ptr &rtp); + /** + * 开始解复用 + * @param rtp rtp包 + * @return true 代表是i帧第一个rtp包 + */ + bool inputRtp(const RtpPacket::Ptr &rtp); private: - void makeAudioTrack(const SdpTrack::Ptr &audio); - void makeVideoTrack(const SdpTrack::Ptr &video); - void loadSdp(const SdpParser &parser); + void makeAudioTrack(const SdpTrack::Ptr &audio); + void makeVideoTrack(const SdpTrack::Ptr &video); + void loadSdp(const SdpParser &parser); private: - RtpCodec::Ptr _audioRtpDecoder; - RtpCodec::Ptr _videoRtpDecoder; + RtpCodec::Ptr _audioRtpDecoder; + RtpCodec::Ptr _videoRtpDecoder; }; } /* namespace mediakit */ diff --git a/src/Rtsp/RtspMediaSource.h b/src/Rtsp/RtspMediaSource.h index 48edce20..51133560 100644 --- a/src/Rtsp/RtspMediaSource.h +++ b/src/Rtsp/RtspMediaSource.h @@ -56,177 +56,177 @@ namespace mediakit { */ class RtspMediaSource : public MediaSource, public RingDelegate { public: - typedef ResourcePool PoolType; - typedef std::shared_ptr Ptr; - typedef RingBuffer RingType; + typedef ResourcePool PoolType; + typedef std::shared_ptr Ptr; + typedef RingBuffer RingType; - /** - * 构造函数 - * @param vhost 虚拟主机名 - * @param app 应用名 - * @param stream_id 流id - * @param ring_size 可以设置固定的环形缓冲大小,0则自适应 - */ - RtspMediaSource(const string &vhost, - const string &app, - const string &stream_id, - int ring_size = RTP_GOP_SIZE) : - MediaSource(RTSP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {} + /** + * 构造函数 + * @param vhost 虚拟主机名 + * @param app 应用名 + * @param stream_id 流id + * @param ring_size 可以设置固定的环形缓冲大小,0则自适应 + */ + RtspMediaSource(const string &vhost, + const string &app, + const string &stream_id, + int ring_size = RTP_GOP_SIZE) : + MediaSource(RTSP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {} - virtual ~RtspMediaSource() {} + virtual ~RtspMediaSource() {} - /** - * 获取媒体源的环形缓冲 - */ - const RingType::Ptr &getRing() const { - return _ring; - } + /** + * 获取媒体源的环形缓冲 + */ + const RingType::Ptr &getRing() const { + return _ring; + } - /** - * 获取播放器个数 - */ - int readerCount() override { - return _ring ? _ring->readerCount() : 0; - } + /** + * 获取播放器个数 + */ + int readerCount() override { + return _ring ? _ring->readerCount() : 0; + } - /** - * 获取该源的sdp - */ - const string &getSdp() const { - return _sdp; - } + /** + * 获取该源的sdp + */ + const string &getSdp() const { + return _sdp; + } - /** - * 获取相应轨道的ssrc - */ - virtual uint32_t getSsrc(TrackType trackType) { - auto track = _sdp_parser.getTrack(trackType); - if (!track) { - return 0; - } - return track->_ssrc; - } + /** + * 获取相应轨道的ssrc + */ + virtual uint32_t getSsrc(TrackType trackType) { + auto track = _sdp_parser.getTrack(trackType); + if (!track) { + return 0; + } + return track->_ssrc; + } - /** - * 获取相应轨道的seqence - */ - virtual uint16_t getSeqence(TrackType trackType) { - auto track = _sdp_parser.getTrack(trackType); - if (!track) { - return 0; - } - return track->_seq; - } + /** + * 获取相应轨道的seqence + */ + virtual uint16_t getSeqence(TrackType trackType) { + auto track = _sdp_parser.getTrack(trackType); + if (!track) { + return 0; + } + return track->_seq; + } - /** - * 获取相应轨道的时间戳,单位毫秒 - */ - uint32_t getTimeStamp(TrackType trackType) override { - auto track = _sdp_parser.getTrack(trackType); - if (track) { - return track->_time_stamp; - } - auto tracks = _sdp_parser.getAvailableTrack(); - switch (tracks.size()) { - case 0: - return 0; - case 1: - return tracks[0]->_time_stamp; - default: - return MAX(tracks[0]->_time_stamp, tracks[1]->_time_stamp); - } - } + /** + * 获取相应轨道的时间戳,单位毫秒 + */ + uint32_t getTimeStamp(TrackType trackType) override { + auto track = _sdp_parser.getTrack(trackType); + if (track) { + return track->_time_stamp; + } + auto tracks = _sdp_parser.getAvailableTrack(); + switch (tracks.size()) { + case 0: + return 0; + case 1: + return tracks[0]->_time_stamp; + default: + return MAX(tracks[0]->_time_stamp, tracks[1]->_time_stamp); + } + } - /** - * 更新时间戳 - */ - void setTimeStamp(uint32_t uiStamp) override { - auto tracks = _sdp_parser.getAvailableTrack(); - for (auto &track : tracks) { - track->_time_stamp = uiStamp; - } - } + /** + * 更新时间戳 + */ + void setTimeStamp(uint32_t uiStamp) override { + auto tracks = _sdp_parser.getAvailableTrack(); + for (auto &track : tracks) { + track->_time_stamp = uiStamp; + } + } - /** - * 设置sdp - */ - virtual void setSdp(const string &sdp) { - _sdp = sdp; - _sdp_parser.load(sdp); - _have_video = (bool)_sdp_parser.getTrack(TrackVideo); - if (_ring) { - regist(); - } - } + /** + * 设置sdp + */ + virtual void setSdp(const string &sdp) { + _sdp = sdp; + _sdp_parser.load(sdp); + _have_video = (bool)_sdp_parser.getTrack(TrackVideo); + if (_ring) { + regist(); + } + } - /** - * 输入rtp - * @param rtp rtp包 - * @param keyPos 该包是否为关键帧的第一个包 - */ - void onWrite(const RtpPacket::Ptr &rtp, bool keyPos) override { - auto track = _sdp_parser.getTrack(rtp->type); - if (track) { - track->_seq = rtp->sequence; - track->_time_stamp = rtp->timeStamp; - track->_ssrc = rtp->ssrc; - } - if (!_ring) { - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - auto lam = [weakSelf](const EventPoller::Ptr &, int size, bool) { - auto strongSelf = weakSelf.lock(); - if (!strongSelf) { - return; - } - strongSelf->onReaderChanged(size); - }; + /** + * 输入rtp + * @param rtp rtp包 + * @param keyPos 该包是否为关键帧的第一个包 + */ + void onWrite(const RtpPacket::Ptr &rtp, bool keyPos) override { + auto track = _sdp_parser.getTrack(rtp->type); + if (track) { + track->_seq = rtp->sequence; + track->_time_stamp = rtp->timeStamp; + track->_ssrc = rtp->ssrc; + } + if (!_ring) { + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + auto lam = [weakSelf](const EventPoller::Ptr &, int size, bool) { + auto strongSelf = weakSelf.lock(); + if (!strongSelf) { + return; + } + strongSelf->onReaderChanged(size); + }; //rtp包缓存最大允许2048个,大概最多3MB数据 //但是这个是GOP缓存的上限值,真实的GOP缓存大小等于两个I帧之间的包数的两倍 //而且每次遇到I帧,则会清空GOP缓存,所以真实的GOP缓存远小于此值 - _ring = std::make_shared(_ring_size, std::move(lam)); - onReaderChanged(0); - if (!_sdp.empty()) { - regist(); - } - } - //不存在视频,为了减少缓存延时,那么关闭GOP缓存 - _ring->write(rtp, _have_video ? keyPos : true); - checkNoneReader(); - } + _ring = std::make_shared(_ring_size, std::move(lam)); + onReaderChanged(0); + if (!_sdp.empty()) { + regist(); + } + } + //不存在视频,为了减少缓存延时,那么关闭GOP缓存 + _ring->write(rtp, _have_video ? keyPos : true); + checkNoneReader(); + } private: - /** - * 每次增减消费者都会触发该函数 - */ - void onReaderChanged(int size) { - //我们记录最后一次活动时间 - _reader_changed_ticker.resetTime(); - if (size != 0 || totalReaderCount() != 0) { - //还有消费者正在观看该流 - _async_emit_none_reader = false; - return; - } - _async_emit_none_reader = true; - } + /** + * 每次增减消费者都会触发该函数 + */ + void onReaderChanged(int size) { + //我们记录最后一次活动时间 + _reader_changed_ticker.resetTime(); + if (size != 0 || totalReaderCount() != 0) { + //还有消费者正在观看该流 + _async_emit_none_reader = false; + return; + } + _async_emit_none_reader = true; + } - /** - * 检查是否无人消费该流, - * 如果无人消费且超过一定时间会触发onNoneReader事件 - */ - void checkNoneReader() { - GET_CONFIG(int, stream_none_reader_delay, General::kStreamNoneReaderDelayMS); - if (_async_emit_none_reader && _reader_changed_ticker.elapsedTime() > stream_none_reader_delay) { - _async_emit_none_reader = false; - onNoneReader(); - } - } + /** + * 检查是否无人消费该流, + * 如果无人消费且超过一定时间会触发onNoneReader事件 + */ + void checkNoneReader() { + GET_CONFIG(int, stream_none_reader_delay, General::kStreamNoneReaderDelayMS); + if (_async_emit_none_reader && _reader_changed_ticker.elapsedTime() > stream_none_reader_delay) { + _async_emit_none_reader = false; + onNoneReader(); + } + } protected: - int _ring_size; - bool _async_emit_none_reader = false; - bool _have_video = false; - Ticker _reader_changed_ticker; - SdpParser _sdp_parser; - string _sdp; - RingType::Ptr _ring; + int _ring_size; + bool _async_emit_none_reader = false; + bool _have_video = false; + Ticker _reader_changed_ticker; + SdpParser _sdp_parser; + string _sdp; + RingType::Ptr _ring; }; } /* namespace mediakit */ diff --git a/src/Rtsp/RtspMediaSourceImp.h b/src/Rtsp/RtspMediaSourceImp.h index 4586df2b..2f77ec09 100644 --- a/src/Rtsp/RtspMediaSourceImp.h +++ b/src/Rtsp/RtspMediaSourceImp.h @@ -39,12 +39,12 @@ public: typedef std::shared_ptr Ptr; /** - * 构造函数 - * @param vhost 虚拟主机 - * @param app 应用名 - * @param id 流id - * @param ringSize 环形缓存大小 - */ + * 构造函数 + * @param vhost 虚拟主机 + * @param app 应用名 + * @param id 流id + * @param ringSize 环形缓存大小 + */ RtspMediaSourceImp(const string &vhost, const string &app, const string &id, int ringSize = RTP_GOP_SIZE) : RtspMediaSource(vhost, app, id,ringSize) { _demuxer = std::make_shared(); _demuxer->setTrackListener(this); @@ -69,9 +69,9 @@ public: } /** - * 设置监听器 - * @param listener - */ + * 设置监听器 + * @param listener + */ void setListener(const std::weak_ptr &listener) override { RtspMediaSource::setListener(listener); if(_muxer){ @@ -87,11 +87,11 @@ public: } /** - * 设置协议转换 - * @param enableRtmp 是否转换成rtmp - * @param enableHls 是否转换成hls - * @param enableMP4 是否mp4录制 - */ + * 设置协议转换 + * @param enableRtmp 是否转换成rtmp + * @param enableHls 是否转换成hls + * @param enableMP4 是否mp4录制 + */ void setProtocolTranslation(bool enableRtmp,bool enableHls,bool enableMP4){ //不重复生成rtsp _muxer = std::make_shared(getVhost(), getApp(), getId(), _demuxer->getDuration(), false, enableRtmp, enableHls, enableMP4); @@ -104,8 +104,8 @@ public: } /** - * _demuxer触发的添加Track事件 - */ + * _demuxer触发的添加Track事件 + */ void onAddTrack(const Track::Ptr &track) override { if(_muxer){ _muxer->addTrack(track); diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index 682cbe19..1cdd56b9 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -43,29 +43,29 @@ using namespace mediakit::Client; namespace mediakit { enum PlayType { - type_play = 0, - type_pause, - type_seek + type_play = 0, + type_pause, + type_seek }; RtspPlayer::RtspPlayer(const EventPoller::Ptr &poller) : TcpClient(poller){ - RtpReceiver::setPoolSize(64); + RtpReceiver::setPoolSize(64); } RtspPlayer::~RtspPlayer(void) { DebugL << endl; } void RtspPlayer::teardown(){ - if (alive()) { - sendRtspRequest("TEARDOWN" ,_strContentBase); - shutdown(SockException(Err_shutdown,"teardown")); - } + if (alive()) { + sendRtspRequest("TEARDOWN" ,_strContentBase); + shutdown(SockException(Err_shutdown,"teardown")); + } - _rtspMd5Nonce.clear(); - _rtspRealm.clear(); - _aTrackInfo.clear(); + _rtspMd5Nonce.clear(); + _rtspRealm.clear(); + _aTrackInfo.clear(); _strSession.clear(); _strContentBase.clear(); - RtpReceiver::clear(); + RtpReceiver::clear(); CLEAR_ARR(_apRtpSock); CLEAR_ARR(_apRtcpSock); @@ -74,65 +74,65 @@ void RtspPlayer::teardown(){ CLEAR_ARR(_aui64RtpRecv) CLEAR_ARR(_aui16NowSeq) - _pPlayTimer.reset(); + _pPlayTimer.reset(); _pRtpTimer.reset(); - _uiCseq = 1; - _onHandshake = nullptr; + _uiCseq = 1; + _onHandshake = nullptr; } void RtspPlayer::play(const string &strUrl){ - RtspUrl url; - if(!url.parse(strUrl)){ - onPlayResult_l(SockException(Err_other,StrPrinter << "illegal rtsp url:" << strUrl),false); - return; - } + RtspUrl url; + if(!url.parse(strUrl)){ + onPlayResult_l(SockException(Err_other,StrPrinter << "illegal rtsp url:" << strUrl),false); + return; + } - teardown(); + teardown(); - if (url._user.size()) { - (*this)[kRtspUser] = url._user; - } - if (url._passwd.size()) { - (*this)[kRtspPwd] = url._passwd; - (*this)[kRtspPwdIsMD5] = false; - } + if (url._user.size()) { + (*this)[kRtspUser] = url._user; + } + if (url._passwd.size()) { + (*this)[kRtspPwd] = url._passwd; + (*this)[kRtspPwdIsMD5] = false; + } - _strUrl = url._url; - _eType = (Rtsp::eRtpType)(int)(*this)[kRtpType]; - DebugL << url._url << " " << (url._user.size() ? url._user : "null") << " " << (url._passwd.size() ? url._passwd : "null") << " " << _eType; + _strUrl = url._url; + _eType = (Rtsp::eRtpType)(int)(*this)[kRtpType]; + DebugL << url._url << " " << (url._user.size() ? url._user : "null") << " " << (url._passwd.size() ? url._passwd : "null") << " " << _eType; - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - float playTimeOutSec = (*this)[kTimeoutMS].as() / 1000.0; - _pPlayTimer.reset( new Timer(playTimeOutSec, [weakSelf]() { - auto strongSelf=weakSelf.lock(); - if(!strongSelf) { - return false; - } - strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtsp timeout"),false); - return false; - },getPoller())); + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + float playTimeOutSec = (*this)[kTimeoutMS].as() / 1000.0; + _pPlayTimer.reset( new Timer(playTimeOutSec, [weakSelf]() { + auto strongSelf=weakSelf.lock(); + if(!strongSelf) { + return false; + } + strongSelf->onPlayResult_l(SockException(Err_timeout,"play rtsp timeout"),false); + return false; + },getPoller())); - if(!(*this)[kNetAdapter].empty()){ - setNetAdapter((*this)[kNetAdapter]); - } - startConnect(url._host, url._port, playTimeOutSec); + if(!(*this)[kNetAdapter].empty()){ + setNetAdapter((*this)[kNetAdapter]); + } + startConnect(url._host, url._port, playTimeOutSec); } void RtspPlayer::onConnect(const SockException &err){ - if(err.getErrCode() != Err_success) { - onPlayResult_l(err,false); - return; - } + if(err.getErrCode() != Err_success) { + onPlayResult_l(err,false); + return; + } - sendDescribe(); + sendDescribe(); } void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) { input(pBuf->data(),pBuf->size()); } void RtspPlayer::onErr(const SockException &ex) { - //定时器_pPlayTimer为空后表明握手结束了 - onPlayResult_l(ex,!_pPlayTimer); + //定时器_pPlayTimer为空后表明握手结束了 + onPlayResult_l(ex,!_pPlayTimer); } // from live555 bool RtspPlayer::handleAuthenticationFailure(const string ¶msStr) { @@ -167,25 +167,25 @@ bool RtspPlayer::handleAuthenticationFailure(const string ¶msStr) { return false; } void RtspPlayer::handleResDESCRIBE(const Parser& parser) { - string authInfo = parser["WWW-Authenticate"]; - //发送DESCRIBE命令后的回复 - if ((parser.Url() == "401") && handleAuthenticationFailure(authInfo)) { - sendDescribe(); - return; - } - if(parser.Url() == "302" || parser.Url() == "301"){ - auto newUrl = parser["Location"]; - if(newUrl.empty()){ - throw std::runtime_error("未找到Location字段(跳转url)"); - } - play(newUrl); - return; - } - if (parser.Url() != "200") { - throw std::runtime_error( - StrPrinter << "DESCRIBE:" << parser.Url() << " " << parser.Tail() << endl); - } - _strContentBase = parser["Content-Base"]; + string authInfo = parser["WWW-Authenticate"]; + //发送DESCRIBE命令后的回复 + if ((parser.Url() == "401") && handleAuthenticationFailure(authInfo)) { + sendDescribe(); + return; + } + if(parser.Url() == "302" || parser.Url() == "301"){ + auto newUrl = parser["Location"]; + if(newUrl.empty()){ + throw std::runtime_error("未找到Location字段(跳转url)"); + } + play(newUrl); + return; + } + if (parser.Url() != "200") { + throw std::runtime_error( + StrPrinter << "DESCRIBE:" << parser.Url() << " " << parser.Tail() << endl); + } + _strContentBase = parser["Content-Base"]; if(_strContentBase.empty()){ _strContentBase = _strUrl; @@ -194,58 +194,58 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) { _strContentBase.pop_back(); } - SdpParser sdpParser(parser.Content()); - //解析sdp - _aTrackInfo = sdpParser.getAvailableTrack(); - auto title = sdpParser.getTrack(TrackTitle); - bool isPlayback = false; - if(title && title->_duration ){ + SdpParser sdpParser(parser.Content()); + //解析sdp + _aTrackInfo = sdpParser.getAvailableTrack(); + auto title = sdpParser.getTrack(TrackTitle); + bool isPlayback = false; + if(title && title->_duration ){ isPlayback = true; - } + } for(auto &stamp : _stamp){ stamp.setPlayBack(isPlayback); stamp.setRelativeStamp(0); } - if (_aTrackInfo.empty()) { - throw std::runtime_error("无有效的Sdp Track"); - } - if (!onCheckSDP(sdpParser.toString())) { - throw std::runtime_error("onCheckSDP faied"); - } + if (_aTrackInfo.empty()) { + throw std::runtime_error("无有效的Sdp Track"); + } + if (!onCheckSDP(sdpParser.toString())) { + throw std::runtime_error("onCheckSDP faied"); + } - sendSetup(0); + sendSetup(0); } //有必要的情况下创建udp端口 void RtspPlayer::createUdpSockIfNecessary(int track_idx){ - auto &rtpSockRef = _apRtpSock[track_idx]; - auto &rtcpSockRef = _apRtcpSock[track_idx]; - if(!rtpSockRef){ - rtpSockRef.reset(new Socket(getPoller())); - //rtp随机端口 - if (!rtpSockRef->bindUdpSock(0, get_local_ip().data())) { - rtpSockRef.reset(); - throw std::runtime_error("open rtp sock failed"); - } - } + auto &rtpSockRef = _apRtpSock[track_idx]; + auto &rtcpSockRef = _apRtcpSock[track_idx]; + if(!rtpSockRef){ + rtpSockRef.reset(new Socket(getPoller())); + //rtp随机端口 + if (!rtpSockRef->bindUdpSock(0, get_local_ip().data())) { + rtpSockRef.reset(); + throw std::runtime_error("open rtp sock failed"); + } + } - if(!rtcpSockRef){ - rtcpSockRef.reset(new Socket(getPoller())); - //rtcp端口为rtp端口+1,目的是为了兼容某些服务器,其实更推荐随机端口 - if (!rtcpSockRef->bindUdpSock(rtpSockRef->get_local_port() + 1, get_local_ip().data())) { - rtcpSockRef.reset(); - throw std::runtime_error("open rtcp sock failed"); - } - } + if(!rtcpSockRef){ + rtcpSockRef.reset(new Socket(getPoller())); + //rtcp端口为rtp端口+1,目的是为了兼容某些服务器,其实更推荐随机端口 + if (!rtcpSockRef->bindUdpSock(rtpSockRef->get_local_port() + 1, get_local_ip().data())) { + rtcpSockRef.reset(); + throw std::runtime_error("open rtcp sock failed"); + } + } - if(rtpSockRef->get_local_port() % 2 != 0){ - //如果rtp端口不是偶数,那么与rtcp端口互换,目的是兼容一些要求严格的服务器 - Socket::Ptr tmp = rtpSockRef; - rtpSockRef = rtcpSockRef; - rtcpSockRef = tmp; - } + if(rtpSockRef->get_local_port() % 2 != 0){ + //如果rtp端口不是偶数,那么与rtcp端口互换,目的是兼容一些要求严格的服务器 + Socket::Ptr tmp = rtpSockRef; + rtpSockRef = rtcpSockRef; + rtcpSockRef = tmp; + } } @@ -253,91 +253,91 @@ void RtspPlayer::createUdpSockIfNecessary(int track_idx){ void RtspPlayer::sendSetup(unsigned int trackIndex) { _onHandshake = std::bind(&RtspPlayer::handleResSETUP,this, placeholders::_1,trackIndex); auto &track = _aTrackInfo[trackIndex]; - auto baseUrl = _strContentBase + "/" + track->_control_surffix; - switch (_eType) { - case Rtsp::RTP_TCP: { - sendRtspRequest("SETUP",baseUrl,{"Transport",StrPrinter << "RTP/AVP/TCP;unicast;interleaved=" << track->_type * 2 << "-" << track->_type * 2 + 1}); - } - break; - case Rtsp::RTP_MULTICAST: { - sendRtspRequest("SETUP",baseUrl,{"Transport","Transport: RTP/AVP;multicast"}); - } - break; - case Rtsp::RTP_UDP: { - createUdpSockIfNecessary(trackIndex); - sendRtspRequest("SETUP",baseUrl,{"Transport", + auto baseUrl = _strContentBase + "/" + track->_control_surffix; + switch (_eType) { + case Rtsp::RTP_TCP: { + sendRtspRequest("SETUP",baseUrl,{"Transport",StrPrinter << "RTP/AVP/TCP;unicast;interleaved=" << track->_type * 2 << "-" << track->_type * 2 + 1}); + } + break; + case Rtsp::RTP_MULTICAST: { + sendRtspRequest("SETUP",baseUrl,{"Transport","Transport: RTP/AVP;multicast"}); + } + break; + case Rtsp::RTP_UDP: { + createUdpSockIfNecessary(trackIndex); + sendRtspRequest("SETUP",baseUrl,{"Transport", StrPrinter << "RTP/AVP;unicast;client_port=" << _apRtpSock[trackIndex]->get_local_port() << "-" << _apRtcpSock[trackIndex]->get_local_port()}); - } - break; - default: - break; - } + } + break; + default: + break; + } } void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex) { - if (parser.Url() != "200") { - throw std::runtime_error( - StrPrinter << "SETUP:" << parser.Url() << " " << parser.Tail() << endl); - } - if (uiTrackIndex == 0) { - _strSession = parser["Session"]; + if (parser.Url() != "200") { + throw std::runtime_error( + StrPrinter << "SETUP:" << parser.Url() << " " << parser.Tail() << endl); + } + if (uiTrackIndex == 0) { + _strSession = parser["Session"]; _strSession.append(";"); _strSession = FindField(_strSession.data(), nullptr, ";"); - } + } - auto strTransport = parser["Transport"]; - if(strTransport.find("TCP") != string::npos || strTransport.find("interleaved") != string::npos){ - _eType = Rtsp::RTP_TCP; - }else if(strTransport.find("multicast") != string::npos){ - _eType = Rtsp::RTP_MULTICAST; - }else{ - _eType = Rtsp::RTP_UDP; - } + auto strTransport = parser["Transport"]; + if(strTransport.find("TCP") != string::npos || strTransport.find("interleaved") != string::npos){ + _eType = Rtsp::RTP_TCP; + }else if(strTransport.find("multicast") != string::npos){ + _eType = Rtsp::RTP_MULTICAST; + }else{ + _eType = Rtsp::RTP_UDP; + } - RtspSplitter::enableRecvRtp(_eType == Rtsp::RTP_TCP); + RtspSplitter::enableRecvRtp(_eType == Rtsp::RTP_TCP); - if(_eType == Rtsp::RTP_TCP) { - string interleaved = FindField( FindField((strTransport + ";").data(), "interleaved=", ";").data(), NULL, "-"); - _aTrackInfo[uiTrackIndex]->_interleaved = atoi(interleaved.data()); - }else{ - const char *strPos = (_eType == Rtsp::RTP_MULTICAST ? "port=" : "server_port=") ; - auto port_str = FindField((strTransport + ";").data(), strPos, ";"); - uint16_t rtp_port = atoi(FindField(port_str.data(), NULL, "-").data()); + if(_eType == Rtsp::RTP_TCP) { + string interleaved = FindField( FindField((strTransport + ";").data(), "interleaved=", ";").data(), NULL, "-"); + _aTrackInfo[uiTrackIndex]->_interleaved = atoi(interleaved.data()); + }else{ + const char *strPos = (_eType == Rtsp::RTP_MULTICAST ? "port=" : "server_port=") ; + auto port_str = FindField((strTransport + ";").data(), strPos, ";"); + uint16_t rtp_port = atoi(FindField(port_str.data(), NULL, "-").data()); uint16_t rtcp_port = atoi(FindField(port_str.data(), "-",NULL).data()); auto &pRtpSockRef = _apRtpSock[uiTrackIndex]; auto &pRtcpSockRef = _apRtcpSock[uiTrackIndex]; - if (_eType == Rtsp::RTP_MULTICAST) { - //udp组播 - auto multiAddr = FindField((strTransport + ";").data(), "destination=", ";"); + if (_eType == Rtsp::RTP_MULTICAST) { + //udp组播 + auto multiAddr = FindField((strTransport + ";").data(), "destination=", ";"); pRtpSockRef.reset(new Socket(getPoller())); - if (!pRtpSockRef->bindUdpSock(rtp_port, multiAddr.data())) { - pRtpSockRef.reset(); - throw std::runtime_error("open udp sock err"); - } - auto fd = pRtpSockRef->rawFD(); - if (-1 == SockUtil::joinMultiAddrFilter(fd, multiAddr.data(), get_peer_ip().data(),get_local_ip().data())) { - SockUtil::joinMultiAddr(fd, multiAddr.data(),get_local_ip().data()); - } - } else { - createUdpSockIfNecessary(uiTrackIndex); - //udp单播 - struct sockaddr_in rtpto; - rtpto.sin_port = ntohs(rtp_port); - rtpto.sin_family = AF_INET; - rtpto.sin_addr.s_addr = inet_addr(get_peer_ip().data()); - pRtpSockRef->setSendPeerAddr((struct sockaddr *)&(rtpto)); - //发送rtp打洞包 - pRtpSockRef->send("\xce\xfa\xed\xfe", 4); + if (!pRtpSockRef->bindUdpSock(rtp_port, multiAddr.data())) { + pRtpSockRef.reset(); + throw std::runtime_error("open udp sock err"); + } + auto fd = pRtpSockRef->rawFD(); + if (-1 == SockUtil::joinMultiAddrFilter(fd, multiAddr.data(), get_peer_ip().data(),get_local_ip().data())) { + SockUtil::joinMultiAddr(fd, multiAddr.data(),get_local_ip().data()); + } + } else { + createUdpSockIfNecessary(uiTrackIndex); + //udp单播 + struct sockaddr_in rtpto; + rtpto.sin_port = ntohs(rtp_port); + rtpto.sin_family = AF_INET; + rtpto.sin_addr.s_addr = inet_addr(get_peer_ip().data()); + pRtpSockRef->setSendPeerAddr((struct sockaddr *)&(rtpto)); + //发送rtp打洞包 + pRtpSockRef->send("\xce\xfa\xed\xfe", 4); - //设置rtcp发送目标,为后续发送rtcp做准备 + //设置rtcp发送目标,为后续发送rtcp做准备 rtpto.sin_port = ntohs(rtcp_port); rtpto.sin_family = AF_INET; rtpto.sin_addr.s_addr = inet_addr(get_peer_ip().data()); pRtcpSockRef->setSendPeerAddr((struct sockaddr *)&(rtpto)); - } + } auto srcIP = inet_addr(get_peer_ip().data()); weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); @@ -368,98 +368,98 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex) strongSelf->onRtcpPacket(uiTrackIndex, strongSelf->_aTrackInfo[uiTrackIndex], (unsigned char *) buf->data(), buf->size()); }); } - } + } - if (uiTrackIndex < _aTrackInfo.size() - 1) { - //需要继续发送SETUP命令 - sendSetup(uiTrackIndex + 1); - return; - } - //所有setup命令发送完毕 - //发送play命令 + if (uiTrackIndex < _aTrackInfo.size() - 1) { + //需要继续发送SETUP命令 + sendSetup(uiTrackIndex + 1); + return; + } + //所有setup命令发送完毕 + //发送play命令 sendPause(type_play, 0); } void RtspPlayer::sendDescribe() { - //发送DESCRIBE命令后处理函数:handleResDESCRIBE - _onHandshake = std::bind(&RtspPlayer::handleResDESCRIBE,this, placeholders::_1); - sendRtspRequest("DESCRIBE",_strUrl,{"Accept","application/sdp"}); + //发送DESCRIBE命令后处理函数:handleResDESCRIBE + _onHandshake = std::bind(&RtspPlayer::handleResDESCRIBE,this, placeholders::_1); + sendRtspRequest("DESCRIBE",_strUrl,{"Accept","application/sdp"}); } void RtspPlayer::sendPause(int type , uint32_t seekMS){ - _onHandshake = std::bind(&RtspPlayer::handleResPAUSE,this, placeholders::_1,type); - //开启或暂停rtsp - switch (type){ - case type_pause: - sendRtspRequest("PAUSE", _strContentBase); - break; - case type_play: - sendRtspRequest("PLAY", _strContentBase); - break; - case type_seek: - sendRtspRequest("PLAY", _strContentBase, {"Range",StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-"}); - break; - default: - WarnL << "unknown type : " << type; - _onHandshake = nullptr; - break; - } + _onHandshake = std::bind(&RtspPlayer::handleResPAUSE,this, placeholders::_1,type); + //开启或暂停rtsp + switch (type){ + case type_pause: + sendRtspRequest("PAUSE", _strContentBase); + break; + case type_play: + sendRtspRequest("PLAY", _strContentBase); + break; + case type_seek: + sendRtspRequest("PLAY", _strContentBase, {"Range",StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-"}); + break; + default: + WarnL << "unknown type : " << type; + _onHandshake = nullptr; + break; + } } void RtspPlayer::pause(bool bPause) { sendPause(bPause ? type_pause : type_seek, getProgressMilliSecond()); } void RtspPlayer::handleResPAUSE(const Parser& parser,int type) { - if (parser.Url() != "200") { - switch (type) { - case type_pause: - WarnL << "Pause failed:" << parser.Url() << " " << parser.Tail() << endl; - break; - case type_play: - WarnL << "Play failed:" << parser.Url() << " " << parser.Tail() << endl; - break; - case type_seek: - WarnL << "Seek failed:" << parser.Url() << " " << parser.Tail() << endl; - break; - } - return; - } + if (parser.Url() != "200") { + switch (type) { + case type_pause: + WarnL << "Pause failed:" << parser.Url() << " " << parser.Tail() << endl; + break; + case type_play: + WarnL << "Play failed:" << parser.Url() << " " << parser.Tail() << endl; + break; + case type_seek: + WarnL << "Seek failed:" << parser.Url() << " " << parser.Tail() << endl; + break; + } + return; + } - if (type == type_pause) { - //暂停成功! - _pRtpTimer.reset(); - return; - } + if (type == type_pause) { + //暂停成功! + _pRtpTimer.reset(); + return; + } - //play或seek成功 - uint32_t iSeekTo = 0; - //修正时间轴 - auto strRange = parser["Range"]; - if (strRange.size()) { - auto strStart = FindField(strRange.data(), "npt=", "-"); - if (strStart == "now") { - strStart = "0"; - } - iSeekTo = 1000 * atof(strStart.data()); - DebugL << "seekTo(ms):" << iSeekTo; - } - //设置相对时间戳 - _stamp[0].setRelativeStamp(iSeekTo); - _stamp[1].setRelativeStamp(iSeekTo); - onPlayResult_l(SockException(Err_success, type == type_seek ? "resum rtsp success" : "rtsp play success"), type == type_seek); + //play或seek成功 + uint32_t iSeekTo = 0; + //修正时间轴 + auto strRange = parser["Range"]; + if (strRange.size()) { + auto strStart = FindField(strRange.data(), "npt=", "-"); + if (strStart == "now") { + strStart = "0"; + } + iSeekTo = 1000 * atof(strStart.data()); + DebugL << "seekTo(ms):" << iSeekTo; + } + //设置相对时间戳 + _stamp[0].setRelativeStamp(iSeekTo); + _stamp[1].setRelativeStamp(iSeekTo); + onPlayResult_l(SockException(Err_success, type == type_seek ? "resum rtsp success" : "rtsp play success"), type == type_seek); } void RtspPlayer::onWholeRtspPacket(Parser &parser) { try { - decltype(_onHandshake) fun; - _onHandshake.swap(fun); + decltype(_onHandshake) fun; + _onHandshake.swap(fun); if(fun){ fun(parser); } parser.Clear(); } catch (std::exception &err) { - //定时器_pPlayTimer为空后表明握手结束了 - onPlayResult_l(SockException(Err_other, err.what()),!_pPlayTimer); + //定时器_pPlayTimer为空后表明握手结束了 + onPlayResult_l(SockException(Err_other, err.what()),!_pPlayTimer); } } @@ -610,39 +610,39 @@ void RtspPlayer::sendReceiverReport(bool overTcp,int iTrackIndex){ void RtspPlayer::onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx){ - //统计丢包率 - if (_aui16FirstSeq[trackidx] == 0 || rtppt->sequence < _aui16FirstSeq[trackidx]) { - _aui16FirstSeq[trackidx] = rtppt->sequence; - _aui64RtpRecv[trackidx] = 0; - } - _aui64RtpRecv[trackidx] ++; - _aui16NowSeq[trackidx] = rtppt->sequence; + //统计丢包率 + if (_aui16FirstSeq[trackidx] == 0 || rtppt->sequence < _aui16FirstSeq[trackidx]) { + _aui16FirstSeq[trackidx] = rtppt->sequence; + _aui64RtpRecv[trackidx] = 0; + } + _aui64RtpRecv[trackidx] ++; + _aui16NowSeq[trackidx] = rtppt->sequence; - //计算相对时间戳 - int64_t dts_out; - _stamp[trackidx].revise(rtppt->timeStamp,rtppt->timeStamp,dts_out,dts_out); + //计算相对时间戳 + int64_t dts_out; + _stamp[trackidx].revise(rtppt->timeStamp,rtppt->timeStamp,dts_out,dts_out); rtppt->timeStamp = dts_out; - onRecvRTP_l(rtppt,_aTrackInfo[trackidx]); + onRecvRTP_l(rtppt,_aTrackInfo[trackidx]); } float RtspPlayer::getPacketLossRate(TrackType type) const{ - int iTrackIdx = getTrackIndexByTrackType(type); - if(iTrackIdx == -1){ - uint64_t totalRecv = 0; - uint64_t totalSend = 0; - for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { - totalRecv += _aui64RtpRecv[i]; - totalSend += (_aui16NowSeq[i] - _aui16FirstSeq[i] + 1); - } - if(totalSend == 0){ - return 0; - } - return 1.0 - (double)totalRecv / totalSend; - } + int iTrackIdx = getTrackIndexByTrackType(type); + if(iTrackIdx == -1){ + uint64_t totalRecv = 0; + uint64_t totalSend = 0; + for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { + totalRecv += _aui64RtpRecv[i]; + totalSend += (_aui16NowSeq[i] - _aui16FirstSeq[i] + 1); + } + if(totalSend == 0){ + return 0; + } + return 1.0 - (double)totalRecv / totalSend; + } - if(_aui16NowSeq[iTrackIdx] - _aui16FirstSeq[iTrackIdx] + 1 == 0){ - return 0; - } - return 1.0 - (double)_aui64RtpRecv[iTrackIdx] / (_aui16NowSeq[iTrackIdx] - _aui16FirstSeq[iTrackIdx] + 1); + if(_aui16NowSeq[iTrackIdx] - _aui16FirstSeq[iTrackIdx] + 1 == 0){ + return 0; + } + return 1.0 - (double)_aui64RtpRecv[iTrackIdx] / (_aui16NowSeq[iTrackIdx] - _aui16FirstSeq[iTrackIdx] + 1); } uint32_t RtspPlayer::getProgressMilliSecond() const{ @@ -653,70 +653,70 @@ void RtspPlayer::seekToMilliSecond(uint32_t ms) { } void RtspPlayer::sendRtspRequest(const string &cmd, const string &url, const std::initializer_list &header) { - string key; - StrCaseMap header_map; - int i = 0; - for(auto &val : header){ - if(++i % 2 == 0){ - header_map.emplace(key,val); - }else{ - key = val; - } - } - sendRtspRequest(cmd,url,header_map); + string key; + StrCaseMap header_map; + int i = 0; + for(auto &val : header){ + if(++i % 2 == 0){ + header_map.emplace(key,val); + }else{ + key = val; + } + } + sendRtspRequest(cmd,url,header_map); } void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrCaseMap &header_const) { - auto header = header_const; - header.emplace("CSeq",StrPrinter << _uiCseq++); - header.emplace("User-Agent",SERVER_NAME "(build in " __DATE__ " " __TIME__ ")"); + auto header = header_const; + header.emplace("CSeq",StrPrinter << _uiCseq++); + header.emplace("User-Agent",SERVER_NAME "(build in " __DATE__ " " __TIME__ ")"); - if(!_strSession.empty()){ - header.emplace("Session",_strSession); - } + if(!_strSession.empty()){ + header.emplace("Session",_strSession); + } - if(!_rtspRealm.empty() && !(*this)[kRtspUser].empty()){ - if(!_rtspMd5Nonce.empty()){ - //MD5认证 - /* - response计算方法如下: - RTSP客户端应该使用username + password并计算response如下: - (1)当password为MD5编码,则 - response = md5( password:nonce:md5(public_method:url) ); - (2)当password为ANSI字符串,则 - response= md5( md5(username:realm:password):nonce:md5(public_method:url) ); - */ - string encrypted_pwd = (*this)[kRtspPwd]; - if(!(*this)[kRtspPwdIsMD5].as()){ - encrypted_pwd = MD5((*this)[kRtspUser]+ ":" + _rtspRealm + ":" + encrypted_pwd).hexdigest(); - } - auto response = MD5( encrypted_pwd + ":" + _rtspMd5Nonce + ":" + MD5(cmd + ":" + url).hexdigest()).hexdigest(); - _StrPrinter printer; - printer << "Digest "; - printer << "username=\"" << (*this)[kRtspUser] << "\", "; - printer << "realm=\"" << _rtspRealm << "\", "; - printer << "nonce=\"" << _rtspMd5Nonce << "\", "; - printer << "uri=\"" << url << "\", "; - printer << "response=\"" << response << "\""; - header.emplace("Authorization",printer); - }else if(!(*this)[kRtspPwdIsMD5].as()){ - //base64认证 - string authStr = StrPrinter << (*this)[kRtspUser] << ":" << (*this)[kRtspPwd]; - char authStrBase64[1024] = {0}; - av_base64_encode(authStrBase64,sizeof(authStrBase64),(uint8_t *)authStr.data(),authStr.size()); - header.emplace("Authorization",StrPrinter << "Basic " << authStrBase64 ); - } - } + if(!_rtspRealm.empty() && !(*this)[kRtspUser].empty()){ + if(!_rtspMd5Nonce.empty()){ + //MD5认证 + /* + response计算方法如下: + RTSP客户端应该使用username + password并计算response如下: + (1)当password为MD5编码,则 + response = md5( password:nonce:md5(public_method:url) ); + (2)当password为ANSI字符串,则 + response= md5( md5(username:realm:password):nonce:md5(public_method:url) ); + */ + string encrypted_pwd = (*this)[kRtspPwd]; + if(!(*this)[kRtspPwdIsMD5].as()){ + encrypted_pwd = MD5((*this)[kRtspUser]+ ":" + _rtspRealm + ":" + encrypted_pwd).hexdigest(); + } + auto response = MD5( encrypted_pwd + ":" + _rtspMd5Nonce + ":" + MD5(cmd + ":" + url).hexdigest()).hexdigest(); + _StrPrinter printer; + printer << "Digest "; + printer << "username=\"" << (*this)[kRtspUser] << "\", "; + printer << "realm=\"" << _rtspRealm << "\", "; + printer << "nonce=\"" << _rtspMd5Nonce << "\", "; + printer << "uri=\"" << url << "\", "; + printer << "response=\"" << response << "\""; + header.emplace("Authorization",printer); + }else if(!(*this)[kRtspPwdIsMD5].as()){ + //base64认证 + string authStr = StrPrinter << (*this)[kRtspUser] << ":" << (*this)[kRtspPwd]; + char authStrBase64[1024] = {0}; + av_base64_encode(authStrBase64,sizeof(authStrBase64),(uint8_t *)authStr.data(),authStr.size()); + header.emplace("Authorization",StrPrinter << "Basic " << authStrBase64 ); + } + } - _StrPrinter printer; - printer << cmd << " " << url << " RTSP/1.0\r\n"; - for (auto &pr : header){ - printer << pr.first << ": " << pr.second << "\r\n"; - } - send(printer << "\r\n"); + _StrPrinter printer; + printer << cmd << " " << url << " RTSP/1.0\r\n"; + for (auto &pr : header){ + printer << pr.first << ": " << pr.second << "\r\n"; + } + send(printer << "\r\n"); } void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &pkt, const SdpTrack::Ptr &track) { - _rtpTicker.resetTime(); + _rtpTicker.resetTime(); onRecvRTP(pkt,track); int iTrackIndex = getTrackIndexByInterleaved(pkt->interleaved); @@ -740,22 +740,22 @@ void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &pkt, const SdpTrack::Ptr &tra } void RtspPlayer::onPlayResult_l(const SockException &ex , bool handshakeCompleted) { - WarnL << ex.getErrCode() << " " << ex.what(); + WarnL << ex.getErrCode() << " " << ex.what(); if(!ex){ //播放成功,恢复rtp接收超时定时器 _rtpTicker.resetTime(); weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); int timeoutMS = (*this)[kMediaTimeoutMS].as(); - //创建rtp数据接收超时检测定时器 - _pRtpTimer.reset( new Timer(timeoutMS / 2000.0, [weakSelf,timeoutMS]() { + //创建rtp数据接收超时检测定时器 + _pRtpTimer.reset( new Timer(timeoutMS / 2000.0, [weakSelf,timeoutMS]() { auto strongSelf=weakSelf.lock(); if(!strongSelf) { return false; } if(strongSelf->_rtpTicker.elapsedTime()> timeoutMS) { - //接收rtp媒体数据包超时 - strongSelf->onPlayResult_l(SockException(Err_timeout,"receive rtp timeout"), true); + //接收rtp媒体数据包超时 + strongSelf->onPlayResult_l(SockException(Err_timeout,"receive rtp timeout"), true); return false; } return true; @@ -780,27 +780,27 @@ void RtspPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete } int RtspPlayer::getTrackIndexByInterleaved(int interleaved) const{ - for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { - if (_aTrackInfo[i]->_interleaved == interleaved) { - return i; - } - } - if(_aTrackInfo.size() == 1){ - return 0; - } - return -1; + for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { + if (_aTrackInfo[i]->_interleaved == interleaved) { + return i; + } + } + if(_aTrackInfo.size() == 1){ + return 0; + } + return -1; } int RtspPlayer::getTrackIndexByTrackType(TrackType trackType) const { - for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { - if (_aTrackInfo[i]->_type == trackType) { - return i; - } - } - if(_aTrackInfo.size() == 1){ - return 0; - } - return -1; + for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { + if (_aTrackInfo[i]->_type == trackType) { + return i; + } + } + if(_aTrackInfo.size() == 1){ + return 0; + } + return -1; } } /* namespace mediakit */ diff --git a/src/Rtsp/RtspPlayer.h b/src/Rtsp/RtspPlayer.h index 5f4f7395..e1bcfeb8 100644 --- a/src/Rtsp/RtspPlayer.h +++ b/src/Rtsp/RtspPlayer.h @@ -50,18 +50,18 @@ namespace mediakit { //实现了rtsp播放器协议部分的功能,及数据接收功能 class RtspPlayer: public PlayerBase,public TcpClient, public RtspSplitter, public RtpReceiver { public: - typedef std::shared_ptr Ptr; + typedef std::shared_ptr Ptr; - RtspPlayer(const EventPoller::Ptr &poller) ; - virtual ~RtspPlayer(void); - void play(const string &strUrl) override; - void pause(bool bPause) override; - void teardown() override; - float getPacketLossRate(TrackType type) const override; + RtspPlayer(const EventPoller::Ptr &poller) ; + virtual ~RtspPlayer(void); + void play(const string &strUrl) override; + void pause(bool bPause) override; + void teardown() override; + float getPacketLossRate(TrackType type) const override; protected: - //派生类回调函数 - virtual bool onCheckSDP(const string &strSdp) = 0; - virtual void onRecvRTP(const RtpPacket::Ptr &pRtppt, const SdpTrack::Ptr &track) = 0; + //派生类回调函数 + virtual bool onCheckSDP(const string &strSdp) = 0; + virtual void onRecvRTP(const RtpPacket::Ptr &pRtppt, const SdpTrack::Ptr &track) = 0; uint32_t getProgressMilliSecond() const; void seekToMilliSecond(uint32_t ms); @@ -83,7 +83,7 @@ protected: * @param rtppt rtp数据包 * @param trackidx track索引 */ - void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override; + void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override; /** @@ -95,61 +95,61 @@ protected: */ virtual void onRtcpPacket(int iTrackidx, SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen); - /////////////TcpClient override///////////// - void onConnect(const SockException &err) override; - void onRecv(const Buffer::Ptr &pBuf) override; - void onErr(const SockException &ex) override; + /////////////TcpClient override///////////// + void onConnect(const SockException &err) override; + void onRecv(const Buffer::Ptr &pBuf) override; + void onErr(const SockException &ex) override; private: - void onRecvRTP_l(const RtpPacket::Ptr &pRtppt, const SdpTrack::Ptr &track); - void onPlayResult_l(const SockException &ex , bool handshakeCompleted); + void onRecvRTP_l(const RtpPacket::Ptr &pRtppt, const SdpTrack::Ptr &track); + void onPlayResult_l(const SockException &ex , bool handshakeCompleted); int getTrackIndexByInterleaved(int interleaved) const; - int getTrackIndexByTrackType(TrackType trackType) const; + int getTrackIndexByTrackType(TrackType trackType) const; - void handleResSETUP(const Parser &parser, unsigned int uiTrackIndex); - void handleResDESCRIBE(const Parser &parser); - bool handleAuthenticationFailure(const string &wwwAuthenticateParamsStr); - void handleResPAUSE(const Parser &parser, int type); + void handleResSETUP(const Parser &parser, unsigned int uiTrackIndex); + void handleResDESCRIBE(const Parser &parser); + bool handleAuthenticationFailure(const string &wwwAuthenticateParamsStr); + void handleResPAUSE(const Parser &parser, int type); - //发送SETUP命令 - void sendSetup(unsigned int uiTrackIndex); - void sendPause(int type , uint32_t ms); - void sendDescribe(); + //发送SETUP命令 + void sendSetup(unsigned int uiTrackIndex); + void sendPause(int type , uint32_t ms); + void sendDescribe(); void sendRtspRequest(const string &cmd, const string &url ,const StrCaseMap &header = StrCaseMap()); - void sendRtspRequest(const string &cmd, const string &url ,const std::initializer_list &header); + void sendRtspRequest(const string &cmd, const string &url ,const std::initializer_list &header); void sendReceiverReport(bool overTcp,int iTrackIndex); - void createUdpSockIfNecessary(int track_idx); + void createUdpSockIfNecessary(int track_idx); private: - string _strUrl; - vector _aTrackInfo; - function _onHandshake; + string _strUrl; + vector _aTrackInfo; + function _onHandshake; Socket::Ptr _apRtpSock[2]; //RTP端口,trackid idx 为数组下标 Socket::Ptr _apRtcpSock[2];//RTCP端口,trackid idx 为数组下标 //rtsp鉴权相关 - string _rtspMd5Nonce; - string _rtspRealm; - //rtsp info - string _strSession; - unsigned int _uiCseq = 1; - string _strContentBase; - Rtsp::eRtpType _eType = Rtsp::RTP_TCP; + string _rtspMd5Nonce; + string _rtspRealm; + //rtsp info + string _strSession; + unsigned int _uiCseq = 1; + string _strContentBase; + Rtsp::eRtpType _eType = Rtsp::RTP_TCP; - /* 丢包率统计需要用到的参数 */ - uint16_t _aui16FirstSeq[2] = { 0 , 0}; - uint16_t _aui16NowSeq[2] = { 0 , 0 }; - uint64_t _aui64RtpRecv[2] = { 0 , 0}; + /* 丢包率统计需要用到的参数 */ + uint16_t _aui16FirstSeq[2] = { 0 , 0}; + uint16_t _aui16NowSeq[2] = { 0 , 0 }; + uint64_t _aui64RtpRecv[2] = { 0 , 0}; - //超时功能实现 - Ticker _rtpTicker; - std::shared_ptr _pPlayTimer; - std::shared_ptr _pRtpTimer; + //超时功能实现 + Ticker _rtpTicker; + std::shared_ptr _pPlayTimer; + std::shared_ptr _pRtpTimer; - //时间戳 - Stamp _stamp[2]; + //时间戳 + Stamp _stamp[2]; - //rtcp相关 + //rtcp相关 RtcpCounter _aRtcpCnt[2]; //rtcp统计,trackid idx 为数组下标 Ticker _aRtcpTicker[2]; //rtcp发送时间,trackid idx 为数组下标 }; diff --git a/src/Rtsp/RtspPlayerImp.h b/src/Rtsp/RtspPlayerImp.h index f61ac7c6..83687033 100644 --- a/src/Rtsp/RtspPlayerImp.h +++ b/src/Rtsp/RtspPlayerImp.h @@ -43,9 +43,9 @@ namespace mediakit { class RtspPlayerImp: public PlayerImp { public: - typedef std::shared_ptr Ptr; - RtspPlayerImp(const EventPoller::Ptr &poller) : PlayerImp(poller){} - virtual ~RtspPlayerImp(){ + typedef std::shared_ptr Ptr; + RtspPlayerImp(const EventPoller::Ptr &poller) : PlayerImp(poller){} + virtual ~RtspPlayerImp(){ DebugL<(_pMediaSrc); - if(_pRtspMediaSrc){ + //派生类回调函数 + bool onCheckSDP(const string &sdp) override { + _pRtspMediaSrc = dynamic_pointer_cast(_pMediaSrc); + if(_pRtspMediaSrc){ _pRtspMediaSrc->setSdp(sdp); - } + } _delegate.reset(new RtspDemuxer); _delegate->loadSdp(sdp); return true; - } - void onRecvRTP(const RtpPacket::Ptr &rtp, const SdpTrack::Ptr &track) override { + } + void onRecvRTP(const RtpPacket::Ptr &rtp, const SdpTrack::Ptr &track) override { if(_pRtspMediaSrc){ // rtsp直接代理是无法判断该rtp是否是I帧,所以GOP缓存基本是无效的 // 为了减少内存使用,那么我们设置为一直关键帧以便清空GOP缓存 @@ -99,7 +99,7 @@ private: } } private: - RtspMediaSource::Ptr _pRtspMediaSrc; + RtspMediaSource::Ptr _pRtspMediaSrc; int _maxAnalysisMS = 0; }; diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index 29a62779..a5e2db68 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -94,16 +94,16 @@ void RtspSession::onError(const SockException& err) { << ")断开:" << err.what() << ",耗时(s):" << duration; - if (_rtpType == Rtsp::RTP_MULTICAST) { - //取消UDP端口监听 - UDPServer::Instance().stopListenPeer(get_peer_ip().data(), this); - } + if (_rtpType == Rtsp::RTP_MULTICAST) { + //取消UDP端口监听 + UDPServer::Instance().stopListenPeer(get_peer_ip().data(), this); + } - if (_http_x_sessioncookie.size() != 0) { - //移除http getter的弱引用记录 - lock_guard lock(g_mtxGetter); - g_mapGetter.erase(_http_x_sessioncookie); - } + if (_http_x_sessioncookie.size() != 0) { + //移除http getter的弱引用记录 + lock_guard lock(g_mtxGetter); + g_mapGetter.erase(_http_x_sessioncookie); + } //流量统计事件广播 GET_CONFIG(uint32_t,iFlowThreshold,General::kFlowThreshold); @@ -118,30 +118,30 @@ void RtspSession::onManager() { GET_CONFIG(uint32_t,keep_alive_sec,Rtsp::kKeepAliveSecond); if (_ticker.createdTime() > handshake_sec * 1000) { - if (_strSession.size() == 0) { - shutdown(SockException(Err_timeout,"illegal connection")); - return; - } - } + if (_strSession.size() == 0) { + shutdown(SockException(Err_timeout,"illegal connection")); + return; + } + } - if ((_rtpType == Rtsp::RTP_UDP || _pushSrc ) && _ticker.elapsedTime() > keep_alive_sec * 1000) { - //如果是推流端或者rtp over udp类型的播放端,那么就做超时检测 + if ((_rtpType == Rtsp::RTP_UDP || _pushSrc ) && _ticker.elapsedTime() > keep_alive_sec * 1000) { + //如果是推流端或者rtp over udp类型的播放端,那么就做超时检测 shutdown(SockException(Err_timeout,"rtp over udp session timeouted")); return; - } + } } void RtspSession::onRecv(const Buffer::Ptr &pBuf) { - _ticker.resetTime(); + _ticker.resetTime(); _ui64TotalBytes += pBuf->size(); if (_onRecv) { - //http poster的请求数据转发给http getter处理 - _onRecv(pBuf); - } else { + //http poster的请求数据转发给http getter处理 + _onRecv(pBuf); + } else { // TraceP(this) << pBuf->size() << "\r\n" << pBuf->data(); - input(pBuf->data(),pBuf->size()); - } + input(pBuf->data(),pBuf->size()); + } } //字符串是否以xx结尾 @@ -151,37 +151,37 @@ static inline bool end_of(const string &str, const string &substr){ }; void RtspSession::onWholeRtspPacket(Parser &parser) { - string strCmd = parser.Method(); //提取出请求命令字 - _iCseq = atoi(parser["CSeq"].data()); - if(_strContentBase.empty() && strCmd != "GET"){ - _strContentBase = parser.Url(); - _mediaInfo.parse(parser.FullUrl()); + string strCmd = parser.Method(); //提取出请求命令字 + _iCseq = atoi(parser["CSeq"].data()); + if(_strContentBase.empty() && strCmd != "GET"){ + _strContentBase = parser.Url(); + _mediaInfo.parse(parser.FullUrl()); _mediaInfo._schema = RTSP_SCHEMA; } - typedef void (RtspSession::*rtsp_request_handler)(const Parser &parser); - static unordered_map s_cmd_functions; - static onceToken token( []() { - s_cmd_functions.emplace("OPTIONS",&RtspSession::handleReq_Options); - s_cmd_functions.emplace("DESCRIBE",&RtspSession::handleReq_Describe); - s_cmd_functions.emplace("ANNOUNCE",&RtspSession::handleReq_ANNOUNCE); - s_cmd_functions.emplace("RECORD",&RtspSession::handleReq_RECORD); - s_cmd_functions.emplace("SETUP",&RtspSession::handleReq_Setup); - s_cmd_functions.emplace("PLAY",&RtspSession::handleReq_Play); - s_cmd_functions.emplace("PAUSE",&RtspSession::handleReq_Pause); - s_cmd_functions.emplace("TEARDOWN",&RtspSession::handleReq_Teardown); - s_cmd_functions.emplace("GET",&RtspSession::handleReq_Get); - s_cmd_functions.emplace("POST",&RtspSession::handleReq_Post); - s_cmd_functions.emplace("SET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); - s_cmd_functions.emplace("GET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); - }, []() {}); + typedef void (RtspSession::*rtsp_request_handler)(const Parser &parser); + static unordered_map s_cmd_functions; + static onceToken token( []() { + s_cmd_functions.emplace("OPTIONS",&RtspSession::handleReq_Options); + s_cmd_functions.emplace("DESCRIBE",&RtspSession::handleReq_Describe); + s_cmd_functions.emplace("ANNOUNCE",&RtspSession::handleReq_ANNOUNCE); + s_cmd_functions.emplace("RECORD",&RtspSession::handleReq_RECORD); + s_cmd_functions.emplace("SETUP",&RtspSession::handleReq_Setup); + s_cmd_functions.emplace("PLAY",&RtspSession::handleReq_Play); + s_cmd_functions.emplace("PAUSE",&RtspSession::handleReq_Pause); + s_cmd_functions.emplace("TEARDOWN",&RtspSession::handleReq_Teardown); + s_cmd_functions.emplace("GET",&RtspSession::handleReq_Get); + s_cmd_functions.emplace("POST",&RtspSession::handleReq_Post); + s_cmd_functions.emplace("SET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); + s_cmd_functions.emplace("GET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); + }, []() {}); - auto it = s_cmd_functions.find(strCmd); - if (it == s_cmd_functions.end()) { + auto it = s_cmd_functions.find(strCmd); + if (it == s_cmd_functions.end()) { sendRtspResponse("403 Forbidden"); shutdown(SockException(Err_shutdown,StrPrinter << "403 Forbidden:" << strCmd)); return; - } + } auto &fun = it->second; try { @@ -197,57 +197,57 @@ void RtspSession::onWholeRtspPacket(Parser &parser) { } void RtspSession::onRtpPacket(const char *data, uint64_t len) { - if(!_pushSrc){ - return; - } + if(!_pushSrc){ + return; + } - int trackIdx = -1; - uint8_t interleaved = data[1]; - if(interleaved %2 == 0){ - trackIdx = getTrackIndexByInterleaved(interleaved); + int trackIdx = -1; + uint8_t interleaved = data[1]; + if(interleaved %2 == 0){ + trackIdx = getTrackIndexByInterleaved(interleaved); if (trackIdx != -1) { handleOneRtp(trackIdx,_aTrackInfo[trackIdx],(unsigned char *)data + 4, len - 4); } - }else{ + }else{ trackIdx = getTrackIndexByInterleaved(interleaved - 1); if (trackIdx != -1) { onRtcpPacket(trackIdx, _aTrackInfo[trackIdx], (unsigned char *) data + 4, len - 4); } - } + } } void RtspSession::onRtcpPacket(int iTrackidx, SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen){ } int64_t RtspSession::getContentLength(Parser &parser) { - if(parser.Method() == "POST"){ - //http post请求的content数据部分是base64编码后的rtsp请求信令包 - return remainDataSize(); - } - return RtspSplitter::getContentLength(parser); + if(parser.Method() == "POST"){ + //http post请求的content数据部分是base64编码后的rtsp请求信令包 + return remainDataSize(); + } + return RtspSplitter::getContentLength(parser); } void RtspSession::handleReq_Options(const Parser &parser) { - //支持这些命令 - sendRtspResponse("200 OK",{"Public" , "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, RECORD, SET_PARAMETER, GET_PARAMETER"}); + //支持这些命令 + sendRtspResponse("200 OK",{"Public" , "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, RECORD, SET_PARAMETER, GET_PARAMETER"}); } void RtspSession::handleReq_ANNOUNCE(const Parser &parser) { - auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA, - _mediaInfo._vhost, - _mediaInfo._app, - _mediaInfo._streamid, - false)); - if(src){ - sendRtspResponse("406 Not Acceptable", {"Content-Type", "text/plain"}, "Already publishing."); + auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA, + _mediaInfo._vhost, + _mediaInfo._app, + _mediaInfo._streamid, + false)); + if(src){ + sendRtspResponse("406 Not Acceptable", {"Content-Type", "text/plain"}, "Already publishing."); string err = StrPrinter << "ANNOUNCE:" << "Already publishing:" << _mediaInfo._vhost << " " << _mediaInfo._app << " " << _mediaInfo._streamid << endl; - throw SockException(Err_shutdown,err); - } + throw SockException(Err_shutdown,err); + } auto full_url = parser.FullUrl(); if(end_of(full_url,".sdp")){ @@ -260,67 +260,67 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) { _strSession = makeRandStr(12); _aTrackInfo = sdpParser.getAvailableTrack(); - _pushSrc = std::make_shared(_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid); - _pushSrc->setListener(dynamic_pointer_cast(shared_from_this())); + _pushSrc = std::make_shared(_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid); + _pushSrc->setListener(dynamic_pointer_cast(shared_from_this())); _pushSrc->setSdp(sdpParser.toString()); - sendRtspResponse("200 OK",{"Content-Base",_strContentBase + "/"}); + sendRtspResponse("200 OK",{"Content-Base",_strContentBase + "/"}); } void RtspSession::handleReq_RECORD(const Parser &parser){ - if (_aTrackInfo.empty() || parser["Session"] != _strSession) { - send_SessionNotFound(); + if (_aTrackInfo.empty() || parser["Session"] != _strSession) { + send_SessionNotFound(); throw SockException(Err_shutdown,_aTrackInfo.empty() ? "can not find any availabe track when record" : "session not found when record"); - } - auto onRes = [this](const string &err,bool enableRtxp,bool enableHls,bool enableMP4){ - bool authSuccess = err.empty(); - if(!authSuccess){ - sendRtspResponse("401 Unauthorized", {"Content-Type", "text/plain"}, err); - shutdown(SockException(Err_shutdown,StrPrinter << "401 Unauthorized:" << err)); - return; - } + } + auto onRes = [this](const string &err,bool enableRtxp,bool enableHls,bool enableMP4){ + bool authSuccess = err.empty(); + if(!authSuccess){ + sendRtspResponse("401 Unauthorized", {"Content-Type", "text/plain"}, err); + shutdown(SockException(Err_shutdown,StrPrinter << "401 Unauthorized:" << err)); + return; + } //设置转协议 _pushSrc->setProtocolTranslation(enableRtxp,enableHls,enableMP4); - _StrPrinter rtp_info; - for(auto &track : _aTrackInfo){ - if (track->_inited == false) { - //还有track没有setup + _StrPrinter rtp_info; + for(auto &track : _aTrackInfo){ + if (track->_inited == false) { + //还有track没有setup shutdown(SockException(Err_shutdown,"track not setuped")); return; - } - rtp_info << "url=" << _strContentBase << "/" << track->_control_surffix << ","; - } + } + rtp_info << "url=" << _strContentBase << "/" << track->_control_surffix << ","; + } - rtp_info.pop_back(); - sendRtspResponse("200 OK", {"RTP-Info",rtp_info}); - if(_rtpType == Rtsp::RTP_TCP){ - //如果是rtsp推流服务器,并且是TCP推流,那么加大TCP接收缓存,这样能提升接收性能 - _sock->setReadBuffer(std::make_shared(256 * 1024)); + rtp_info.pop_back(); + sendRtspResponse("200 OK", {"RTP-Info",rtp_info}); + if(_rtpType == Rtsp::RTP_TCP){ + //如果是rtsp推流服务器,并且是TCP推流,那么加大TCP接收缓存,这样能提升接收性能 + _sock->setReadBuffer(std::make_shared(256 * 1024)); setSocketFlags(); - } - }; + } + }; - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - Broadcast::PublishAuthInvoker invoker = [weakSelf,onRes](const string &err,bool enableRtxp,bool enableHls,bool enableMP4){ - auto strongSelf = weakSelf.lock(); - if(!strongSelf){ - return; - } - strongSelf->async([weakSelf,onRes,err,enableRtxp,enableHls,enableMP4](){ - auto strongSelf = weakSelf.lock(); - if(!strongSelf){ - return; - } - onRes(err,enableRtxp,enableHls,enableMP4); - }); - }; + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + Broadcast::PublishAuthInvoker invoker = [weakSelf,onRes](const string &err,bool enableRtxp,bool enableHls,bool enableMP4){ + auto strongSelf = weakSelf.lock(); + if(!strongSelf){ + return; + } + strongSelf->async([weakSelf,onRes,err,enableRtxp,enableHls,enableMP4](){ + auto strongSelf = weakSelf.lock(); + if(!strongSelf){ + return; + } + onRes(err,enableRtxp,enableHls,enableMP4); + }); + }; - //rtsp推流需要鉴权 - auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish,_mediaInfo,invoker,*this); - if(!flag){ - //该事件无人监听,默认不鉴权 + //rtsp推流需要鉴权 + auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish,_mediaInfo,invoker,*this); + if(!flag){ + //该事件无人监听,默认不鉴权 GET_CONFIG(bool,toRtxp,General::kPublishToRtxp); GET_CONFIG(bool,toHls,General::kPublishToHls); GET_CONFIG(bool,toMP4,General::kPublishToMP4); @@ -385,7 +385,7 @@ void RtspSession::onAuthSuccess() { strongSelf->_aTrackInfo = SdpParser(rtsp_src->getSdp()).getAvailableTrack(); if (strongSelf->_aTrackInfo.empty()) { //该流无效 - DebugL << "无trackInfo,该流无效"; + DebugL << "无trackInfo,该流无效"; strongSelf->send_StreamNotFound(); strongSelf->shutdown(SockException(Err_shutdown,"can not find any available track in sdp")); return; @@ -472,7 +472,7 @@ void RtspSession::onAuthBasic(const string &realm,const string &strBase64){ } void RtspSession::onAuthDigest(const string &realm,const string &strMd5){ - DebugP(this) << strMd5; + DebugP(this) << strMd5; auto mapTmp = Parser::parseArgs(strMd5,",","="); decltype(mapTmp) map; for(auto &pr : mapTmp){ @@ -561,7 +561,7 @@ void RtspSession::onAuthUser(const string &realm,const string &authorization){ } //请求中包含认证信息 auto authType = FindField(authorization.data(),NULL," "); - auto authStr = FindField(authorization.data()," ",NULL); + auto authStr = FindField(authorization.data()," ",NULL); if(authType.empty() || authStr.empty()){ //认证信息格式不合法,回复401 Unauthorized onAuthFailed(realm,"can not find auth type or auth string"); @@ -579,50 +579,50 @@ void RtspSession::onAuthUser(const string &realm,const string &authorization){ } } inline void RtspSession::send_StreamNotFound() { - sendRtspResponse("404 Stream Not Found",{"Connection","Close"}); + sendRtspResponse("404 Stream Not Found",{"Connection","Close"}); } inline void RtspSession::send_UnsupportedTransport() { - sendRtspResponse("461 Unsupported Transport",{"Connection","Close"}); + sendRtspResponse("461 Unsupported Transport",{"Connection","Close"}); } inline void RtspSession::send_SessionNotFound() { - sendRtspResponse("454 Session Not Found",{"Connection","Close"}); + sendRtspResponse("454 Session Not Found",{"Connection","Close"}); } void RtspSession::handleReq_Setup(const Parser &parser) { //处理setup命令,该函数可能进入多次 auto controlSuffix = split(parser.FullUrl(),"/").back();// parser.FullUrl().substr(_strContentBase.size()); if(controlSuffix.front() == '/'){ - controlSuffix = controlSuffix.substr(1); + controlSuffix = controlSuffix.substr(1); } - int trackIdx = getTrackIndexByControlSuffix(controlSuffix); - if (trackIdx == -1) { - //未找到相应track + int trackIdx = getTrackIndexByControlSuffix(controlSuffix); + if (trackIdx == -1) { + //未找到相应track throw SockException(Err_shutdown, StrPrinter << "can not find any track by control suffix:" << controlSuffix); } - SdpTrack::Ptr &trackRef = _aTrackInfo[trackIdx]; - if (trackRef->_inited) { - //已经初始化过该Track + SdpTrack::Ptr &trackRef = _aTrackInfo[trackIdx]; + if (trackRef->_inited) { + //已经初始化过该Track throw SockException(Err_shutdown, "can not setup one track twice"); - } - trackRef->_inited = true; //现在初始化 + } + trackRef->_inited = true; //现在初始化 - if(_rtpType == Rtsp::RTP_Invalid){ - auto &strTransport = parser["Transport"]; - if(strTransport.find("TCP") != string::npos){ - _rtpType = Rtsp::RTP_TCP; - }else if(strTransport.find("multicast") != string::npos){ - _rtpType = Rtsp::RTP_MULTICAST; - }else{ - _rtpType = Rtsp::RTP_UDP; - } - } + if(_rtpType == Rtsp::RTP_Invalid){ + auto &strTransport = parser["Transport"]; + if(strTransport.find("TCP") != string::npos){ + _rtpType = Rtsp::RTP_TCP; + }else if(strTransport.find("multicast") != string::npos){ + _rtpType = Rtsp::RTP_MULTICAST; + }else{ + _rtpType = Rtsp::RTP_UDP; + } + } //允许接收rtp、rtcp包 - RtspSplitter::enableRecvRtp(_rtpType == Rtsp::RTP_TCP); + RtspSplitter::enableRecvRtp(_rtpType == Rtsp::RTP_TCP); - switch (_rtpType) { - case Rtsp::RTP_TCP: { + switch (_rtpType) { + case Rtsp::RTP_TCP: { if(_pushSrc){ //rtsp推流时,interleaved由推流者决定 auto key_values = Parser::parseArgs(parser["Transport"],";","="); @@ -636,192 +636,192 @@ void RtspSession::handleReq_Setup(const Parser &parser) { //rtsp播放时,由于数据共享分发,所以interleaved必须由服务器决定 trackRef->_interleaved = 2 * trackRef->_type; } - sendRtspResponse("200 OK", - {"Transport",StrPrinter << "RTP/AVP/TCP;unicast;" - << "interleaved=" << (int)trackRef->_interleaved << "-" << (int)trackRef->_interleaved + 1 << ";" - << "ssrc=" << printSSRC(trackRef->_ssrc), - "x-Transport-Options" , "late-tolerance=1.400000", - "x-Dynamic-Rate" , "1" - }); - } - break; - case Rtsp::RTP_UDP: { - //我们用trackIdx区分rtp和rtcp包 - auto pSockRtp = std::make_shared(_sock->getPoller()); - if (!pSockRtp->bindUdpSock(0,get_local_ip().data())) { - //分配端口失败 - send_NotAcceptable(); + sendRtspResponse("200 OK", + {"Transport",StrPrinter << "RTP/AVP/TCP;unicast;" + << "interleaved=" << (int)trackRef->_interleaved << "-" << (int)trackRef->_interleaved + 1 << ";" + << "ssrc=" << printSSRC(trackRef->_ssrc), + "x-Transport-Options" , "late-tolerance=1.400000", + "x-Dynamic-Rate" , "1" + }); + } + break; + case Rtsp::RTP_UDP: { + //我们用trackIdx区分rtp和rtcp包 + auto pSockRtp = std::make_shared(_sock->getPoller()); + if (!pSockRtp->bindUdpSock(0,get_local_ip().data())) { + //分配端口失败 + send_NotAcceptable(); throw SockException(Err_shutdown, "open rtp socket failed"); } - auto pSockRtcp = std::make_shared(_sock->getPoller()); - if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + 1,get_local_ip().data())) { - //分配端口失败 - send_NotAcceptable(); + auto pSockRtcp = std::make_shared(_sock->getPoller()); + if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + 1,get_local_ip().data())) { + //分配端口失败 + send_NotAcceptable(); throw SockException(Err_shutdown, "open rtcp socket failed"); } - _apRtpSock[trackIdx] = pSockRtp; - _apRtcpSock[trackIdx] = pSockRtcp; - //设置客户端内网端口信息 - string strClientPort = FindField(parser["Transport"].data(), "client_port=", NULL); - uint16_t ui16RtpPort = atoi( FindField(strClientPort.data(), NULL, "-").data()); + _apRtpSock[trackIdx] = pSockRtp; + _apRtcpSock[trackIdx] = pSockRtcp; + //设置客户端内网端口信息 + string strClientPort = FindField(parser["Transport"].data(), "client_port=", NULL); + uint16_t ui16RtpPort = atoi( FindField(strClientPort.data(), NULL, "-").data()); uint16_t ui16RtcpPort = atoi( FindField(strClientPort.data(), "-" , NULL).data()); struct sockaddr_in peerAddr; //设置rtp发送目标地址 - peerAddr.sin_family = AF_INET; - peerAddr.sin_port = htons(ui16RtpPort); - peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data()); - bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero); - pSockRtp->setSendPeerAddr((struct sockaddr *)(&peerAddr)); + peerAddr.sin_family = AF_INET; + peerAddr.sin_port = htons(ui16RtpPort); + peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data()); + bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero); + pSockRtp->setSendPeerAddr((struct sockaddr *)(&peerAddr)); - //设置rtcp发送目标地址 + //设置rtcp发送目标地址 peerAddr.sin_family = AF_INET; peerAddr.sin_port = htons(ui16RtcpPort); peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data()); bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero); pSockRtcp->setSendPeerAddr((struct sockaddr *)(&peerAddr)); - //尝试获取客户端nat映射地址 - startListenPeerUdpData(trackIdx); - //InfoP(this) << "分配端口:" << srv_port; + //尝试获取客户端nat映射地址 + startListenPeerUdpData(trackIdx); + //InfoP(this) << "分配端口:" << srv_port; - sendRtspResponse("200 OK", - {"Transport",StrPrinter << "RTP/AVP/UDP;unicast;" - << "client_port=" << strClientPort << ";" - << "server_port=" << pSockRtp->get_local_port() << "-" << pSockRtcp->get_local_port() << ";" - << "ssrc=" << printSSRC(trackRef->_ssrc) - }); - } - break; - case Rtsp::RTP_MULTICAST: { - if(!_multicaster){ - _multicaster = RtpMultiCaster::get(getPoller(),get_local_ip(),_mediaInfo._vhost, _mediaInfo._app, _mediaInfo._streamid); - if (!_multicaster) { - send_NotAcceptable(); + sendRtspResponse("200 OK", + {"Transport",StrPrinter << "RTP/AVP/UDP;unicast;" + << "client_port=" << strClientPort << ";" + << "server_port=" << pSockRtp->get_local_port() << "-" << pSockRtcp->get_local_port() << ";" + << "ssrc=" << printSSRC(trackRef->_ssrc) + }); + } + break; + case Rtsp::RTP_MULTICAST: { + if(!_multicaster){ + _multicaster = RtpMultiCaster::get(getPoller(),get_local_ip(),_mediaInfo._vhost, _mediaInfo._app, _mediaInfo._streamid); + if (!_multicaster) { + send_NotAcceptable(); throw SockException(Err_shutdown, "can not get a available udp multicast socket"); } - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - _multicaster->setDetachCB(this, [weakSelf]() { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } - strongSelf->safeShutdown(SockException(Err_shutdown,"ring buffer detached")); - }); - } - int iSrvPort = _multicaster->getPort(trackRef->_type); - //我们用trackIdx区分rtp和rtcp包 - //由于组播udp端口是共享的,而rtcp端口为组播udp端口+1,所以rtcp端口需要改成共享端口 - auto pSockRtcp = UDPServer::Instance().getSock(getPoller(),get_local_ip().data(),2*trackIdx + 1,iSrvPort + 1); - if (!pSockRtcp) { - //分配端口失败 - send_NotAcceptable(); + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + _multicaster->setDetachCB(this, [weakSelf]() { + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } + strongSelf->safeShutdown(SockException(Err_shutdown,"ring buffer detached")); + }); + } + int iSrvPort = _multicaster->getPort(trackRef->_type); + //我们用trackIdx区分rtp和rtcp包 + //由于组播udp端口是共享的,而rtcp端口为组播udp端口+1,所以rtcp端口需要改成共享端口 + auto pSockRtcp = UDPServer::Instance().getSock(getPoller(),get_local_ip().data(),2*trackIdx + 1,iSrvPort + 1); + if (!pSockRtcp) { + //分配端口失败 + send_NotAcceptable(); throw SockException(Err_shutdown, "open shared rtcp socket failed"); - } - startListenPeerUdpData(trackIdx); + } + startListenPeerUdpData(trackIdx); GET_CONFIG(uint32_t,udpTTL,MultiCast::kUdpTTL); - sendRtspResponse("200 OK", - {"Transport",StrPrinter << "RTP/AVP;multicast;" - << "destination=" << _multicaster->getIP() << ";" - << "source=" << get_local_ip() << ";" - << "port=" << iSrvPort << "-" << pSockRtcp->get_local_port() << ";" - << "ttl=" << udpTTL << ";" - << "ssrc=" << printSSRC(trackRef->_ssrc) - }); - } - break; - default: - break; - } + sendRtspResponse("200 OK", + {"Transport",StrPrinter << "RTP/AVP;multicast;" + << "destination=" << _multicaster->getIP() << ";" + << "source=" << get_local_ip() << ";" + << "port=" << iSrvPort << "-" << pSockRtcp->get_local_port() << ";" + << "ttl=" << udpTTL << ";" + << "ssrc=" << printSSRC(trackRef->_ssrc) + }); + } + break; + default: + break; + } } void RtspSession::handleReq_Play(const Parser &parser) { - if (_aTrackInfo.empty() || parser["Session"] != _strSession) { - send_SessionNotFound(); + if (_aTrackInfo.empty() || parser["Session"] != _strSession) { + send_SessionNotFound(); throw SockException(Err_shutdown,_aTrackInfo.empty() ? "can not find any availabe track when play" : "session not found when play"); } - auto strRange = parser["Range"]; + auto strRange = parser["Range"]; auto onRes = [this,strRange](const string &err){ bool authSuccess = err.empty(); if(!authSuccess){ //第一次play是播放,否则是恢复播放。只对播放鉴权 - sendRtspResponse("401 Unauthorized", {"Content-Type", "text/plain"}, err); + sendRtspResponse("401 Unauthorized", {"Content-Type", "text/plain"}, err); shutdown(SockException(Err_shutdown,StrPrinter << "401 Unauthorized:" << err)); return; } auto pMediaSrc = _pMediaSrc.lock(); if(!pMediaSrc){ - send_StreamNotFound(); - shutdown(SockException(Err_shutdown,"rtsp stream released")); - return; + send_StreamNotFound(); + shutdown(SockException(Err_shutdown,"rtsp stream released")); + return; } bool useBuf = true; - _enableSendRtp = false; + _enableSendRtp = false; - if (strRange.size() && !_bFirstPlay) { + if (strRange.size() && !_bFirstPlay) { //这个是seek操作 - auto strStart = FindField(strRange.data(), "npt=", "-"); - if (strStart == "now") { - strStart = "0"; - } - auto iStartTime = 1000 * atof(strStart.data()); - InfoP(this) << "rtsp seekTo(ms):" << iStartTime; - useBuf = !pMediaSrc->seekTo(iStartTime); - }else if(pMediaSrc->totalReaderCount() == 0){ - //第一个消费者 - pMediaSrc->seekTo(0); - } - _bFirstPlay = false; + auto strStart = FindField(strRange.data(), "npt=", "-"); + if (strStart == "now") { + strStart = "0"; + } + auto iStartTime = 1000 * atof(strStart.data()); + InfoP(this) << "rtsp seekTo(ms):" << iStartTime; + useBuf = !pMediaSrc->seekTo(iStartTime); + }else if(pMediaSrc->totalReaderCount() == 0){ + //第一个消费者 + pMediaSrc->seekTo(0); + } + _bFirstPlay = false; - _StrPrinter rtp_info; - for(auto &track : _aTrackInfo){ - if (track->_inited == false) { - //还有track没有setup + _StrPrinter rtp_info; + for(auto &track : _aTrackInfo){ + if (track->_inited == false) { + //还有track没有setup shutdown(SockException(Err_shutdown,"track not setuped")); return; - } - track->_ssrc = pMediaSrc->getSsrc(track->_type); - track->_seq = pMediaSrc->getSeqence(track->_type); - track->_time_stamp = pMediaSrc->getTimeStamp(track->_type); + } + track->_ssrc = pMediaSrc->getSsrc(track->_type); + track->_seq = pMediaSrc->getSeqence(track->_type); + track->_time_stamp = pMediaSrc->getTimeStamp(track->_type); - rtp_info << "url=" << _strContentBase << "/" << track->_control_surffix << ";" - << "seq=" << track->_seq << ";" - << "rtptime=" << (int)(track->_time_stamp * (track->_samplerate / 1000)) << ","; - } + rtp_info << "url=" << _strContentBase << "/" << track->_control_surffix << ";" + << "seq=" << track->_seq << ";" + << "rtptime=" << (int)(track->_time_stamp * (track->_samplerate / 1000)) << ","; + } - rtp_info.pop_back(); + rtp_info.pop_back(); - sendRtspResponse("200 OK", - {"Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << pMediaSrc->getTimeStamp(TrackInvalid) / 1000.0, - "RTP-Info",rtp_info - }); + sendRtspResponse("200 OK", + {"Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << pMediaSrc->getTimeStamp(TrackInvalid) / 1000.0, + "RTP-Info",rtp_info + }); - _enableSendRtp = true; + _enableSendRtp = true; setSocketFlags(); - if (!_pRtpReader && _rtpType != Rtsp::RTP_MULTICAST) { - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - _pRtpReader = pMediaSrc->getRing()->attach(getPoller(),useBuf); - _pRtpReader->setDetachCB([weakSelf]() { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } + if (!_pRtpReader && _rtpType != Rtsp::RTP_MULTICAST) { + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + _pRtpReader = pMediaSrc->getRing()->attach(getPoller(),useBuf); + _pRtpReader->setDetachCB([weakSelf]() { + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } strongSelf->shutdown(SockException(Err_shutdown,"rtsp ring buffer detached")); }); - _pRtpReader->setReadCB([weakSelf](const RtpPacket::Ptr &pack) { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return; - } - if(strongSelf->_enableSendRtp) { - strongSelf->sendRtpPacket(pack); - } - }); - } + _pRtpReader->setReadCB([weakSelf](const RtpPacket::Ptr &pack) { + auto strongSelf = weakSelf.lock(); + if(!strongSelf) { + return; + } + if(strongSelf->_enableSendRtp) { + strongSelf->sendRtpPacket(pack); + } + }); + } }; weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); @@ -852,69 +852,69 @@ void RtspSession::handleReq_Play(const Parser &parser) { } void RtspSession::handleReq_Pause(const Parser &parser) { - if (parser["Session"] != _strSession) { - send_SessionNotFound(); + if (parser["Session"] != _strSession) { + send_SessionNotFound(); throw SockException(Err_shutdown,"session not found when pause"); } - sendRtspResponse("200 OK"); - _enableSendRtp = false; + sendRtspResponse("200 OK"); + _enableSendRtp = false; } void RtspSession::handleReq_Teardown(const Parser &parser) { - sendRtspResponse("200 OK"); + sendRtspResponse("200 OK"); throw SockException(Err_shutdown,"rtsp player send teardown request"); } void RtspSession::handleReq_Get(const Parser &parser) { - _http_x_sessioncookie = parser["x-sessioncookie"]; - sendRtspResponse("200 OK", - {"Cache-Control","no-store", - "Pragma","no-store", - "Content-Type","application/x-rtsp-tunnelled", - },"","HTTP/1.0"); + _http_x_sessioncookie = parser["x-sessioncookie"]; + sendRtspResponse("200 OK", + {"Cache-Control","no-store", + "Pragma","no-store", + "Content-Type","application/x-rtsp-tunnelled", + },"","HTTP/1.0"); - //注册http getter,以便http poster绑定 - lock_guard lock(g_mtxGetter); - g_mapGetter[_http_x_sessioncookie] = dynamic_pointer_cast(shared_from_this()); + //注册http getter,以便http poster绑定 + lock_guard lock(g_mtxGetter); + g_mapGetter[_http_x_sessioncookie] = dynamic_pointer_cast(shared_from_this()); } void RtspSession::handleReq_Post(const Parser &parser) { - lock_guard lock(g_mtxGetter); - string sessioncookie = parser["x-sessioncookie"]; - //Poster 找到 Getter - auto it = g_mapGetter.find(sessioncookie); - if (it == g_mapGetter.end()) { + lock_guard lock(g_mtxGetter); + string sessioncookie = parser["x-sessioncookie"]; + //Poster 找到 Getter + auto it = g_mapGetter.find(sessioncookie); + if (it == g_mapGetter.end()) { throw SockException(Err_shutdown,"can not find http getter by x-sessioncookie"); } - //Poster 找到Getter的SOCK - auto httpGetterWeak = it->second; - //移除http getter的弱引用记录 - g_mapGetter.erase(sessioncookie); + //Poster 找到Getter的SOCK + auto httpGetterWeak = it->second; + //移除http getter的弱引用记录 + g_mapGetter.erase(sessioncookie); - //http poster收到请求后转发给http getter处理 - _onRecv = [this,httpGetterWeak](const Buffer::Ptr &pBuf){ - auto httpGetterStrong = httpGetterWeak.lock(); - if(!httpGetterStrong){ - shutdown(SockException(Err_shutdown,"http getter released")); - return; - } + //http poster收到请求后转发给http getter处理 + _onRecv = [this,httpGetterWeak](const Buffer::Ptr &pBuf){ + auto httpGetterStrong = httpGetterWeak.lock(); + if(!httpGetterStrong){ + shutdown(SockException(Err_shutdown,"http getter released")); + return; + } - //切换到http getter的线程 - httpGetterStrong->async([pBuf,httpGetterWeak](){ - auto httpGetterStrong = httpGetterWeak.lock(); - if(!httpGetterStrong){ - return; - } - httpGetterStrong->onRecv(std::make_shared(decodeBase64(string(pBuf->data(),pBuf->size())))); - }); - }; + //切换到http getter的线程 + httpGetterStrong->async([pBuf,httpGetterWeak](){ + auto httpGetterStrong = httpGetterWeak.lock(); + if(!httpGetterStrong){ + return; + } + httpGetterStrong->onRecv(std::make_shared(decodeBase64(string(pBuf->data(),pBuf->size())))); + }); + }; - if(!parser.Content().empty()){ - //http poster后面的粘包 - _onRecv(std::make_shared(parser.Content())); - } + if(!parser.Content().empty()){ + //http poster后面的粘包 + _onRecv(std::make_shared(parser.Content())); + } sendRtspResponse("200 OK", {"Cache-Control","no-store", @@ -924,33 +924,33 @@ void RtspSession::handleReq_Post(const Parser &parser) { } void RtspSession::handleReq_SET_PARAMETER(const Parser &parser) { - //TraceP(this) <onWrite(rtppt, false); + _pushSrc->onWrite(rtppt, false); } inline void RtspSession::onRcvPeerUdpData(int intervaled, const Buffer::Ptr &pBuf, const struct sockaddr& addr) { - //这是rtcp心跳包,说明播放器还存活 - _ticker.resetTime(); + //这是rtcp心跳包,说明播放器还存活 + _ticker.resetTime(); - if(intervaled % 2 == 0){ - if(_pushSrc){ - //这是rtsp推流上来的rtp包 - handleOneRtp(intervaled / 2,_aTrackInfo[intervaled / 2],( unsigned char *)pBuf->data(),pBuf->size()); - }else if(!_udpSockConnected.count(intervaled)){ + if(intervaled % 2 == 0){ + if(_pushSrc){ + //这是rtsp推流上来的rtp包 + handleOneRtp(intervaled / 2,_aTrackInfo[intervaled / 2],( unsigned char *)pBuf->data(),pBuf->size()); + }else if(!_udpSockConnected.count(intervaled)){ //这是rtsp播放器的rtp打洞包 _udpSockConnected.emplace(intervaled); _apRtpSock[intervaled / 2]->setSendPeerAddr(&addr); - } - }else{ - //rtcp包 + } + }else{ + //rtcp包 if(!_udpSockConnected.count(intervaled)){ _udpSockConnected.emplace(intervaled); _apRtcpSock[(intervaled - 1) / 2]->setSendPeerAddr(&addr); @@ -961,13 +961,13 @@ inline void RtspSession::onRcvPeerUdpData(int intervaled, const Buffer::Ptr &pBu inline void RtspSession::startListenPeerUdpData(int trackIdx) { - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); auto srcIP = inet_addr(get_peer_ip().data()); - auto onUdpData = [weakSelf,srcIP](const Buffer::Ptr &pBuf, struct sockaddr *pPeerAddr,int intervaled){ - auto strongSelf=weakSelf.lock(); - if(!strongSelf) { - return false; - } + auto onUdpData = [weakSelf,srcIP](const Buffer::Ptr &pBuf, struct sockaddr *pPeerAddr,int intervaled){ + auto strongSelf=weakSelf.lock(); + if(!strongSelf) { + return false; + } if (((struct sockaddr_in *) pPeerAddr)->sin_addr.s_addr != srcIP) { WarnP(strongSelf.get()) << ((intervaled % 2 == 0) ? "收到其他地址的rtp数据:" : "收到其他地址的rtcp数据:") @@ -975,154 +975,154 @@ inline void RtspSession::startListenPeerUdpData(int trackIdx) { return true; } - struct sockaddr addr=*pPeerAddr; - strongSelf->async([weakSelf,pBuf,addr,intervaled]() { - auto strongSelf=weakSelf.lock(); - if(!strongSelf) { - return; - } - strongSelf->onRcvPeerUdpData(intervaled,pBuf,addr); - }); - return true; - }; + struct sockaddr addr=*pPeerAddr; + strongSelf->async([weakSelf,pBuf,addr,intervaled]() { + auto strongSelf=weakSelf.lock(); + if(!strongSelf) { + return; + } + strongSelf->onRcvPeerUdpData(intervaled,pBuf,addr); + }); + return true; + }; - switch (_rtpType){ - case Rtsp::RTP_MULTICAST:{ - //组播使用的共享rtcp端口 - UDPServer::Instance().listenPeer(get_peer_ip().data(), this, [onUdpData]( - int intervaled, const Buffer::Ptr &pBuf, struct sockaddr *pPeerAddr) { - return onUdpData(pBuf,pPeerAddr,intervaled); - }); - } - break; - case Rtsp::RTP_UDP:{ - auto setEvent = [&](Socket::Ptr &sock,int intervaled){ - if(!sock){ - WarnP(this) << "udp端口为空:" << intervaled; - return; - } - sock->setOnRead([onUdpData,intervaled](const Buffer::Ptr &pBuf, struct sockaddr *pPeerAddr , int addr_len){ - onUdpData(pBuf,pPeerAddr,intervaled); - }); - }; - setEvent(_apRtpSock[trackIdx], 2*trackIdx ); - setEvent(_apRtcpSock[trackIdx], 2*trackIdx + 1 ); - } - break; + switch (_rtpType){ + case Rtsp::RTP_MULTICAST:{ + //组播使用的共享rtcp端口 + UDPServer::Instance().listenPeer(get_peer_ip().data(), this, [onUdpData]( + int intervaled, const Buffer::Ptr &pBuf, struct sockaddr *pPeerAddr) { + return onUdpData(pBuf,pPeerAddr,intervaled); + }); + } + break; + case Rtsp::RTP_UDP:{ + auto setEvent = [&](Socket::Ptr &sock,int intervaled){ + if(!sock){ + WarnP(this) << "udp端口为空:" << intervaled; + return; + } + sock->setOnRead([onUdpData,intervaled](const Buffer::Ptr &pBuf, struct sockaddr *pPeerAddr , int addr_len){ + onUdpData(pBuf,pPeerAddr,intervaled); + }); + }; + setEvent(_apRtpSock[trackIdx], 2*trackIdx ); + setEvent(_apRtcpSock[trackIdx], 2*trackIdx + 1 ); + } + break; - default: - break; - } + default: + break; + } } static string dateStr(){ - char buf[64]; - time_t tt = time(NULL); - strftime(buf, sizeof buf, "%a, %b %d %Y %H:%M:%S GMT", gmtime(&tt)); - return buf; + char buf[64]; + time_t tt = time(NULL); + strftime(buf, sizeof buf, "%a, %b %d %Y %H:%M:%S GMT", gmtime(&tt)); + return buf; } bool RtspSession::sendRtspResponse(const string &res_code, - const StrCaseMap &header_const, - const string &sdp, - const char *protocol){ - auto header = header_const; - header.emplace("CSeq",StrPrinter << _iCseq); - if(!_strSession.empty()){ - header.emplace("Session",_strSession); - } + const StrCaseMap &header_const, + const string &sdp, + const char *protocol){ + auto header = header_const; + header.emplace("CSeq",StrPrinter << _iCseq); + if(!_strSession.empty()){ + header.emplace("Session",_strSession); + } - header.emplace("Server",SERVER_NAME "(build in " __DATE__ " " __TIME__ ")"); - header.emplace("Date",dateStr()); + header.emplace("Server",SERVER_NAME "(build in " __DATE__ " " __TIME__ ")"); + header.emplace("Date",dateStr()); - if(!sdp.empty()){ - header.emplace("Content-Length",StrPrinter << sdp.size()); - header.emplace("Content-Type","application/sdp"); - } + if(!sdp.empty()){ + header.emplace("Content-Length",StrPrinter << sdp.size()); + header.emplace("Content-Type","application/sdp"); + } - _StrPrinter printer; - printer << protocol << " " << res_code << "\r\n"; - for (auto &pr : header){ - printer << pr.first << ": " << pr.second << "\r\n"; - } + _StrPrinter printer; + printer << protocol << " " << res_code << "\r\n"; + for (auto &pr : header){ + printer << pr.first << ": " << pr.second << "\r\n"; + } - printer << "\r\n"; + printer << "\r\n"; - if(!sdp.empty()){ - printer << sdp; - } + if(!sdp.empty()){ + printer << sdp; + } // DebugP(this) << printer; - return send(std::make_shared(printer)) > 0 ; + return send(std::make_shared(printer)) > 0 ; } int RtspSession::send(const Buffer::Ptr &pkt){ // if(!_enableSendRtp){ // DebugP(this) << pkt->data(); // } - _ui64TotalBytes += pkt->size(); - return TcpSession::send(pkt); + _ui64TotalBytes += pkt->size(); + return TcpSession::send(pkt); } bool RtspSession::sendRtspResponse(const string &res_code, - const std::initializer_list &header, - const string &sdp, - const char *protocol) { - string key; - StrCaseMap header_map; - int i = 0; - for(auto &val : header){ - if(++i % 2 == 0){ - header_map.emplace(key,val); - }else{ - key = val; - } - } - return sendRtspResponse(res_code,header_map,sdp,protocol); + const std::initializer_list &header, + const string &sdp, + const char *protocol) { + string key; + StrCaseMap header_map; + int i = 0; + for(auto &val : header){ + if(++i % 2 == 0){ + header_map.emplace(key,val); + }else{ + key = val; + } + } + return sendRtspResponse(res_code,header_map,sdp,protocol); } inline string RtspSession::printSSRC(uint32_t ui32Ssrc) { - char tmp[9] = { 0 }; - ui32Ssrc = htonl(ui32Ssrc); - uint8_t *pSsrc = (uint8_t *) &ui32Ssrc; - for (int i = 0; i < 4; i++) { - sprintf(tmp + 2 * i, "%02X", pSsrc[i]); - } - return tmp; + char tmp[9] = { 0 }; + ui32Ssrc = htonl(ui32Ssrc); + uint8_t *pSsrc = (uint8_t *) &ui32Ssrc; + for (int i = 0; i < 4; i++) { + sprintf(tmp + 2 * i, "%02X", pSsrc[i]); + } + return tmp; } inline int RtspSession::getTrackIndexByTrackType(TrackType type) { - for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { - if (type == _aTrackInfo[i]->_type) { - return i; - } - } + for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { + if (type == _aTrackInfo[i]->_type) { + return i; + } + } if(_aTrackInfo.size() == 1){ return 0; } - return -1; + return -1; } inline int RtspSession::getTrackIndexByControlSuffix(const string &controlSuffix) { - for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { - if (controlSuffix == _aTrackInfo[i]->_control_surffix) { - return i; - } - } - if(_aTrackInfo.size() == 1){ + for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { + if (controlSuffix == _aTrackInfo[i]->_control_surffix) { + return i; + } + } + if(_aTrackInfo.size() == 1){ return 0; - } - return -1; + } + return -1; } inline int RtspSession::getTrackIndexByInterleaved(int interleaved){ - for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { - if (_aTrackInfo[i]->_interleaved == interleaved) { - return i; - } - } + for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { + if (_aTrackInfo[i]->_interleaved == interleaved) { + return i; + } + } if(_aTrackInfo.size() == 1){ return 0; } - return -1; + return -1; } bool RtspSession::close(MediaSource &sender,bool force) { @@ -1130,9 +1130,9 @@ bool RtspSession::close(MediaSource &sender,bool force) { if(!_pushSrc || (!force && _pushSrc->totalReaderCount())){ return false; } - string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force; - safeShutdown(SockException(Err_shutdown,err)); - return true; + string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force; + safeShutdown(SockException(Err_shutdown,err)); + return true; } diff --git a/src/Rtsp/RtspSession.h b/src/Rtsp/RtspSession.h index 6a77dfc5..ae234493 100644 --- a/src/Rtsp/RtspSession.h +++ b/src/Rtsp/RtspSession.h @@ -69,20 +69,20 @@ private: class RtspSession: public TcpSession, public RtspSplitter, public RtpReceiver , public MediaSourceEvent{ public: - typedef std::shared_ptr Ptr; - typedef std::function onGetRealm; + typedef std::shared_ptr Ptr; + typedef std::function onGetRealm; //encrypted为true是则表明是md5加密的密码,否则是明文密码 //在请求明文密码时如果提供md5密码者则会导致认证失败 - typedef std::function onAuth; + typedef std::function onAuth; - RtspSession(const Socket::Ptr &pSock); - virtual ~RtspSession(); - ////TcpSession override//// - void onRecv(const Buffer::Ptr &pBuf) override; - void onError(const SockException &err) override; - void onManager() override; + RtspSession(const Socket::Ptr &pSock); + virtual ~RtspSession(); + ////TcpSession override//// + void onRecv(const Buffer::Ptr &pBuf) override; + void onError(const SockException &err) override; + void onManager() override; protected: - //RtspSplitter override + //RtspSplitter override /** * 收到完整的rtsp包回调,包括sdp等content数据 * @param parser rtsp包 @@ -103,14 +103,14 @@ protected: */ int64_t getContentLength(Parser &parser) override; - //RtpReceiver override - void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override; - //MediaSourceEvent override - bool close(MediaSource &sender,bool force) override ; + //RtpReceiver override + void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override; + //MediaSourceEvent override + bool close(MediaSource &sender,bool force) override ; void onNoneReader(MediaSource &sender) override; - int totalReaderCount(MediaSource &sender) override; + int totalReaderCount(MediaSource &sender) override; - //TcpSession override + //TcpSession override int send(const Buffer::Ptr &pkt) override; /** @@ -122,121 +122,121 @@ protected: */ virtual void onRtcpPacket(int iTrackidx, SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen); private: - //处理options方法,获取服务器能力 + //处理options方法,获取服务器能力 void handleReq_Options(const Parser &parser); - //处理describe方法,请求服务器rtsp sdp信息 + //处理describe方法,请求服务器rtsp sdp信息 void handleReq_Describe(const Parser &parser); - //处理ANNOUNCE方法,请求推流,附带sdp + //处理ANNOUNCE方法,请求推流,附带sdp void handleReq_ANNOUNCE(const Parser &parser); - //处理record方法,开始推流 + //处理record方法,开始推流 void handleReq_RECORD(const Parser &parser); - //处理setup方法,播放和推流协商rtp传输方式用 + //处理setup方法,播放和推流协商rtp传输方式用 void handleReq_Setup(const Parser &parser); - //处理play方法,开始或恢复播放 + //处理play方法,开始或恢复播放 void handleReq_Play(const Parser &parser); - //处理pause方法,暂停播放 + //处理pause方法,暂停播放 void handleReq_Pause(const Parser &parser); - //处理teardown方法,结束播放 + //处理teardown方法,结束播放 void handleReq_Teardown(const Parser &parser); - //处理Get方法,rtp over http才用到 + //处理Get方法,rtp over http才用到 void handleReq_Get(const Parser &parser); - //处理Post方法,rtp over http才用到 + //处理Post方法,rtp over http才用到 void handleReq_Post(const Parser &parser); - //处理SET_PARAMETER、GET_PARAMETER方法,一般用于心跳 + //处理SET_PARAMETER、GET_PARAMETER方法,一般用于心跳 void handleReq_SET_PARAMETER(const Parser &parser); - //rtsp资源未找到 - void inline send_StreamNotFound(); - //不支持的传输模式 - void inline send_UnsupportedTransport(); - //会话id错误 - void inline send_SessionNotFound(); - //一般rtsp服务器打开端口失败时触发 - void inline send_NotAcceptable(); - //ssrc转字符串 - inline string printSSRC(uint32_t ui32Ssrc); + //rtsp资源未找到 + void inline send_StreamNotFound(); + //不支持的传输模式 + void inline send_UnsupportedTransport(); + //会话id错误 + void inline send_SessionNotFound(); + //一般rtsp服务器打开端口失败时触发 + void inline send_NotAcceptable(); + //ssrc转字符串 + inline string printSSRC(uint32_t ui32Ssrc); - //获取track下标 - inline int getTrackIndexByTrackType(TrackType type); + //获取track下标 + inline int getTrackIndexByTrackType(TrackType type); inline int getTrackIndexByControlSuffix(const string &controlSuffix); - inline int getTrackIndexByInterleaved(int interleaved); + inline int getTrackIndexByInterleaved(int interleaved); - //一般用于接收udp打洞包,也用于rtsp推流 - inline void onRcvPeerUdpData(int intervaled, const Buffer::Ptr &pBuf, const struct sockaddr &addr); - //配合onRcvPeerUdpData使用 - inline void startListenPeerUdpData(int iTrackIdx); + //一般用于接收udp打洞包,也用于rtsp推流 + inline void onRcvPeerUdpData(int intervaled, const Buffer::Ptr &pBuf, const struct sockaddr &addr); + //配合onRcvPeerUdpData使用 + inline void startListenPeerUdpData(int iTrackIdx); ////rtsp专有认证相关//// - //认证成功 + //认证成功 void onAuthSuccess(); - //认证失败 + //认证失败 void onAuthFailed(const string &realm,const string &why,bool close = true); - //开始走rtsp专有认证流程 + //开始走rtsp专有认证流程 void onAuthUser(const string &realm,const string &authorization); - //校验base64方式的认证加密 + //校验base64方式的认证加密 void onAuthBasic(const string &realm,const string &strBase64); - //校验md5方式的认证加密 + //校验md5方式的认证加密 void onAuthDigest(const string &realm,const string &strMd5); - //发送rtp给客户端 + //发送rtp给客户端 void sendRtpPacket(const RtpPacket::Ptr &pkt); - //回复客户端 - bool sendRtspResponse(const string &res_code,const std::initializer_list &header, const string &sdp = "" , const char *protocol = "RTSP/1.0"); - bool sendRtspResponse(const string &res_code,const StrCaseMap &header = StrCaseMap(), const string &sdp = "",const char *protocol = "RTSP/1.0"); - //服务器发送rtcp - void sendSenderReport(bool overTcp,int iTrackIndex); - //设置socket标志 - void setSocketFlags(); + //回复客户端 + bool sendRtspResponse(const string &res_code,const std::initializer_list &header, const string &sdp = "" , const char *protocol = "RTSP/1.0"); + bool sendRtspResponse(const string &res_code,const StrCaseMap &header = StrCaseMap(), const string &sdp = "",const char *protocol = "RTSP/1.0"); + //服务器发送rtcp + void sendSenderReport(bool overTcp,int iTrackIndex); + //设置socket标志 + void setSocketFlags(); private: - //用于判断客户端是否超时 - Ticker _ticker; - //收到的seq,回复时一致 - int _iCseq = 0; - //ContentBase - string _strContentBase; - //Session号 - string _strSession; - //是否第一次播放,第一次播放需要鉴权,第二次播放属于暂停恢复 - bool _bFirstPlay = true; - //url解析后保存的相关信息 + //用于判断客户端是否超时 + Ticker _ticker; + //收到的seq,回复时一致 + int _iCseq = 0; + //ContentBase + string _strContentBase; + //Session号 + string _strSession; + //是否第一次播放,第一次播放需要鉴权,第二次播放属于暂停恢复 + bool _bFirstPlay = true; + //url解析后保存的相关信息 MediaInfo _mediaInfo; - //rtsp播放器绑定的直播源 - std::weak_ptr _pMediaSrc; - //直播源读取器 - RingBuffer::RingReader::Ptr _pRtpReader; - //推流或拉流客户端采用的rtp传输方式 - Rtsp::eRtpType _rtpType = Rtsp::RTP_Invalid; - //sdp里面有效的track,包含音频或视频 - vector _aTrackInfo; - ////////RTP over udp//////// - //RTP端口,trackid idx 为数组下标 - Socket::Ptr _apRtpSock[2]; - //RTCP端口,trackid idx 为数组下标 - Socket::Ptr _apRtcpSock[2]; - //标记是否收到播放的udp打洞包,收到播放的udp打洞包后才能知道其外网udp端口号 + //rtsp播放器绑定的直播源 + std::weak_ptr _pMediaSrc; + //直播源读取器 + RingBuffer::RingReader::Ptr _pRtpReader; + //推流或拉流客户端采用的rtp传输方式 + Rtsp::eRtpType _rtpType = Rtsp::RTP_Invalid; + //sdp里面有效的track,包含音频或视频 + vector _aTrackInfo; + ////////RTP over udp//////// + //RTP端口,trackid idx 为数组下标 + Socket::Ptr _apRtpSock[2]; + //RTCP端口,trackid idx 为数组下标 + Socket::Ptr _apRtcpSock[2]; + //标记是否收到播放的udp打洞包,收到播放的udp打洞包后才能知道其外网udp端口号 unordered_set _udpSockConnected; - ////////RTP over udp_multicast//////// - //共享的rtp组播对象 - RtpMultiCaster::Ptr _multicaster; + ////////RTP over udp_multicast//////// + //共享的rtp组播对象 + RtpMultiCaster::Ptr _multicaster; - //登录认证 + //登录认证 string _strNonce; //消耗的总流量 uint64_t _ui64TotalBytes = 0; - //RTSP over HTTP - //quicktime 请求rtsp会产生两次tcp连接, - //一次发送 get 一次发送post,需要通过x-sessioncookie关联起来 - string _http_x_sessioncookie; - function _onRecv; - //是否开始发送rtp + //RTSP over HTTP + //quicktime 请求rtsp会产生两次tcp连接, + //一次发送 get 一次发送post,需要通过x-sessioncookie关联起来 + string _http_x_sessioncookie; + function _onRecv; + //是否开始发送rtp bool _enableSendRtp; //rtsp推流相关 - RtspMediaSourceImp::Ptr _pushSrc; - //rtcp统计,trackid idx 为数组下标 - RtcpCounter _aRtcpCnt[2]; - //rtcp发送时间,trackid idx 为数组下标 - Ticker _aRtcpTicker[2]; + RtspMediaSourceImp::Ptr _pushSrc; + //rtcp统计,trackid idx 为数组下标 + RtcpCounter _aRtcpCnt[2]; + //rtcp发送时间,trackid idx 为数组下标 + Ticker _aRtcpTicker[2]; //时间戳修整器 Stamp _stamp[2]; }; diff --git a/src/Rtsp/UDPServer.cpp b/src/Rtsp/UDPServer.cpp index 210d04b0..c4e3a002 100644 --- a/src/Rtsp/UDPServer.cpp +++ b/src/Rtsp/UDPServer.cpp @@ -38,76 +38,76 @@ UDPServer::UDPServer() { } UDPServer::~UDPServer() { - InfoL; + InfoL; } Socket::Ptr UDPServer::getSock(const EventPoller::Ptr &poller,const char* strLocalIp, int intervaled,uint16_t iLocalPort) { - lock_guard lck(_mtxUpdSock); - string strKey = StrPrinter << strLocalIp << ":" << intervaled << endl; - auto it = _mapUpdSock.find(strKey); - if (it == _mapUpdSock.end()) { - Socket::Ptr pSock(new Socket(poller)); - //InfoL<bindUdpSock(iLocalPort, strLocalIp)) { - //分配失败 - return nullptr; - } + lock_guard lck(_mtxUpdSock); + string strKey = StrPrinter << strLocalIp << ":" << intervaled << endl; + auto it = _mapUpdSock.find(strKey); + if (it == _mapUpdSock.end()) { + Socket::Ptr pSock(new Socket(poller)); + //InfoL<bindUdpSock(iLocalPort, strLocalIp)) { + //分配失败 + return nullptr; + } - pSock->setOnRead(bind(&UDPServer::onRcvData, this, intervaled, placeholders::_1,placeholders::_2)); - pSock->setOnErr(bind(&UDPServer::onErr, this, strKey, placeholders::_1)); - _mapUpdSock[strKey] = pSock; - DebugL << strLocalIp << " " << pSock->get_local_port() << " " << intervaled; - return pSock; - } - return it->second; + pSock->setOnRead(bind(&UDPServer::onRcvData, this, intervaled, placeholders::_1,placeholders::_2)); + pSock->setOnErr(bind(&UDPServer::onErr, this, strKey, placeholders::_1)); + _mapUpdSock[strKey] = pSock; + DebugL << strLocalIp << " " << pSock->get_local_port() << " " << intervaled; + return pSock; + } + return it->second; } void UDPServer::listenPeer(const char* strPeerIp, void* pSelf, const onRecvData& cb) { - lock_guard lck(_mtxDataHandler); - auto &mapRef = _mapDataHandler[strPeerIp]; - mapRef.emplace(pSelf, cb); + lock_guard lck(_mtxDataHandler); + auto &mapRef = _mapDataHandler[strPeerIp]; + mapRef.emplace(pSelf, cb); } void UDPServer::stopListenPeer(const char* strPeerIp, void* pSelf) { - lock_guard lck(_mtxDataHandler); - auto it0 = _mapDataHandler.find(strPeerIp); - if (it0 == _mapDataHandler.end()) { - return; - } - auto &mapRef = it0->second; - auto it1 = mapRef.find(pSelf); - if (it1 != mapRef.end()) { - mapRef.erase(it1); - } - if (mapRef.size() == 0) { - _mapDataHandler.erase(it0); - } + lock_guard lck(_mtxDataHandler); + auto it0 = _mapDataHandler.find(strPeerIp); + if (it0 == _mapDataHandler.end()) { + return; + } + auto &mapRef = it0->second; + auto it1 = mapRef.find(pSelf); + if (it1 != mapRef.end()) { + mapRef.erase(it1); + } + if (mapRef.size() == 0) { + _mapDataHandler.erase(it0); + } } void UDPServer::onErr(const string& strKey, const SockException& err) { - WarnL << err.what(); - lock_guard lck(_mtxUpdSock); - _mapUpdSock.erase(strKey); + WarnL << err.what(); + lock_guard lck(_mtxUpdSock); + _mapUpdSock.erase(strKey); } void UDPServer::onRcvData(int intervaled, const Buffer::Ptr &pBuf, struct sockaddr* pPeerAddr) { - //TraceL << trackIndex; - struct sockaddr_in *in = (struct sockaddr_in *) pPeerAddr; - string peerIp = inet_ntoa(in->sin_addr); - lock_guard lck(_mtxDataHandler); - auto it0 = _mapDataHandler.find(peerIp); - if (it0 == _mapDataHandler.end()) { - return; - } - auto &mapRef = it0->second; - for (auto it1 = mapRef.begin(); it1 != mapRef.end(); ++it1) { - onRecvData &funRef = it1->second; - if (!funRef(intervaled, pBuf, pPeerAddr)) { - it1 = mapRef.erase(it1); - } - } - if (mapRef.size() == 0) { - _mapDataHandler.erase(it0); - } + //TraceL << trackIndex; + struct sockaddr_in *in = (struct sockaddr_in *) pPeerAddr; + string peerIp = inet_ntoa(in->sin_addr); + lock_guard lck(_mtxDataHandler); + auto it0 = _mapDataHandler.find(peerIp); + if (it0 == _mapDataHandler.end()) { + return; + } + auto &mapRef = it0->second; + for (auto it1 = mapRef.begin(); it1 != mapRef.end(); ++it1) { + onRecvData &funRef = it1->second; + if (!funRef(intervaled, pBuf, pPeerAddr)) { + it1 = mapRef.erase(it1); + } + } + if (mapRef.size() == 0) { + _mapDataHandler.erase(it0); + } } } /* namespace mediakit */ diff --git a/src/Rtsp/UDPServer.h b/src/Rtsp/UDPServer.h index 497986a8..cab66603 100644 --- a/src/Rtsp/UDPServer.h +++ b/src/Rtsp/UDPServer.h @@ -43,21 +43,21 @@ namespace mediakit { class UDPServer : public std::enable_shared_from_this { public: - typedef function< bool(int intervaled, const Buffer::Ptr &buffer, struct sockaddr *peer_addr)> onRecvData; - ~UDPServer(); - static UDPServer &Instance(); - Socket::Ptr getSock(const EventPoller::Ptr &poller,const char *strLocalIp, int intervaled,uint16_t iLocalPort = 0); - void listenPeer(const char *strPeerIp, void *pSelf, const onRecvData &cb); - void stopListenPeer(const char *strPeerIp, void *pSelf); + typedef function< bool(int intervaled, const Buffer::Ptr &buffer, struct sockaddr *peer_addr)> onRecvData; + ~UDPServer(); + static UDPServer &Instance(); + Socket::Ptr getSock(const EventPoller::Ptr &poller,const char *strLocalIp, int intervaled,uint16_t iLocalPort = 0); + void listenPeer(const char *strPeerIp, void *pSelf, const onRecvData &cb); + void stopListenPeer(const char *strPeerIp, void *pSelf); private: - UDPServer(); - void onRcvData(int intervaled, const Buffer::Ptr &pBuf,struct sockaddr *pPeerAddr); - void onErr(const string &strKey,const SockException &err); - unordered_map _mapUpdSock; - mutex _mtxUpdSock; + UDPServer(); + void onRcvData(int intervaled, const Buffer::Ptr &pBuf,struct sockaddr *pPeerAddr); + void onErr(const string &strKey,const SockException &err); + unordered_map _mapUpdSock; + mutex _mtxUpdSock; - unordered_map > _mapDataHandler; - mutex _mtxDataHandler; + unordered_map > _mapDataHandler; + mutex _mtxDataHandler; }; } /* namespace mediakit */ diff --git a/src/Shell/ShellSession.cpp b/src/Shell/ShellSession.cpp index 7822245c..f981e490 100644 --- a/src/Shell/ShellSession.cpp +++ b/src/Shell/ShellSession.cpp @@ -48,29 +48,29 @@ ShellSession::~ShellSession() { } void ShellSession::onRecv(const Buffer::Ptr&buf) { - //DebugL << hexdump(buf->data(), buf->size()); + //DebugL << hexdump(buf->data(), buf->size()); GET_CONFIG(uint32_t,maxReqSize,Shell::kMaxReqSize); if (_strRecvBuf.size() + buf->size() >= maxReqSize) { - shutdown(SockException(Err_other,"recv buffer overflow")); - return; - } - _beatTicker.resetTime(); - _strRecvBuf.append(buf->data(), buf->size()); - if (_strRecvBuf.find("\xff\xf4\xff\0xfd\x06") != std::string::npos) { - send("\033[0m\r\n Bye bye!\r\n"); - shutdown(SockException(Err_other,"received Ctrl+C")); - return; - } - size_t index; - string line; - while ((index = _strRecvBuf.find("\r\n")) != std::string::npos) { - line = _strRecvBuf.substr(0, index); - _strRecvBuf.erase(0, index + 2); - if (!onCommandLine(line)) { - shutdown(SockException(Err_other,"exit cmd")); - return; - } - } + shutdown(SockException(Err_other,"recv buffer overflow")); + return; + } + _beatTicker.resetTime(); + _strRecvBuf.append(buf->data(), buf->size()); + if (_strRecvBuf.find("\xff\xf4\xff\0xfd\x06") != std::string::npos) { + send("\033[0m\r\n Bye bye!\r\n"); + shutdown(SockException(Err_other,"received Ctrl+C")); + return; + } + size_t index; + string line; + while ((index = _strRecvBuf.find("\r\n")) != std::string::npos) { + line = _strRecvBuf.substr(0, index); + _strRecvBuf.erase(0, index + 2); + if (!onCommandLine(line)) { + shutdown(SockException(Err_other,"exit cmd")); + return; + } + } } void ShellSession::onError(const SockException &err){ @@ -78,19 +78,19 @@ void ShellSession::onError(const SockException &err){ } void ShellSession::onManager() { - if (_beatTicker.elapsedTime() > 1000 * 60 * 5) { - //5 miniutes for alive + if (_beatTicker.elapsedTime() > 1000 * 60 * 5) { + //5 miniutes for alive shutdown(SockException(Err_timeout,"session timeout")); - return; - } + return; + } } inline bool ShellSession::onCommandLine(const string& line) { auto loginInterceptor = _loginInterceptor; if (loginInterceptor) { - bool ret = loginInterceptor(line); - return ret; - } + bool ret = loginInterceptor(line); + return ret; + } try { std::shared_ptr ss(new stringstream); CMDRegister::Instance()(line,ss); @@ -102,21 +102,21 @@ inline bool ShellSession::onCommandLine(const string& line) { send("\r\n"); } printShellPrefix(); - return true; + return true; } inline void ShellSession::pleaseInputUser() { - send("\033[0m"); - send(StrPrinter << SERVER_NAME << " login: " << endl); - _loginInterceptor = [this](const string &user_name) { - _strUserName=user_name; + send("\033[0m"); + send(StrPrinter << SERVER_NAME << " login: " << endl); + _loginInterceptor = [this](const string &user_name) { + _strUserName=user_name; pleaseInputPasswd(); - return true; - }; + return true; + }; } inline void ShellSession::pleaseInputPasswd() { - send("Password: \033[8m"); - _loginInterceptor = [this](const string &passwd) { + send("Password: \033[8m"); + _loginInterceptor = [this](const string &passwd) { auto onAuth = [this](const string &errMessage){ if(!errMessage.empty()){ //鉴权失败 @@ -157,12 +157,12 @@ inline void ShellSession::pleaseInputPasswd() { //如果无人监听shell登录事件,那么默认shell无法登录 onAuth("please listen kBroadcastShellLogin event"); } - return true; - }; + return true; + }; } inline void ShellSession::printShellPrefix() { - send(StrPrinter << _strUserName << "@" << SERVER_NAME << "# " << endl); + send(StrPrinter << _strUserName << "@" << SERVER_NAME << "# " << endl); } }/* namespace mediakit */ diff --git a/src/Shell/ShellSession.h b/src/Shell/ShellSession.h index 4c3732ca..112506c9 100644 --- a/src/Shell/ShellSession.h +++ b/src/Shell/ShellSession.h @@ -37,23 +37,23 @@ namespace mediakit { class ShellSession: public TcpSession { public: - ShellSession(const Socket::Ptr &_sock); - virtual ~ShellSession(); + ShellSession(const Socket::Ptr &_sock); + virtual ~ShellSession(); - void onRecv(const Buffer::Ptr &) override; + void onRecv(const Buffer::Ptr &) override; void onError(const SockException &err) override; - void onManager() override; + void onManager() override; private: - inline bool onCommandLine(const string &); - inline void pleaseInputUser(); - inline void pleaseInputPasswd(); - inline void printShellPrefix(); + inline bool onCommandLine(const string &); + inline void pleaseInputUser(); + inline void pleaseInputPasswd(); + inline void printShellPrefix(); - function _loginInterceptor; - string _strRecvBuf; - Ticker _beatTicker; - string _strUserName; + function _loginInterceptor; + string _strRecvBuf; + Ticker _beatTicker; + string _strUserName; }; } /* namespace mediakit */ diff --git a/tests/DeviceHK/DeviceHK.cpp b/tests/DeviceHK/DeviceHK.cpp index f1d57d8c..01197429 100644 --- a/tests/DeviceHK/DeviceHK.cpp +++ b/tests/DeviceHK/DeviceHK.cpp @@ -32,232 +32,232 @@ namespace mediakit { #define HK_APP_NAME "live" DeviceHK::DeviceHK() { - InfoL << endl; - static onceToken token( []() { - NET_DVR_Init(); - NET_DVR_SetDVRMessageCallBack_V31([](LONG lCommand,NET_DVR_ALARMER *pAlarmer,char *pAlarmInfo,DWORD dwBufLen,void* pUser){ - WarnL< hkLoginCB; - loginInfo.bUseAsynLogin = TRUE; - weak_ptr weakSelf = shared_from_this(); - loginInfo.pUser = new hkLoginCB([weakSelf,cb](LONG lUserID, DWORD dwResult, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo ) { - //TraceL<sSerialNumber; - connectResult result; - if(dwResult==TRUE) { - result.strDevName=(char *)(lpDeviceInfo->sSerialNumber); - result.ui16ChnStart=lpDeviceInfo->byStartChan; - result.ui16ChnCount=lpDeviceInfo->byChanNum; - auto _strongSelf=weakSelf.lock(); - if(_strongSelf) { - auto strongSelf=dynamic_pointer_cast(_strongSelf); - strongSelf->onConnected(lUserID,lpDeviceInfo); - } - } else { - WarnL<<"connect deviceHK failed:"<(pUser); - (*fun)(lUserID,dwResult,lpDeviceInfo); - delete fun; - }; - NET_DVR_SetConnectTime(iTimeOut * 1000, 3); - NET_DVR_Login_V40(&loginInfo, &loginResult); + //callback info + typedef function< void(LONG lUserID, DWORD dwResult, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo)> hkLoginCB; + loginInfo.bUseAsynLogin = TRUE; + weak_ptr weakSelf = shared_from_this(); + loginInfo.pUser = new hkLoginCB([weakSelf,cb](LONG lUserID, DWORD dwResult, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo ) { + //TraceL<sSerialNumber; + connectResult result; + if(dwResult==TRUE) { + result.strDevName=(char *)(lpDeviceInfo->sSerialNumber); + result.ui16ChnStart=lpDeviceInfo->byStartChan; + result.ui16ChnCount=lpDeviceInfo->byChanNum; + auto _strongSelf=weakSelf.lock(); + if(_strongSelf) { + auto strongSelf=dynamic_pointer_cast(_strongSelf); + strongSelf->onConnected(lUserID,lpDeviceInfo); + } + } else { + WarnL<<"connect deviceHK failed:"<(pUser); + (*fun)(lUserID,dwResult,lpDeviceInfo); + delete fun; + }; + NET_DVR_SetConnectTime(iTimeOut * 1000, 3); + NET_DVR_Login_V40(&loginInfo, &loginResult); } void DeviceHK::disconnect(const relustCB& cb) { - m_mapChannels.clear(); - if (m_i64LoginId >= 0) { - NET_DVR_Logout(m_i64LoginId); - m_i64LoginId = -1; - Device::onDisconnected(true); - } + m_mapChannels.clear(); + if (m_i64LoginId >= 0) { + NET_DVR_Logout(m_i64LoginId); + m_i64LoginId = -1; + Device::onDisconnected(true); + } } void DeviceHK::addChannel(int iChn, bool bMainStream) { - DevChannel::Ptr channel( new DevChannelHK(m_i64LoginId, (char *) m_deviceInfo.sSerialNumber, iChn, bMainStream)); - m_mapChannels[iChn] = channel; + DevChannel::Ptr channel( new DevChannelHK(m_i64LoginId, (char *) m_deviceInfo.sSerialNumber, iChn, bMainStream)); + m_mapChannels[iChn] = channel; } void DeviceHK::delChannel(int chn) { - m_mapChannels.erase(chn); + m_mapChannels.erase(chn); } void DeviceHK::onConnected(LONG lUserID, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo) { - m_i64LoginId = lUserID; - m_deviceInfo = *lpDeviceInfo; - Device::onConnected(); + m_i64LoginId = lUserID; + m_deviceInfo = *lpDeviceInfo; + Device::onConnected(); } void DeviceHK::addAllChannel(bool bMainStream) { - InfoL << endl; - for (int i = 0; i < m_deviceInfo.byChanNum; i++) { - addChannel(m_deviceInfo.byStartChan + i, bMainStream); - } + InfoL << endl; + for (int i = 0; i < m_deviceInfo.byChanNum; i++) { + addChannel(m_deviceInfo.byStartChan + i, bMainStream); + } } DevChannelHK::DevChannelHK(int64_t i64LoginId, const char* pcDevName, int iChn, bool bMainStream) : - DevChannel(HK_APP_NAME,(StrPrinter<(pUser); - if(self->m_i64PreviewHandle!=(int64_t)lPlayHandle) { - return; - } - self->onPreview(dwDataType,pBuffer,dwBufSize); - }, this); - if (m_i64PreviewHandle == -1) { - throw std::runtime_error( StrPrinter << "设备[" << pcDevName << "/" << iChn << "]开始实时预览失败:" - << NET_DVR_GetLastError() << endl); - } + DevChannel(HK_APP_NAME,(StrPrinter<(pUser); + if(self->m_i64PreviewHandle!=(int64_t)lPlayHandle) { + return; + } + self->onPreview(dwDataType,pBuffer,dwBufSize); + }, this); + if (m_i64PreviewHandle == -1) { + throw std::runtime_error( StrPrinter << "设备[" << pcDevName << "/" << iChn << "]开始实时预览失败:" + << NET_DVR_GetLastError() << endl); + } } DevChannelHK::~DevChannelHK() { - InfoL << endl; - if (m_i64PreviewHandle >= 0) { - NET_DVR_StopRealPlay(m_i64PreviewHandle); - m_i64PreviewHandle = -1; - } - if (m_iPlayHandle >= 0) { - PlayM4_StopSoundShare(m_iPlayHandle); - PlayM4_Stop(m_iPlayHandle); - m_iPlayHandle = -1; - } + InfoL << endl; + if (m_i64PreviewHandle >= 0) { + NET_DVR_StopRealPlay(m_i64PreviewHandle); + m_i64PreviewHandle = -1; + } + if (m_iPlayHandle >= 0) { + PlayM4_StopSoundShare(m_iPlayHandle); + PlayM4_Stop(m_iPlayHandle); + m_iPlayHandle = -1; + } } void DevChannelHK::onPreview(DWORD dwDataType, BYTE* pBuffer, DWORD dwBufSize) { - //TimeTicker1(-1); - switch (dwDataType) { - case NET_DVR_SYSHEAD: { //系统头数据 - if (!PlayM4_GetPort(&m_iPlayHandle)) { //获取播放库未使用的通道号 - WarnL << "PlayM4_GetPort:" << NET_DVR_GetLastError(); - break; - } - if (dwBufSize > 0) { - if (!PlayM4_SetStreamOpenMode(m_iPlayHandle, STREAME_REALTIME)) { //设置实时流播放模式 - WarnL << "PlayM4_SetStreamOpenMode:" << NET_DVR_GetLastError(); - break; - } - if (!PlayM4_OpenStream(m_iPlayHandle, pBuffer, dwBufSize, - 1024 * 1024)) { //打开流接口 - WarnL << "PlayM4_OpenStream:" << NET_DVR_GetLastError(); - break; - } + //TimeTicker1(-1); + switch (dwDataType) { + case NET_DVR_SYSHEAD: { //系统头数据 + if (!PlayM4_GetPort(&m_iPlayHandle)) { //获取播放库未使用的通道号 + WarnL << "PlayM4_GetPort:" << NET_DVR_GetLastError(); + break; + } + if (dwBufSize > 0) { + if (!PlayM4_SetStreamOpenMode(m_iPlayHandle, STREAME_REALTIME)) { //设置实时流播放模式 + WarnL << "PlayM4_SetStreamOpenMode:" << NET_DVR_GetLastError(); + break; + } + if (!PlayM4_OpenStream(m_iPlayHandle, pBuffer, dwBufSize, + 1024 * 1024)) { //打开流接口 + WarnL << "PlayM4_OpenStream:" << NET_DVR_GetLastError(); + break; + } - PlayM4_SetDecCallBackMend(m_iPlayHandle, - [](int nPort,char * pBuf,int nSize,FRAME_INFO * pFrameInfo, void* nUser,int nReserved2) { - DevChannelHK *chn=reinterpret_cast(nUser); - if(chn->m_iPlayHandle!=nPort) { - return; - } - chn->onGetDecData(pBuf,nSize,pFrameInfo); - }, this); - if (!PlayM4_Play(m_iPlayHandle, 0)) { //播放开始 - WarnL << "PlayM4_Play:" << NET_DVR_GetLastError(); - break; - } - InfoL << "设置解码器成功!" << endl; - //打开音频解码, 需要码流是复合流 - if (!PlayM4_PlaySoundShare(m_iPlayHandle)) { - WarnL << "PlayM4_PlaySound:" << NET_DVR_GetLastError(); - break; - } - } - } - break; - case NET_DVR_STREAMDATA: { //流数据(包括复合流或音视频分开的视频流数据) - if (dwBufSize > 0 && m_iPlayHandle != -1) { - if (!PlayM4_InputData(m_iPlayHandle, pBuffer, dwBufSize)) { - WarnL << "PlayM4_InputData:" << NET_DVR_GetLastError(); - break; - } - } - } - break; - case NET_DVR_AUDIOSTREAMDATA: { //音频数据 - } - break; - case NET_DVR_PRIVATE_DATA: { //私有数据,包括智能信息 - } - break; - default: - break; - } + PlayM4_SetDecCallBackMend(m_iPlayHandle, + [](int nPort,char * pBuf,int nSize,FRAME_INFO * pFrameInfo, void* nUser,int nReserved2) { + DevChannelHK *chn=reinterpret_cast(nUser); + if(chn->m_iPlayHandle!=nPort) { + return; + } + chn->onGetDecData(pBuf,nSize,pFrameInfo); + }, this); + if (!PlayM4_Play(m_iPlayHandle, 0)) { //播放开始 + WarnL << "PlayM4_Play:" << NET_DVR_GetLastError(); + break; + } + InfoL << "设置解码器成功!" << endl; + //打开音频解码, 需要码流是复合流 + if (!PlayM4_PlaySoundShare(m_iPlayHandle)) { + WarnL << "PlayM4_PlaySound:" << NET_DVR_GetLastError(); + break; + } + } + } + break; + case NET_DVR_STREAMDATA: { //流数据(包括复合流或音视频分开的视频流数据) + if (dwBufSize > 0 && m_iPlayHandle != -1) { + if (!PlayM4_InputData(m_iPlayHandle, pBuffer, dwBufSize)) { + WarnL << "PlayM4_InputData:" << NET_DVR_GetLastError(); + break; + } + } + } + break; + case NET_DVR_AUDIOSTREAMDATA: { //音频数据 + } + break; + case NET_DVR_PRIVATE_DATA: { //私有数据,包括智能信息 + } + break; + default: + break; + } } void DevChannelHK::onGetDecData(char* pBuf, int nSize, FRAME_INFO* pFrameInfo) { - //InfoL << pFrameInfo->nType; - switch (pFrameInfo->nType) { - case T_YV12: { - if (!m_bVideoSeted) { - m_bVideoSeted = true; - VideoInfo video; - video.iWidth = pFrameInfo->nWidth; - video.iHeight = pFrameInfo->nHeight; - video.iFrameRate = pFrameInfo->nFrameRate; - initVideo(video); - } - char *yuv[3]; - int yuv_len[3]; - yuv_len[0] = pFrameInfo->nWidth; - yuv_len[1] = pFrameInfo->nWidth / 2; - yuv_len[2] = pFrameInfo->nWidth / 2; - int dwOffset_Y = pFrameInfo->nWidth * pFrameInfo->nHeight; - yuv[0] = pBuf; - yuv[2] = yuv[0] + dwOffset_Y; - yuv[1] = yuv[2] + dwOffset_Y / 4; - inputYUV(yuv, yuv_len, pFrameInfo->nStamp); - } - break; - case T_AUDIO16: { - if (!m_bAudioSeted) { - m_bAudioSeted = true; - AudioInfo audio; - audio.iChannel = pFrameInfo->nWidth; - audio.iSampleBit = pFrameInfo->nHeight; - audio.iSampleRate = pFrameInfo->nFrameRate; - initAudio(audio); - } - inputPCM(pBuf, nSize, pFrameInfo->nStamp); - } - break; - default: - break; - } + //InfoL << pFrameInfo->nType; + switch (pFrameInfo->nType) { + case T_YV12: { + if (!m_bVideoSeted) { + m_bVideoSeted = true; + VideoInfo video; + video.iWidth = pFrameInfo->nWidth; + video.iHeight = pFrameInfo->nHeight; + video.iFrameRate = pFrameInfo->nFrameRate; + initVideo(video); + } + char *yuv[3]; + int yuv_len[3]; + yuv_len[0] = pFrameInfo->nWidth; + yuv_len[1] = pFrameInfo->nWidth / 2; + yuv_len[2] = pFrameInfo->nWidth / 2; + int dwOffset_Y = pFrameInfo->nWidth * pFrameInfo->nHeight; + yuv[0] = pBuf; + yuv[2] = yuv[0] + dwOffset_Y; + yuv[1] = yuv[2] + dwOffset_Y / 4; + inputYUV(yuv, yuv_len, pFrameInfo->nStamp); + } + break; + case T_AUDIO16: { + if (!m_bAudioSeted) { + m_bAudioSeted = true; + AudioInfo audio; + audio.iChannel = pFrameInfo->nWidth; + audio.iSampleBit = pFrameInfo->nHeight; + audio.iSampleRate = pFrameInfo->nFrameRate; + initAudio(audio); + } + inputPCM(pBuf, nSize, pFrameInfo->nStamp); + } + break; + default: + break; + } } } /* namespace mediakit */ diff --git a/tests/DeviceHK/DeviceHK.h b/tests/DeviceHK/DeviceHK.h index 69e716b3..05012f29 100644 --- a/tests/DeviceHK/DeviceHK.h +++ b/tests/DeviceHK/DeviceHK.h @@ -41,26 +41,26 @@ namespace mediakit { class connectInfo { public: - connectInfo(const char *_strDevIp, - uint16_t _ui16DevPort, - const char *_strUserName, - const char *_strPwd) { - strDevIp = _strDevIp; - ui16DevPort = _ui16DevPort; - strUserName = _strUserName; - strPwd = _strPwd; - } - string strDevIp; - uint16_t ui16DevPort; - string strUserName; - string strPwd; + connectInfo(const char *_strDevIp, + uint16_t _ui16DevPort, + const char *_strUserName, + const char *_strPwd) { + strDevIp = _strDevIp; + ui16DevPort = _ui16DevPort; + strUserName = _strUserName; + strPwd = _strPwd; + } + string strDevIp; + uint16_t ui16DevPort; + string strUserName; + string strPwd; }; class connectResult { public: - string strDevName; - uint16_t ui16ChnStart; - uint16_t ui16ChnCount; + string strDevName; + uint16_t ui16ChnStart; + uint16_t ui16ChnCount; }; typedef function connectCB; @@ -68,28 +68,28 @@ typedef function relustCB; class Device: public enable_shared_from_this { public: - typedef std::shared_ptr Ptr; - Device() { - } - virtual ~Device(){ disconnect([](bool bSuccess){ - });}; + typedef std::shared_ptr Ptr; + Device() { + } + virtual ~Device(){ disconnect([](bool bSuccess){ + });}; - virtual void connectDevice(const connectInfo &info, const connectCB &cb, int iTimeOut = 3)=0; + virtual void connectDevice(const connectInfo &info, const connectCB &cb, int iTimeOut = 3)=0; - virtual void disconnect(const relustCB &cb) { - } + virtual void disconnect(const relustCB &cb) { + } - virtual void addChannel(int iChnIndex, bool bMainStream = true)=0; + virtual void addChannel(int iChnIndex, bool bMainStream = true)=0; - virtual void delChannel(int iChnIndex)=0; + virtual void delChannel(int iChnIndex)=0; - virtual void addAllChannel(bool bMainStream = true)=0; + virtual void addAllChannel(bool bMainStream = true)=0; protected: - void onConnected() { - } - void onDisconnected(bool bSelfDisconnect) { - } + void onConnected() { + } + void onDisconnected(bool bSelfDisconnect) { + } }; @@ -97,36 +97,36 @@ protected: class DevChannelHK; class DeviceHK: public Device { public: - typedef std::shared_ptr Ptr; - DeviceHK(); - virtual ~DeviceHK(); + typedef std::shared_ptr Ptr; + DeviceHK(); + virtual ~DeviceHK(); - void connectDevice(const connectInfo &info, const connectCB &cb, int iTimeOut = 3) override; - void disconnect(const relustCB &cb) override; + void connectDevice(const connectInfo &info, const connectCB &cb, int iTimeOut = 3) override; + void disconnect(const relustCB &cb) override; - void addChannel(int iChnIndex, bool bMainStream = true) override; - void delChannel(int iChnIndex) override; - void addAllChannel(bool bMainStream = true) override; + void addChannel(int iChnIndex, bool bMainStream = true) override; + void delChannel(int iChnIndex) override; + void addAllChannel(bool bMainStream = true) override; private: - map > m_mapChannels; - int64_t m_i64LoginId = -1; - NET_DVR_DEVICEINFO_V30 m_deviceInfo; - void onConnected(LONG lUserID, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo); + map > m_mapChannels; + int64_t m_i64LoginId = -1; + NET_DVR_DEVICEINFO_V30 m_deviceInfo; + void onConnected(LONG lUserID, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo); }; class DevChannelHK: public DevChannel { public: - typedef std::shared_ptr Ptr; - DevChannelHK(int64_t i64LoginId, const char *pcDevName, int iChn, bool bMainStream = true); - virtual ~DevChannelHK(); + typedef std::shared_ptr Ptr; + DevChannelHK(int64_t i64LoginId, const char *pcDevName, int iChn, bool bMainStream = true); + virtual ~DevChannelHK(); protected: - int64_t m_i64LoginId = -1; - int64_t m_i64PreviewHandle = -1; - int m_iPlayHandle = -1; - void onPreview(DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize); - void onGetDecData(char * pBuf, int nSize, FRAME_INFO * pFrameInfo); - bool m_bVideoSeted = false; - bool m_bAudioSeted = false; + int64_t m_i64LoginId = -1; + int64_t m_i64PreviewHandle = -1; + int m_iPlayHandle = -1; + void onPreview(DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize); + void onGetDecData(char * pBuf, int nSize, FRAME_INFO * pFrameInfo); + bool m_bVideoSeted = false; + bool m_bAudioSeted = false; }; } /* namespace mediakit */ diff --git a/tests/H264Decoder.h b/tests/H264Decoder.h index daf3d45f..95c0fe48 100644 --- a/tests/H264Decoder.h +++ b/tests/H264Decoder.h @@ -46,51 +46,51 @@ namespace mediakit { class H264Decoder { public: - H264Decoder(void){ - avcodec_register_all(); - AVCodec *pCodec = avcodec_find_decoder(AV_CODEC_ID_H264); - if (!pCodec) { - throw std::runtime_error("未找到H264解码器"); - } - m_pContext.reset(avcodec_alloc_context3(pCodec), [](AVCodecContext *pCtx) { - avcodec_close(pCtx); - avcodec_free_context(&pCtx); - }); - if (!m_pContext) { - throw std::runtime_error("创建解码器失败"); - } - if (pCodec->capabilities & AV_CODEC_CAP_TRUNCATED) { - /* we do not send complete frames */ - m_pContext->flags |= AV_CODEC_FLAG_TRUNCATED; - } - if(avcodec_open2(m_pContext.get(), pCodec, NULL)< 0){ - throw std::runtime_error("打开编码器失败"); - } - m_pFrame.reset(av_frame_alloc(),[](AVFrame *pFrame){ - av_frame_free(&pFrame); - }); - if (!m_pFrame) { - throw std::runtime_error("创建帧缓存失败"); - } - } - virtual ~H264Decoder(void){} - bool inputVideo(unsigned char* data,unsigned int dataSize,uint32_t ui32Stamp,AVFrame **ppFrame){ - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = data; - pkt.size = dataSize; - pkt.dts = ui32Stamp; - int iGotPicture ; - auto iLen = avcodec_decode_video2(m_pContext.get(), m_pFrame.get(), &iGotPicture, &pkt); - if (!iGotPicture || iLen < 0) { - return false; - } - *ppFrame = m_pFrame.get(); - return true; - } + H264Decoder(void){ + avcodec_register_all(); + AVCodec *pCodec = avcodec_find_decoder(AV_CODEC_ID_H264); + if (!pCodec) { + throw std::runtime_error("未找到H264解码器"); + } + m_pContext.reset(avcodec_alloc_context3(pCodec), [](AVCodecContext *pCtx) { + avcodec_close(pCtx); + avcodec_free_context(&pCtx); + }); + if (!m_pContext) { + throw std::runtime_error("创建解码器失败"); + } + if (pCodec->capabilities & AV_CODEC_CAP_TRUNCATED) { + /* we do not send complete frames */ + m_pContext->flags |= AV_CODEC_FLAG_TRUNCATED; + } + if(avcodec_open2(m_pContext.get(), pCodec, NULL)< 0){ + throw std::runtime_error("打开编码器失败"); + } + m_pFrame.reset(av_frame_alloc(),[](AVFrame *pFrame){ + av_frame_free(&pFrame); + }); + if (!m_pFrame) { + throw std::runtime_error("创建帧缓存失败"); + } + } + virtual ~H264Decoder(void){} + bool inputVideo(unsigned char* data,unsigned int dataSize,uint32_t ui32Stamp,AVFrame **ppFrame){ + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = data; + pkt.size = dataSize; + pkt.dts = ui32Stamp; + int iGotPicture ; + auto iLen = avcodec_decode_video2(m_pContext.get(), m_pFrame.get(), &iGotPicture, &pkt); + if (!iGotPicture || iLen < 0) { + return false; + } + *ppFrame = m_pFrame.get(); + return true; + } private: - std::shared_ptr m_pContext; - std::shared_ptr m_pFrame; + std::shared_ptr m_pContext; + std::shared_ptr m_pFrame; }; diff --git a/tests/YuvDisplayer.h b/tests/YuvDisplayer.h index 1cd77867..db367cee 100644 --- a/tests/YuvDisplayer.h +++ b/tests/YuvDisplayer.h @@ -65,13 +65,13 @@ public: SDL_PushEvent(&event); } - void runLoop(){ - bool flag = true; - std::function task; - SDL_Event event; - while(flag){ - SDL_WaitEvent(&event); - switch (event.type){ + void runLoop(){ + bool flag = true; + std::function task; + SDL_Event event; + while(flag){ + SDL_WaitEvent(&event); + switch (event.type){ case REFRESH_EVENT:{ { lock_guard lck(_mtxTask); @@ -91,17 +91,17 @@ public: default: break; } - } - } + } + } - void shutdown(){ - doTask([](){return false;}); - } + void shutdown(){ + doTask([](){return false;}); + } private: SDLDisplayerHelper(){ }; ~SDLDisplayerHelper(){ - shutdown(); + shutdown(); }; private: std::deque > _taskList; @@ -112,7 +112,7 @@ private: class YuvDisplayer { public: - YuvDisplayer(void *hwnd = nullptr,const char *title = "untitled"){ + YuvDisplayer(void *hwnd = nullptr,const char *title = "untitled"){ static onceToken token([]() { if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) == -1) { @@ -131,39 +131,39 @@ public: SDL_Quit(); }); - _title = title; - _hwnd = hwnd; - } - virtual ~YuvDisplayer(){ - if (_texture) { - SDL_DestroyTexture(_texture); - _texture = nullptr; - } - if (_render) { - SDL_DestroyRenderer(_render); - _render = nullptr; - } - if (_win) { - SDL_DestroyWindow(_win); - _win = nullptr; - } - } - bool displayYUV(AVFrame *pFrame){ - if (!_win) { - if (_hwnd) { - _win = SDL_CreateWindowFrom(_hwnd); - }else { - _win = SDL_CreateWindow(_title.data(), - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - pFrame->width, - pFrame->height, - SDL_WINDOW_OPENGL); - } - } - if (_win && ! _render){ + _title = title; + _hwnd = hwnd; + } + virtual ~YuvDisplayer(){ + if (_texture) { + SDL_DestroyTexture(_texture); + _texture = nullptr; + } + if (_render) { + SDL_DestroyRenderer(_render); + _render = nullptr; + } + if (_win) { + SDL_DestroyWindow(_win); + _win = nullptr; + } + } + bool displayYUV(AVFrame *pFrame){ + if (!_win) { + if (_hwnd) { + _win = SDL_CreateWindowFrom(_hwnd); + }else { + _win = SDL_CreateWindow(_title.data(), + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + pFrame->width, + pFrame->height, + SDL_WINDOW_OPENGL); + } + } + if (_win && ! _render){ #if 0 - SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */ + SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */ SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardware acceleration */ SDL_RENDERER_PRESENTVSYNC = 0x00000004, /**< Present is synchronized @@ -172,34 +172,34 @@ public: rendering to texture */ #endif - _render = SDL_CreateRenderer(_win, -1, SDL_RENDERER_ACCELERATED); - } - if (_render && !_texture) { - _texture = SDL_CreateTexture(_render, SDL_PIXELFORMAT_IYUV, - SDL_TEXTUREACCESS_STREAMING, - pFrame->width, - pFrame->height); - } - if (_texture) { - SDL_UpdateYUVTexture(_texture, nullptr, - pFrame->data[0], pFrame->linesize[0], - pFrame->data[1], pFrame->linesize[1], - pFrame->data[2], pFrame->linesize[2]); + _render = SDL_CreateRenderer(_win, -1, SDL_RENDERER_ACCELERATED); + } + if (_render && !_texture) { + _texture = SDL_CreateTexture(_render, SDL_PIXELFORMAT_IYUV, + SDL_TEXTUREACCESS_STREAMING, + pFrame->width, + pFrame->height); + } + if (_texture) { + SDL_UpdateYUVTexture(_texture, nullptr, + pFrame->data[0], pFrame->linesize[0], + pFrame->data[1], pFrame->linesize[1], + pFrame->data[2], pFrame->linesize[2]); - //SDL_UpdateTexture(_texture, nullptr, pFrame->data[0], pFrame->linesize[0]); - SDL_RenderClear(_render); - SDL_RenderCopy(_render, _texture, nullptr, nullptr); - SDL_RenderPresent(_render); - return true; - } - return false; - } + //SDL_UpdateTexture(_texture, nullptr, pFrame->data[0], pFrame->linesize[0]); + SDL_RenderClear(_render); + SDL_RenderCopy(_render, _texture, nullptr, nullptr); + SDL_RenderPresent(_render); + return true; + } + return false; + } private: - string _title; - SDL_Window *_win = nullptr; - SDL_Renderer *_render = nullptr; - SDL_Texture *_texture = nullptr; - void *_hwnd = nullptr; + string _title; + SDL_Window *_win = nullptr; + SDL_Renderer *_render = nullptr; + SDL_Texture *_texture = nullptr; + void *_hwnd = nullptr; }; #endif /* YUVDISPLAYER_H_ */ \ No newline at end of file diff --git a/tests/bom.cpp b/tests/bom.cpp index 3502d382..a1e82bbd 100644 --- a/tests/bom.cpp +++ b/tests/bom.cpp @@ -126,6 +126,7 @@ void process_file(const char *file,bool rm_bom){ InfoL << (rm_bom ? "删除" : "添加") << "bom:" << file; } +/// 这个程序是为了统一添加或删除utf-8 bom头 int main(int argc, char *argv[]) { CMD_main cmd_main; try { @@ -148,7 +149,7 @@ int main(int argc, char *argv[]) { bool no_filter = filter_set.find("*") != filter_set.end(); //设置日志 Logger::Instance().add(std::make_shared()); - + path = File::absolutePath(path, ""); for_each_file(path.data(),[&](const char *path){ if(!no_filter){ //开启了过滤器 diff --git a/tests/tab.cpp b/tests/tab.cpp index 4d46bd8c..9d8873ba 100644 --- a/tests/tab.cpp +++ b/tests/tab.cpp @@ -1,18 +1,9 @@ -#include -#include - -#if !defined(_WIN32) - -#include - -#endif //!defined(_WIN32) - +#include #include #include "Util/CMD.h" #include "Util/util.h" #include "Util/logger.h" #include "Util/File.h" -#include "Util/uv_errno.h" using namespace std; using namespace toolkit; @@ -41,17 +32,40 @@ public: virtual ~CMD_main() {} }; +vector split(const string& s, const char *delim) { + vector ret; + int last = 0; + int index = s.find(delim, last); + while (index != string::npos) { + if (index - last >= 0) { + ret.push_back(s.substr(last, index - last)); + } + last = index + strlen(delim); + index = s.find(delim, last); + } + if (!s.size() || s.size() - last >= 0) { + ret.push_back(s.substr(last)); + } + return ret; +} + void process_file(const char *file) { auto str = File::loadFile(file); if (str.empty()) { return; } - auto lines = split(str, "\n"); + auto lines = ::split(str, "\n"); deque lines_copy; for (auto &line : lines) { + if(line.empty()){ + lines_copy.push_back(""); + continue; + } string line_copy; bool flag = false; + int i = 0; for (auto &ch : line) { + ++i; switch (ch) { case '\t' : line_copy.append(" "); @@ -65,6 +79,7 @@ void process_file(const char *file) { break; } if (flag) { + line_copy.append(line.substr(i)); break; } } @@ -75,9 +90,13 @@ void process_file(const char *file) { str.append(line); str.push_back('\n'); } + if(!lines_copy.empty()){ + str.pop_back(); + } File::saveFile(str, file); } +/// 这个程序是为了统一替换tab为4个空格 int main(int argc, char *argv[]) { CMD_main cmd_main; try { @@ -87,10 +106,9 @@ int main(int argc, char *argv[]) { return -1; } - bool rm_bom = cmd_main.hasKey("rm"); string path = cmd_main["in"]; string filter = cmd_main["filter"]; - auto vec = split(filter, ","); + auto vec = ::split(filter, ","); set filter_set; for (auto ext : vec) { @@ -100,6 +118,8 @@ int main(int argc, char *argv[]) { bool no_filter = filter_set.find("*") != filter_set.end(); //设置日志 Logger::Instance().add(std::make_shared()); + path = File::absolutePath(path, ""); + DebugL << path; File::scanDir(path, [&](const string &path, bool isDir) { if (isDir) { return true; diff --git a/tests/test_httpApi.cpp b/tests/test_httpApi.cpp index 8694eac6..a39985bb 100644 --- a/tests/test_httpApi.cpp +++ b/tests/test_httpApi.cpp @@ -50,89 +50,89 @@ const char kPort[] = HTTP_FIELD"port"; #define HTTPS_PORT 443 extern const char kSSLPort[] = HTTP_FIELD"sslport"; onceToken token1([](){ - mINI::Instance()[kPort] = HTTP_PORT; - mINI::Instance()[kSSLPort] = HTTPS_PORT; + mINI::Instance()[kPort] = HTTP_PORT; + mINI::Instance()[kSSLPort] = HTTPS_PORT; },nullptr); }//namespace Http } // namespace mediakit void initEventListener(){ - static onceToken s_token([](){ - NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastHttpRequest,[](BroadcastHttpRequestArgs){ - //const Parser &parser,HttpSession::HttpResponseInvoker &invoker,bool &consumed - if(strstr(parser.Url().data(),"/api/") != parser.Url().data()){ - return; - } - //url以"/api/起始,说明是http api" - consumed = true;//该http请求已被消费 + static onceToken s_token([](){ + NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastHttpRequest,[](BroadcastHttpRequestArgs){ + //const Parser &parser,HttpSession::HttpResponseInvoker &invoker,bool &consumed + if(strstr(parser.Url().data(),"/api/") != parser.Url().data()){ + return; + } + //url以"/api/起始,说明是http api" + consumed = true;//该http请求已被消费 - _StrPrinter printer; - ////////////////method//////////////////// - printer << "\r\nmethod:\r\n\t" << parser.Method(); - ////////////////url///////////////// - printer << "\r\nurl:\r\n\t" << parser.Url(); - ////////////////protocol///////////////// - printer << "\r\nprotocol:\r\n\t" << parser.Tail(); - ///////////////args////////////////// - printer << "\r\nargs:\r\n"; - for(auto &pr : parser.getUrlArgs()){ - printer << "\t" << pr.first << " : " << pr.second << "\r\n"; - } - ///////////////header////////////////// - printer << "\r\nheader:\r\n"; - for(auto &pr : parser.getValues()){ - printer << "\t" << pr.first << " : " << pr.second << "\r\n"; - } - ////////////////content///////////////// - printer << "\r\ncontent:\r\n" << parser.Content(); - auto contentOut = printer << endl; + _StrPrinter printer; + ////////////////method//////////////////// + printer << "\r\nmethod:\r\n\t" << parser.Method(); + ////////////////url///////////////// + printer << "\r\nurl:\r\n\t" << parser.Url(); + ////////////////protocol///////////////// + printer << "\r\nprotocol:\r\n\t" << parser.Tail(); + ///////////////args////////////////// + printer << "\r\nargs:\r\n"; + for(auto &pr : parser.getUrlArgs()){ + printer << "\t" << pr.first << " : " << pr.second << "\r\n"; + } + ///////////////header////////////////// + printer << "\r\nheader:\r\n"; + for(auto &pr : parser.getValues()){ + printer << "\t" << pr.first << " : " << pr.second << "\r\n"; + } + ////////////////content///////////////// + printer << "\r\ncontent:\r\n" << parser.Content(); + auto contentOut = printer << endl; - ////////////////我们测算异步回复,当然你也可以同步回复///////////////// - EventPollerPool::Instance().getPoller()->async([invoker,contentOut](){ - HttpSession::KeyValue headerOut; - //你可以自定义header,如果跟默认header重名,则会覆盖之 - //默认header有:Server,Connection,Date,Content-Type,Content-Length - //请勿覆盖Connection、Content-Length键 - //键名覆盖时不区分大小写 - headerOut["TestHeader"] = "HeaderValue"; - invoker("200 OK",headerOut,contentOut); - }); - }); - }, nullptr); + ////////////////我们测算异步回复,当然你也可以同步回复///////////////// + EventPollerPool::Instance().getPoller()->async([invoker,contentOut](){ + HttpSession::KeyValue headerOut; + //你可以自定义header,如果跟默认header重名,则会覆盖之 + //默认header有:Server,Connection,Date,Content-Type,Content-Length + //请勿覆盖Connection、Content-Length键 + //键名覆盖时不区分大小写 + headerOut["TestHeader"] = "HeaderValue"; + invoker("200 OK",headerOut,contentOut); + }); + }); + }, nullptr); } int main(int argc,char *argv[]){ - //设置退出信号处理函数 - static semaphore sem; - signal(SIGINT, [](int) { sem.post(); });// 设置退出信号 + //设置退出信号处理函数 + static semaphore sem; + signal(SIGINT, [](int) { sem.post(); });// 设置退出信号 - //设置日志 - Logger::Instance().add(std::make_shared()); - Logger::Instance().setWriter(std::make_shared()); + //设置日志 + Logger::Instance().add(std::make_shared()); + Logger::Instance().setWriter(std::make_shared()); - //加载配置文件,如果配置文件不存在就创建一个 - loadIniConfig(); - initEventListener(); + //加载配置文件,如果配置文件不存在就创建一个 + loadIniConfig(); + initEventListener(); - //加载证书,证书包含公钥和私钥 - SSL_Initor::Instance().loadCertificate((exeDir() + "ssl.p12").data()); - //信任某个自签名证书 - SSL_Initor::Instance().trustCertificate((exeDir() + "ssl.p12").data()); - //不忽略无效证书证书(例如自签名或过期证书) - SSL_Initor::Instance().ignoreInvalidCertificate(false); + //加载证书,证书包含公钥和私钥 + SSL_Initor::Instance().loadCertificate((exeDir() + "ssl.p12").data()); + //信任某个自签名证书 + SSL_Initor::Instance().trustCertificate((exeDir() + "ssl.p12").data()); + //不忽略无效证书证书(例如自签名或过期证书) + SSL_Initor::Instance().ignoreInvalidCertificate(false); - //开启http服务器 - TcpServer::Ptr httpSrv(new TcpServer()); - httpSrv->start(mINI::Instance()[Http::kPort]);//默认80 + //开启http服务器 + TcpServer::Ptr httpSrv(new TcpServer()); + httpSrv->start(mINI::Instance()[Http::kPort]);//默认80 //如果支持ssl,还可以开启https服务器 - TcpServer::Ptr httpsSrv(new TcpServer()); - httpsSrv->start(mINI::Instance()[Http::kSSLPort]);//默认443 + TcpServer::Ptr httpsSrv(new TcpServer()); + httpsSrv->start(mINI::Instance()[Http::kSSLPort]);//默认443 - InfoL << "你可以在浏览器输入:http://127.0.0.1/api/my_api?key0=val0&key1=参数1" << endl; + InfoL << "你可以在浏览器输入:http://127.0.0.1/api/my_api?key0=val0&key1=参数1" << endl; - sem.wait(); - return 0; + sem.wait(); + return 0; } diff --git a/tests/test_pusherMp4.cpp b/tests/test_pusherMp4.cpp index 9b94631b..d84353fd 100644 --- a/tests/test_pusherMp4.cpp +++ b/tests/test_pusherMp4.cpp @@ -48,92 +48,92 @@ Timer::Ptr g_timer; //推流失败或断开延迟2秒后重试推流 void rePushDelay(const EventPoller::Ptr &poller, const string &schema, - const string &vhost, - const string &app, - const string &stream, - const string &filePath, - const string &url) ; + const string &vhost, + const string &app, + const string &stream, + const string &filePath, + const string &url) ; //创建推流器并开始推流 void createPusher(const EventPoller::Ptr &poller, const string &schema, - const string &vhost, - const string &app, - const string &stream, - const string &filePath, - const string &url) { - //不限制APP名,并且指定文件绝对路径 - auto src = MP4Reader::onMakeMediaSource(schema,vhost,app,stream,filePath, false); + const string &vhost, + const string &app, + const string &stream, + const string &filePath, + const string &url) { + //不限制APP名,并且指定文件绝对路径 + auto src = MP4Reader::onMakeMediaSource(schema,vhost,app,stream,filePath, false); if(!src){ //文件不存在 WarnL << "MP4文件不存在:" << filePath; return; } - //创建推流器并绑定一个MediaSource + //创建推流器并绑定一个MediaSource pusher.reset(new MediaPusher(src,poller)); - //可以指定rtsp推流方式,支持tcp和udp方式,默认tcp + //可以指定rtsp推流方式,支持tcp和udp方式,默认tcp // (*pusher)[Client::kRtpType] = Rtsp::RTP_UDP; - //设置推流中断处理逻辑 - pusher->setOnShutdown([poller,schema,vhost,app,stream,filePath, url](const SockException &ex) { - WarnL << "Server connection is closed:" << ex.getErrCode() << " " << ex.what(); + //设置推流中断处理逻辑 + pusher->setOnShutdown([poller,schema,vhost,app,stream,filePath, url](const SockException &ex) { + WarnL << "Server connection is closed:" << ex.getErrCode() << " " << ex.what(); //重新推流 - rePushDelay(poller,schema,vhost,app, stream,filePath, url); - }); - //设置发布结果处理逻辑 - pusher->setOnPublished([poller,schema,vhost,app,stream,filePath, url](const SockException &ex) { - if (ex) { - WarnL << "Publish fail:" << ex.getErrCode() << " " << ex.what(); - //如果发布失败,就重试 - rePushDelay(poller,schema,vhost,app, stream, filePath ,url); - }else { - InfoL << "Publish success,Please play with player:" << url; - } - }); - pusher->publish(url); + rePushDelay(poller,schema,vhost,app, stream,filePath, url); + }); + //设置发布结果处理逻辑 + pusher->setOnPublished([poller,schema,vhost,app,stream,filePath, url](const SockException &ex) { + if (ex) { + WarnL << "Publish fail:" << ex.getErrCode() << " " << ex.what(); + //如果发布失败,就重试 + rePushDelay(poller,schema,vhost,app, stream, filePath ,url); + }else { + InfoL << "Publish success,Please play with player:" << url; + } + }); + pusher->publish(url); } //推流失败或断开延迟2秒后重试推流 void rePushDelay(const EventPoller::Ptr &poller, const string &schema, - const string &vhost, - const string &app, - const string &stream, - const string &filePath, - const string &url) { - g_timer = std::make_shared(2,[poller,schema,vhost,app, stream, filePath,url]() { - InfoL << "Re-Publishing..."; - //重新推流 - createPusher(poller,schema,vhost,app, stream, filePath,url); - //此任务不重复 - return false; - }, poller); + const string &vhost, + const string &app, + const string &stream, + const string &filePath, + const string &url) { + g_timer = std::make_shared(2,[poller,schema,vhost,app, stream, filePath,url]() { + InfoL << "Re-Publishing..."; + //重新推流 + createPusher(poller,schema,vhost,app, stream, filePath,url); + //此任务不重复 + return false; + }, poller); } //这里才是真正执行main函数,你可以把函数名(domain)改成main,然后就可以输入自定义url了 int domain(const string & filePath,const string & pushUrl){ - //设置日志 - Logger::Instance().add(std::make_shared()); - Logger::Instance().setWriter(std::make_shared()); + //设置日志 + Logger::Instance().add(std::make_shared()); + Logger::Instance().setWriter(std::make_shared()); auto poller = EventPollerPool::Instance().getPoller(); //vhost/app/stream可以随便自己填,现在不限制app应用名了 createPusher(poller,FindField(pushUrl.data(), nullptr,"://"),DEFAULT_VHOST,"live","stream",filePath,pushUrl); - //设置退出信号处理函数 - static semaphore sem; - signal(SIGINT, [](int) { sem.post(); });// 设置退出信号 + //设置退出信号处理函数 + static semaphore sem; + signal(SIGINT, [](int) { sem.post(); });// 设置退出信号 sem.wait(); - pusher.reset(); - g_timer.reset(); - return 0; + pusher.reset(); + g_timer.reset(); + return 0; } int main(int argc,char *argv[]){ //可以使用test_server生成的mp4文件 - //文件使用绝对路径,推流url支持rtsp和rtmp + //文件使用绝对路径,推流url支持rtsp和rtmp return domain("/Users/xzl/Desktop/bear-1280x720-long.mp4","rtsp://127.0.0.1/live/rtsp_push"); } diff --git a/tests/test_server.cpp b/tests/test_server.cpp index 02d67a1c..297dc8aa 100644 --- a/tests/test_server.cpp +++ b/tests/test_server.cpp @@ -357,6 +357,6 @@ int main(int argc,char *argv[]) { Recorder::stopAll(); lock_guard lck(s_mtxFlvRecorder); s_mapFlvRecorder.clear(); - return 0; + return 0; }