diff --git a/src/Extension/H265.cpp b/src/Extension/H265.cpp index 6894264c..5c4aa916 100644 --- a/src/Extension/H265.cpp +++ b/src/Extension/H265.cpp @@ -25,9 +25,36 @@ */ #include "H265.h" +#include "SPSParser.h" +#include "Util/logger.h" namespace mediakit{ + + +bool getAVCH265Info(const string& strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps) { + return getAVC265Info(strSps.data(),strSps.size(),iVideoWidth,iVideoHeight,iVideoFps); + +} + +bool getAVC265Info(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps){ + T_GetBitContext tGetBitBuf; + T_HEVCSPS tH265SpsInfo; + memset(&tGetBitBuf,0,sizeof(tGetBitBuf)); + memset(&tH265SpsInfo,0,sizeof(tH265SpsInfo)); + tGetBitBuf.pu8Buf = (uint8_t*)sps ; + tGetBitBuf.iBufSize = sps_len ; + if(0 != h265DecSeqParameterSet((void *) &tGetBitBuf, &tH265SpsInfo)){ + return false; + } + h265GetWidthHeight(&tH265SpsInfo, &iVideoWidth, &iVideoHeight); + h265GeFramerate(&tH265SpsInfo, &iVideoFps); + //ErrorL << iVideoWidth << " " << iVideoHeight << " " << iVideoFps; + return true; +} + + + Sdp::Ptr H265Track::getSdp() { if(!ready()){ WarnL << "H265 Track未准备好"; diff --git a/src/Extension/H265.h b/src/Extension/H265.h index cd367b66..7063d470 100644 --- a/src/Extension/H265.h +++ b/src/Extension/H265.h @@ -36,6 +36,9 @@ using namespace toolkit; namespace mediakit { +bool getAVCH265Info(const string& strSps,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); +bool getAVC265Info(const char * sps,int sps_len,int &iVideoWidth, int &iVideoHeight, float &iVideoFps); + /** * 265帧类 */ @@ -176,6 +179,7 @@ public: _vps = vps.substr(vps_prefix_len); _sps = sps.substr(sps_prefix_len); _pps = pps.substr(pps_prefix_len); + onReady(); } /** @@ -206,6 +210,30 @@ public: return CodecH265; } + /** + * 返回视频高度 + * @return + */ + int getVideoHeight() const override{ + return _height ; + } + + /** + * 返回视频宽度 + * @return + */ + int getVideoWidth() const override{ + return _width; + } + + /** + * 返回视频fps + * @return + */ + float getVideoFps() const override{ + return _fps; + } + bool ready() override { return !_vps.empty() && !_sps.empty() && !_pps.empty(); } @@ -280,6 +308,12 @@ private: } } + /** + * 解析sps获取宽高fps + */ + void onReady(){ + getAVCH265Info(_sps,_width,_height,_fps); + } Track::Ptr clone() override { return std::make_shared::type>(*this); } @@ -325,6 +359,9 @@ private: string _vps; string _sps; string _pps; + int _width = 0; + int _height = 0; + float _fps = 0; bool _last_frame_is_idr = false; }; diff --git a/tests/test_server.cpp b/tests/test_server.cpp index 85fa58a4..df30a0c8 100644 --- a/tests/test_server.cpp +++ b/tests/test_server.cpp @@ -180,7 +180,7 @@ void initEventListener() { NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastMediaChanged, [](BroadcastMediaChangedArgs) { if (schema == RTMP_SCHEMA && app == "live") { lock_guard lck(s_mtxFlvRecorder); - if (/*bRegist*/0) { + if (bRegist) { DebugL << "开始录制RTMP:" << schema << " " << vhost << " " << app << " " << stream; GET_CONFIG(string, http_root, Http::kRootPath); auto path = @@ -239,9 +239,8 @@ int main(int argc,char *argv[]) { //这里是拉流地址,支持rtmp/rtsp协议,负载必须是H264+AAC //如果是其他不识别的音视频将会被忽略(譬如说h264+adpcm转发后会去除音频) - auto urlList = { -// "rtsp://admin:admin123@192.168.5.82/", - "rtsp://192.168.5.24/live/chn0", + auto urlList = {"rtmp://live.hkstv.hk.lxdns.com/live/hks1", + "rtmp://live.hkstv.hk.lxdns.com/live/hks2" //rtsp链接支持输入用户名密码 /*"rtsp://admin:jzan123456@192.168.0.122/"*/}; map proxyMap; @@ -260,7 +259,7 @@ int main(int argc,char *argv[]) { //rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 - PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", to_string(i).data(),true,true,true,true)); + PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", to_string(i).data())); //指定RTP over TCP(播放rtsp时有效) (*player)[kRtpType] = Rtsp::RTP_TCP; //开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试 @@ -277,7 +276,7 @@ int main(int argc,char *argv[]) { " http-flv地址 : http://127.0.0.1/live/0.flv\n" " rtsp地址 : rtsp://127.0.0.1/live/0\n" " rtmp地址 : rtmp://127.0.0.1/live/0"; -#if 1 + //加载证书,证书包含公钥和私钥 SSL_Initor::Instance().loadCertificate((exeDir() + "ssl.p12").data()); //信任某个自签名证书 @@ -294,12 +293,12 @@ int main(int argc,char *argv[]) { //简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象 //测试方法:telnet 127.0.0.1 9000 -// TcpServer::Ptr shellSrv(new TcpServer()); + TcpServer::Ptr shellSrv(new TcpServer()); TcpServer::Ptr rtspSrv(new TcpServer()); TcpServer::Ptr rtmpSrv(new TcpServer()); TcpServer::Ptr httpSrv(new TcpServer()); -// shellSrv->start(shellPort); + shellSrv->start(shellPort); rtspSrv->start(rtspPort);//默认554 rtmpSrv->start(rtmpPort);//默认1935 //http服务器,支持websocket @@ -313,17 +312,15 @@ int main(int argc,char *argv[]) { //支持ssl加密的rtsp服务器,可用于诸如亚马逊echo show这样的设备访问 TcpServer::Ptr rtspSSLSrv(new TcpServer()); rtspSSLSrv->start(rtspsPort);//默认322 - + //服务器支持动态切换端口(不影响现有连接) NoticeCenter::Instance().addListener(ReloadConfigTag,Broadcast::kBroadcastReloadConfig,[&](BroadcastReloadConfigArgs){ //重新创建服务器 -#if 0 if(shellPort != mINI::Instance()[Shell::kPort].as()){ shellPort = mINI::Instance()[Shell::kPort]; shellSrv->start(shellPort); InfoL << "重启shell服务器:" << shellPort; } -#endif if(rtspPort != mINI::Instance()[Rtsp::kPort].as()){ rtspPort = mINI::Instance()[Rtsp::kPort]; rtspSrv->start(rtspPort); @@ -334,7 +331,6 @@ int main(int argc,char *argv[]) { rtmpSrv->start(rtmpPort); InfoL << "重启rtmp服务器" << rtmpPort; } -#if 1 if(httpPort != mINI::Instance()[Http::kPort].as()){ httpPort = mINI::Instance()[Http::kPort]; httpSrv->start(httpPort); @@ -345,7 +341,6 @@ int main(int argc,char *argv[]) { httpsSrv->start(httpsPort); InfoL << "重启https服务器" << httpsPort; } -#endif if(rtspsPort != mINI::Instance()[Rtsp::kSSLPort].as()){ rtspsPort = mINI::Instance()[Rtsp::kSSLPort]; @@ -353,7 +348,7 @@ int main(int argc,char *argv[]) { InfoL << "重启rtsps服务器" << rtspsPort; } }); -#endif + //设置退出信号处理函数 static semaphore sem; signal(SIGINT, [](int) { sem.post(); });// 设置退出信号