From 9157116e1d19b8ae6621d849ec287c3cb6e66102 Mon Sep 17 00:00:00 2001 From: eguid <642209085@qq.com> Date: Thu, 22 Sep 2016 14:42:49 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=8E=9FAPI=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=E4=B8=8D=E5=8F=98=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=86=85=E9=83=A8=E9=80=BB=E8=BE=91=202=E3=80=81=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=B8=A4=E4=B8=AA=E5=8F=82=E6=95=B0=EF=BC=8Ccodec:?= =?UTF-8?q?=E8=A7=A3=E7=A0=81=EF=BC=88=E9=BB=98=E8=AE=A4=E8=A7=A3=E7=A0=81?= =?UTF-8?q?=E5=99=A8=E6=98=AFH264=EF=BC=89=EF=BC=8CtwoPart:0-2,0=3D?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E5=85=83=E7=A0=81=E6=B5=81=EF=BC=8C1=3D?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E8=87=AA=E5=AE=9A=E4=B9=89=E6=B5=81=EF=BC=8C?= =?UTF-8?q?2=3D=E6=8E=A8=E9=80=81=E4=B8=A4=E4=B8=AA=E6=B5=81=EF=BC=88?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E8=87=AA=E5=AE=9A=E4=B9=89=E6=B5=81=EF=BC=8C?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E5=85=83=E7=A0=81=E6=B5=81=EF=BC=89=203?= =?UTF-8?q?=E3=80=81=E4=B8=8D=E6=94=AF=E6=8C=81=E9=9F=B3=E9=A2=91=E8=A7=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=8C=E9=BB=98=E8=AE=A4=E5=8E=BB=E9=99=A4=E9=9F=B3?= =?UTF-8?q?=E9=A2=91=204=E3=80=81=E8=BE=93=E5=87=BA=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81=E6=98=BE=E7=A4=BA=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=8A=9F=E8=83=BD=205=E3=80=81=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E5=AE=9E=E4=BD=93=E7=B1=BB=E5=B9=B6=E4=BE=9D?= =?UTF-8?q?=E8=B5=96json=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .settings/org.eclipse.jdt.core.prefs | 11 - bin/cc/eguid/livepush/PushManager.class | Bin 421 -> 421 bytes bin/cc/eguid/livepush/PushManagerImpl.class | Bin 3572 -> 3605 bytes bin/cc/eguid/livepush/Readme | 8 +- bin/cc/eguid/livepush/conf/ConfUtil.class | Bin 1574 -> 1592 bytes .../livepush/entity/LivePushEntity.class | Bin 0 -> 2327 bytes .../eguid/livepush/handler/OutHandler.class | Bin 2501 -> 2399 bytes .../eguid/livepush/handler/PushHandler.class | Bin 400 -> 400 bytes .../livepush/handler/PushHandlerImpl.class | Bin 3438 -> 3851 bytes src/cc/eguid/livepush/PushManager.java | 2 +- src/cc/eguid/livepush/PushManagerImpl.java | 190 ++++++++---------- src/cc/eguid/livepush/Readme | 8 +- src/cc/eguid/livepush/conf/ConfUtil.java | 3 +- .../eguid/livepush/entity/LivePushEntity.java | 183 +++++++++++++++++ src/cc/eguid/livepush/handler/OutHandler.java | 147 ++++++-------- .../eguid/livepush/handler/PushHandler.java | 4 +- .../livepush/handler/PushHandlerImpl.java | 179 ++++++++++------- 17 files changed, 453 insertions(+), 282 deletions(-) delete mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 bin/cc/eguid/livepush/entity/LivePushEntity.class create mode 100644 src/cc/eguid/livepush/entity/LivePushEntity.java diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 3a21537..0000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,11 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/bin/cc/eguid/livepush/PushManager.class b/bin/cc/eguid/livepush/PushManager.class index dfcef7824ca7a4b2d1e06f1e7e1d4cc88fc807ef..4fb28ac2547828d33aa8d8f69d448954ed516ea8 100644 GIT binary patch delta 16 YcmZ3=yp(yu8aDr=tkmR^iJLwH05tvwAOHXW delta 16 YcmZ3=yp(yu8n)n)qRhPXiJLwH05$~&KmY&$ diff --git a/bin/cc/eguid/livepush/PushManagerImpl.class b/bin/cc/eguid/livepush/PushManagerImpl.class index 278c6774d6c505553108e729875d3259a1ab2579..c2de0e2fe075b4e39a7e9dbfe3ae7c4bbf313f0e 100644 GIT binary patch delta 511 zcmYk3T}xD96osGn%sHMs$D@+imow3%jg6QNRQ5rEm6{k%T~$Jq5u$=KC>3;5WA^1m zVew+%O<3f;Ix$@o_z$B05XJleZ-ds%M0E2m-o4k_d+oiq+m_?2G5g)Gw;N7NF&_Ki zn4@;f>uCD5__nGEnJTmrOkT6O6HAvf)Al?~PnH60R4!z)q>8xim6Ij%M|)U>8GG9422y zS5D!)@^Di9PDyb_nzM@ZOLI<&3-mD{-5|qU#(FN+3q@O~`%SY?zt7@slbG_! zCA7!+hFsz*5!cwmnA+da-fqhMxV+x3xU@kup#5Hsj<-(zcZuNNC03%0mm?%^zeTA( DV7y$| delta 498 zcmYk2%}Z2K7{-5R=3cMenTwKNr6Z+|qceWw!m={@kQz-;M5#0qL6Omz(Z-D0==7zv zi57?U>RylrCa6V!K>tabAlwE%YK5EkaL)TY&-uOYr`UeOR=9j(b!BlW(|_IWg{q6O z@J`6Y?RPg`{OxX;=)Y#aVc0I0x7bxLS^Vi`L&;_w&Qn2(dM?mPoG#S_5XGo=(?+{a zV+(%L?)x$C6uvsf{_vCTWn8YtEyxoM9gKCdbF|*2db^mDlA_>Qgm{B_& zNf*vtbv`rmjrpn5nJ+A!bxLGQY90APp zl2?RftmidvG|5|iUaQ`*ena{chpJ7f-s!c9vS^+8LzBl%kM|26xdyFjJDO{pBarlr s;uAd9nzCFIS(;_B=50rC+Zg*KxLEW2#Pa?B%l{hmxNAgMx4(kK0Y4a4VE_OC diff --git a/bin/cc/eguid/livepush/Readme b/bin/cc/eguid/livepush/Readme index 5c56766..701d76b 100644 --- a/bin/cc/eguid/livepush/Readme +++ b/bin/cc/eguid/livepush/Readme @@ -1,4 +1,4 @@ -使用说明: +livePush0.2.1使用说明: (重要:使用前必须保证ffmpeg环境包在该项目的WEB-INF\classes\cc\eguid\livepush\ffmpeg\目录中) 1、对象创建 PushManager pusher = new PushManagerImpl(); @@ -8,19 +8,21 @@ PushManager pusher = new PushManagerImpl(); name:应用名; input:接收地址; output:推送地址; +codec:视频编码; fmt:视频格式; fps:视频帧率; rs:视频分辨率; -disableAudio:是否开启音频; +twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码) 2.2、参数使用 Map map = new HashMap(); map.put("appName", "testwanglaing123"); map.put("input","rtsp://admin:admin@192.168.2.236:37779/cam/realmonitor?channel=1&subtype=0"); map.put("output", "rtmp://192.168.30.21/live/"); +map.put("codec","h264"); map.put("fmt", "flv"); map.put("fps", "25"); map.put("rs", "640x360"); -map.put("disableAudio", "true"); +map.put("twoPart","2"); 3、调用方法 3.1、发布方法 diff --git a/bin/cc/eguid/livepush/conf/ConfUtil.class b/bin/cc/eguid/livepush/conf/ConfUtil.class index a77f041d46611f38a1567245f430734d4b0ff466..9eec51bb6047b536a995d06abf67fd507b7adf47 100644 GIT binary patch delta 543 zcmXw$OHWfl7>1uY$8t&?V`;>c3cb@JwLL1Hs-P9o7SYxa2@%9g8ZAu?6rv5$#DtA* zOkB+mz_`%3FOBtLm8urpx37o^@^8vbg?#md2W0YOLs1DmZ(PQJZGoJHvuxk^Gmo z85M=^?85{ed?U0t>M|IJy2M>ZcF1jWDsbB6tjqcGXD0U)fs!UOUC!l-I^Y@FoD9sn z+sB0lQfB4Ij5C!Gy8Tty;kt8>%(FW-%q00u78tS6!$Z z6Wxp}SB(qZ86U~mq_S}1e_`UrXjg9Cn0NhF3MJ_zSq|PCM>}E79+o)V9Ne+{DK8aYQz%iYp z|88lkO{$XPoNyw(+-QoTBt$a6w4i@+vA%3ojo(kkx?=@NaY}NUGtLuV-bis)QX(%1 z*i9veDy4JoPk*J;Ol?VV$`n1Abna>6ff$!03nbru(4r#yksdT){te+!)MaFy)I!=N z9m=?5UB=fq@{Xy{NtYRy*^)ElA6yBCDlQjau-PMBR^QjEf<~Xh1icEQsH2c%gseKk z1aYQRWL9~~q^T%r`@31)&TMCgvXU5FQ9PkI39fPtAJ>&%;`>Qir=WYNE{3!2kBc$q VvwuMIl>On4iGpY8H&nV0^A}2ygBSn+ diff --git a/bin/cc/eguid/livepush/entity/LivePushEntity.class b/bin/cc/eguid/livepush/entity/LivePushEntity.class new file mode 100644 index 0000000000000000000000000000000000000000..b4e2923a39b3236670ee62b62cf2e1eebe91c72d GIT binary patch literal 2327 zcmc(f%TE(g6voe#J}4O;@{-~MD^}1nK&u)ZOd5eh2Qwqa};dcm;s`r^ulnR6l(R;W{C zt)iYW%a&2FwvCm7iQ?+2%rZbHyw#d(iFaV$LXJ4IBiAs3n8W zx`q9d>3{SJv@Zq^p5gyylG!LJbV4PSnpvGxsl`*LRBH9qX_eYMHK@`dPiZQ(dum9f z4o{7!)Je?>HRVlbX7|=Q2a^X+h?>g2nl6bgd^3&MXx_WuM%3426xqevZAX#b)nVl4 z`0~R@dV(`N2qMEGgv@P@DB;K*`1&y)+@U7<0L#16!lZkPOtD(dnR6D8a>w8A!U&Hi z#bIItz9EWIFGZ*kI*KYYO$b8DJ|CM((qn44P6L(27wjDt}WDqafsp5OMU2{K;INPkD@En z-19otXwX|&!p9in!4vFbJa{mXb8J9RD7Gjh6q^(lifxJr#Rjp}I-RMVPDk|Y`AB^` zC<*|H@Iy}Cl3Fv0hMqOksAe0(!j`?`dgf*TvMhG!_Nx9ICtN#@g4>aS#Qh+5r6A*S zkhmXY1t7UPAnYbPFd+r$_k&nckaKd7em}^4fRyWi@MSW{c_~Q35Ask7azPG~@Pj-C z$dfuCJV6X{Q3^8P2YD(5xg-Y}@Pj-9$n!cNJirVxDFsRTL0(EhrsN<=Kger LVUQW|hjHyUIN?Xv literal 0 HcmV?d00001 diff --git a/bin/cc/eguid/livepush/handler/OutHandler.class b/bin/cc/eguid/livepush/handler/OutHandler.class index 88b3949ddab159fa290a05be54caa9fda5c07ddb..e42e992c306ac104beb5fec3821a523dc98550fe 100644 GIT binary patch delta 1154 zcmaiz-%lJ>6vsbzc4uc9N5Q3Qp@F8QAW#fwp)`R)p@IUgEx%f&wCXA=-3klcU9k1n zf-Q|nu}w4hKx5L_#6X%x+s3Y>-Aa5gni~HGA7qy_KJaE@OvN)rQR9P|%)Q@x&i8!J zckaFOP416A^X~7rz5;5Pyl$3i%~@3Ol);mVoMXZ9VAW7CGFa7fG8PXFTkN1(;Tjo> zEBt{6>F`KZXEYp%_r#;2;BdXcPJ2-+uqU()W?bTf7IoCyKWRI?H8fZ}M5DdMwW+X4 zk)2LWr033N&dq0TPOhXTO|h`o;%Qp!%dUE%KV$JMZFbsK?CBt2@SL6P&MSJJMujoz z^c;$K*{{(1qw(0N$u7Dqy6LeGYekQFIiT=l&V8DhNjl0eILa^D*W6nZhZNS*!j;TN z*D@b|mY$ySa#&HalA2z=b7A@R$LZAj>4k-*h0BtX;2OwW{Y3b6US1O863rw($V`5| zbjMyvT{PLqD;7c86kgedfj~GC^75LZEPejM^30|5nW=lH=GS!Z&Dc45-nNj%>kNwb z!BD(?K=!n(yu+~>c5EI~6qI$?U%NKdco~wfJ+gdjae4l%i6UZAN{)j@EshhFY&h0D z6dn&f5IJNJw`cXuTl8>bAap{Z+7)If8XbwYuLV4@crZQ|v+wGa>OK2c{Yri@Zt}>Y zkVhyYml7VAr-D*D<>}HZ(W$b1MuWaXP_^A_lqc$?!T^=80)KIa=%VzXVAXa9~=wUD(+M>)EIGT5b*g5T(WLOWm(J8tmqDi+4yNr@n)w0{*iO%sj< GCjJ1I0Vg{E delta 1258 zcmZ8g>rYd67=C^|Jw1ndvau2aC@=*TXq}ycPPq=n3#>R4ynr&TP)iXCwuRwtwG1Xv z@RC!rV3x4Wks3F_>#-?peljK|Cfojjec|-LC;Z^IC9?OFt(kl|=e<1d^Im^{S)Qhu zpTCa%2A~*2_ssbQn+Q7tf6N!~_n5I6MFO@kq;@#_oc2zq*KKbI_&i>>MEI@pGcLC} z1s`CCfbDOB&iMnbE(s+lW#C*sAHzyVg2U5ouP1^4(YTylr2@(s(&Z{H-K=M;l<*;{ z9=(B1uip6~35OFscJ~HE z9A(I${7c;G%zzq=E|s=0b3;V4KG*gw+loaTXRr`(E^<@*KJ;JR1o?zvb&?>i497#% z&yD!yiFjC1hwsvi%5YLI(9IIF0=bBF(qW;qkge zw9CUrdtQfxGw7rm+^#@P8?B|FuvX{u>U`Y{Sp~InCAW&IJ4-#bXt5{StxIMw_$A~c zRhN1t^x;$Tdi+(Lo<3KCq*=f@xq#0}Gx-C~K(C*H)le3Xx6RcrpXN8Q0r@(AJ2M|f ztVRmf;4Q328Va!iR@h*ZkD3nfMc`2^Pnyd4?Ii7xUz!Soi~Bih*tlHaByvyhxgayGhtkmR^iJ#^H05x+5ApigX delta 16 YcmbQhJb`(_8@Aw*qRhPXiJ#^H05*CDK>z>% diff --git a/bin/cc/eguid/livepush/handler/PushHandlerImpl.class b/bin/cc/eguid/livepush/handler/PushHandlerImpl.class index cabb99d83eda8334cffc5d21e5de5f00533366d9..951ec12b7a5951319f4e63e308423f62303dd11a 100644 GIT binary patch literal 3851 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 h$map); +public String push(Mapmap); /** * 通过应用名删除某个push * @param pushId diff --git a/src/cc/eguid/livepush/PushManagerImpl.java b/src/cc/eguid/livepush/PushManagerImpl.java index a0e7c93..916c5e9 100644 --- a/src/cc/eguid/livepush/PushManagerImpl.java +++ b/src/cc/eguid/livepush/PushManagerImpl.java @@ -14,7 +14,6 @@ import cc.eguid.livepush.handler.OutHandler; import cc.eguid.livepush.handler.PushHandler; import cc.eguid.livepush.handler.PushHandlerImpl; - /** * 实现push管理器的push,delete,view服务 * @@ -24,106 +23,91 @@ import cc.eguid.livepush.handler.PushHandlerImpl; * @since jdk1.7 */ -public class PushManagerImpl implements PushManager -{ - /** - *配置文件 - */ - private ConfUtil confUtil = new ConfUtil(); - - public PushManagerImpl() - { - confUtil.isHave(); - } - - /** - * 引用push处理器 - */ - private PushHandler pusher = new PushHandlerImpl(); - - /** - * 管理处理器的主进程Process及两个输出线程的关系 - */ - private HandlerDao hd = new HandlerDaoImpl(); - - public void setPusher(PushHandler pusher) - { - this.pusher = pusher; - } - - public void setHd(HandlerDao hd) - { - this.hd = hd; - } - - @Override - public String push(Map parammap) - { - // ffmpeg环境是否配置正确 - if (!confUtil.isHave()) - { - return null; - } - - // 参数是否符合要求 - if (parammap == null || parammap.isEmpty() || !parammap.containsKey("appName")) - { - return null; - } - String appName = null; - ConcurrentMap resultMap = null; - try - { - appName = parammap.get("appName"); - if (appName != null && "".equals(appName.trim())) - { - return null; - } - parammap.put("ffmpegPath", confUtil.getPath()); - resultMap = pusher.push(parammap); - // 处理器和输出线程对应关系 - hd.set(appName, resultMap); - } - catch (Exception e) - { - // 暂时先写这样,后期加日志 - System.err.println("重大错误:参数不符合要求" + e.getMessage()); - } - return appName; - - } - - @Override - public boolean closePush(String appName) - { - if (hd.isHave(appName)) - { - ConcurrentMap map = hd.get(appName); - // 关闭两个线程 - ((OutHandler)map.get("error")).destroy(); - // ((OutHandler)map.get("info")).destroy(); - // 暂时先这样写,后期加日志 - System.out.println("停止命令-----end commond"); - // 关闭命令主进程 - ((Process)map.get("process")).destroy(); - // 删除处理器与线程对应关系表 - hd.delete(appName); - return true; - } - return false; - } - - @Override - public Set viewAppName() - { - return hd.getAllAppName(); - } - - @Override - public boolean isHave(String appName) - { - hd.isHave(appName); - return false; - - } +public class PushManagerImpl implements PushManager { + /** + * 配置文件 + */ + private ConfUtil confUtil = new ConfUtil(); + + public PushManagerImpl() { + confUtil.isHave(); + } + + /** + * 引用push处理器 + */ + private PushHandler pusher = new PushHandlerImpl(); + + /** + * 管理处理器的主进程Process及两个输出线程的关系 + */ + private HandlerDao hd = new HandlerDaoImpl(); + + public synchronized void setPusher(PushHandler pusher) { + this.pusher = pusher; + } + + public synchronized void setHd(HandlerDao hd) { + this.hd = hd; + } + + @Override + public synchronized String push(Map parammap) { + String appName = null; + ConcurrentMap resultMap = null; + try { + // ffmpeg环境是否配置正确 + if (!confUtil.isHave()) { + return null; + } + // 参数是否符合要求 + if (parammap == null || parammap.isEmpty() || !parammap.containsKey("appName")) { + return null; + } + appName = (String) parammap.get("appName"); + if (appName != null && "".equals(appName.trim())) { + return null; + } + parammap.put("ffmpegPath", confUtil.getPath()); + resultMap = pusher.push(parammap); + // 处理器和输出线程对应关系 + hd.set(appName, resultMap); + } catch (Exception e) { + // 暂时先写这样,后期加日志 + System.err.println("重大错误:参数不符合要求或运行失败" + e.getMessage()); + return null; + } + return appName; + + } + + @Override + public synchronized boolean closePush(String appName) { + if (hd.isHave(appName)) { + ConcurrentMap map = hd.get(appName); + // 关闭两个线程 + ((OutHandler) map.get("error")).destroy(); + // ((OutHandler)map.get("info")).destroy(); + // 暂时先这样写,后期加日志 + System.out.println("停止命令-----end commond"); + // 关闭命令主进程 + ((Process) map.get("process")).destroy(); + // 删除处理器与线程对应关系表 + hd.delete(appName); + return true; + } + return false; + } + + @Override + public synchronized Set viewAppName() { + return hd.getAllAppName(); + } + + @Override + public synchronized boolean isHave(String appName) { + hd.isHave(appName); + return false; + + } } diff --git a/src/cc/eguid/livepush/Readme b/src/cc/eguid/livepush/Readme index 5c56766..701d76b 100644 --- a/src/cc/eguid/livepush/Readme +++ b/src/cc/eguid/livepush/Readme @@ -1,4 +1,4 @@ -使用说明: +livePush0.2.1使用说明: (重要:使用前必须保证ffmpeg环境包在该项目的WEB-INF\classes\cc\eguid\livepush\ffmpeg\目录中) 1、对象创建 PushManager pusher = new PushManagerImpl(); @@ -8,19 +8,21 @@ PushManager pusher = new PushManagerImpl(); name:应用名; input:接收地址; output:推送地址; +codec:视频编码; fmt:视频格式; fps:视频帧率; rs:视频分辨率; -disableAudio:是否开启音频; +twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码) 2.2、参数使用 Map map = new HashMap(); map.put("appName", "testwanglaing123"); map.put("input","rtsp://admin:admin@192.168.2.236:37779/cam/realmonitor?channel=1&subtype=0"); map.put("output", "rtmp://192.168.30.21/live/"); +map.put("codec","h264"); map.put("fmt", "flv"); map.put("fps", "25"); map.put("rs", "640x360"); -map.put("disableAudio", "true"); +map.put("twoPart","2"); 3、调用方法 3.1、发布方法 diff --git a/src/cc/eguid/livepush/conf/ConfUtil.java b/src/cc/eguid/livepush/conf/ConfUtil.java index cf90c0c..350c4c8 100644 --- a/src/cc/eguid/livepush/conf/ConfUtil.java +++ b/src/cc/eguid/livepush/conf/ConfUtil.java @@ -29,8 +29,9 @@ public class ConfUtil */ private void initConfInfo() { - System.out.print("预加载配置:"); + String path = getClass().getResource("../").getPath() + "ffmpeg/ffmpeg.exe"; + System.out.print("预加载FFMPEG配置:"+path); File ffmpeg =new File(path); ffmpegPath=ffmpeg.getPath(); if (isHave=ffmpeg.isFile()) diff --git a/src/cc/eguid/livepush/entity/LivePushEntity.java b/src/cc/eguid/livepush/entity/LivePushEntity.java new file mode 100644 index 0000000..5b39713 --- /dev/null +++ b/src/cc/eguid/livepush/entity/LivePushEntity.java @@ -0,0 +1,183 @@ +package cc.eguid.livepush.entity; + +import java.io.Serializable; + +public class LivePushEntity implements Serializable { + private static final long serialVersionUID = -1580871796857185739L; + + public LivePushEntity() { + super(); + } + + /** + * 示例: appName="test123" + * input="rtsp://admin:admin@192.168.2.236:37779/cam/realmonitor?channel=1&subtype=0" + * output="rtmp://192.168.30.21/live/" codec="h264" fmt="flv" fps="25" + * rs="640x360" twoPart="2" twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码) + */ + + public LivePushEntity(String appName, String input, String output, String codec, String fmt, String fps, String rs, + String twoPart) { + super(); + this.appName = appName; + this.input = input; + this.output = output; + this.fmt = fmt; + this.fps = fps; + this.rs = rs; + this.codec = codec; + this.twoPart = twoPart; + } + + /** + * 应用名 + */ + private String appName; + + /** + * 视频源地址,可以是实时流地址也可以是文件路径 + */ + private String input; + + /** + * 实时流输出地址,这个默认是固定的rtmp服务器发布地址 + */ + private String output; + + /** + * 视频格式,默认flv + */ + private String fmt; + + /** + * 帧率,最好是25-60 + */ + private String fps; + + /** + * 分辨率,例如:640x360 + */ + private String rs; + + /** + * 视频编码 + */ + private String codec; + /** + * twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码) + */ + private String twoPart; + + /** + * @return the appName + */ + public String getAppName() { + return appName; + } + + /** + * @param appName + * the appName to set + */ + public void setAppName(String appName) { + this.appName = appName; + } + + /** + * @return the input + */ + public String getInput() { + return input; + } + + /** + * @param input + * the input to set + */ + public void setInput(String input) { + this.input = input; + } + + /** + * @return the output + */ + public String getOutput() { + return output; + } + + /** + * @param output + * the output to set + */ + public void setOutput(String output) { + this.output = output; + } + + /** + * @return the fmt + */ + public String getFmt() { + return fmt; + } + + /** + * @param fmt + * the fmt to set + */ + public void setFmt(String fmt) { + this.fmt = fmt; + } + + /** + * @return the fps + */ + public String getFps() { + return fps; + } + + /** + * @param fps + * the fps to set + */ + public void setFps(String fps) { + this.fps = fps; + } + + /** + * @return the rs + */ + public String getRs() { + return rs; + } + + /** + * @param rs + * the rs to set + */ + public void setRs(String rs) { + this.rs = rs; + } + + /** + * @return the codec + */ + public String getCodec() { + return codec; + } + + /** + * @param codec + */ + public void setCodec(String codec) { + this.codec = codec; + } + + public String getTwoPart() { + return twoPart; + } + + public void setTwoPart(String twoPart) { + this.twoPart = twoPart; + } + +} diff --git a/src/cc/eguid/livepush/handler/OutHandler.java b/src/cc/eguid/livepush/handler/OutHandler.java index ad2bbec..6da9c2e 100644 --- a/src/cc/eguid/livepush/handler/OutHandler.java +++ b/src/cc/eguid/livepush/handler/OutHandler.java @@ -3,13 +3,11 @@ */ package cc.eguid.livepush.handler; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; - /** * 用于输出命令行主进程的消息线程(必须开启,否则命令行主进程无法正常执行) 重要:该类重写了destroy方法,用于安全的关闭该线程 * @@ -19,92 +17,71 @@ import java.io.InputStreamReader; * @since jdk1.7 */ -public class OutHandler extends Thread -{ - /** - * 控制状态 - */ - private volatile boolean desstatus = true; +public class OutHandler extends Thread { + /** + * 控制状态 + */ + private volatile boolean desstatus = true; + + /** + * 读取输出流 + */ + private BufferedReader br = null; + + /** + * 输出类型 + */ + private String type = null; - /** - * 读取输出流 - */ - private BufferedReader br=null; + public OutHandler(InputStream is, String type) { + br = new BufferedReader(new InputStreamReader(is)); + this.type = type; + } - /** - * 输出类型 - */ - private String type=null; + /** + * 重写线程销毁方法,安全的关闭线程 + */ + @Override + public void destroy() { + setDesStatus(false); + } - public OutHandler(InputStream is, String type) - { - br = new BufferedReader(new InputStreamReader(is)); - this.type = type; - } + public void setDesStatus(boolean desStatus) { + this.desstatus = desStatus; + } - /** - * 重写线程销毁方法,安全的关闭线程 - */ - @Override - public void destroy() - { - setDesStatus(false); - } - - public void setDesStatus(boolean desStatus) - { - this.desstatus = desStatus; - } + /** + * 执行输出线程 + */ + @Override + public void run() { + String msg = null; + int index = 0; + int errorIndex = 0; + int status = 10; + try { + System.out.println(type + "开始推流!"); + while (desstatus && (msg = br.readLine()) != null) { + if (msg.indexOf("[rtsp") != -1) { + System.out.println("接收" + status + "个数据包" + msg); + System.out.println(type + ",网络异常丢包,丢包次数:" + errorIndex++ + ",消息体:" + msg); + status = 10; + index = 0; + } - /** - * 执行输出线程 - */ - @Override - public void run() - { - String msg = null; - int status = 0; - int index = 0; - try - { - while (desstatus&&(msg = br.readLine()) != null) - { - if (msg.indexOf("[rtsp") != -1) - { - if (status > 5) - { - System.err.println(type + "持续发生严重网络丢包错误,建议立即关闭该应用后检查网络状况!"); - } - else - { - System.out.println(type + ",网络异常丢包:" + msg); - } - status++ ; - } - else if (msg.indexOf("[h264") != -1) - { - System.out.println(type + ",解码错误:" + msg); - } - else - { - if (index >= 10) - { - System.out.println(type + ",网络消息:接收到" + index + "个数据包"); - index = 0; - } - index++ ; - } - } - } - catch (IOException e) - { - System.out.println("发生内部异常错误,自动关闭["+this.getId()+"]线程"); - destroy(); - }finally { - if(this.isAlive()) - { - destroy(); - } - } - } + if (index % status == 0) { + System.out.println("接收" + status + "个数据包" + msg); + status *= 2; + } + index++; + } + } catch (IOException e) { + System.out.println("发生内部异常错误,自动关闭[" + this.getId() + "]线程"); + destroy(); + } finally { + if (this.isAlive()) { + destroy(); + } + } + } } diff --git a/src/cc/eguid/livepush/handler/PushHandler.java b/src/cc/eguid/livepush/handler/PushHandler.java index 6443c50..f37a274 100644 --- a/src/cc/eguid/livepush/handler/PushHandler.java +++ b/src/cc/eguid/livepush/handler/PushHandler.java @@ -23,12 +23,12 @@ public interface PushHandler { /** * 处理push操作(包含一个主进程和两个输出线程) - * @param map + * @param parammap * 格式: * name:应用名;input:接收地址;output:推送地址;fmt:视频格式;fps:视频帧率;rs:视频分辨率;disableAudio:是否开启音频 * @return map(进程,消息(info,error)) * @throws IOException * */ -public ConcurrentMap push(Mapmap)throws Exception; +public ConcurrentMap push(Map parammap)throws Exception; } diff --git a/src/cc/eguid/livepush/handler/PushHandlerImpl.java b/src/cc/eguid/livepush/handler/PushHandlerImpl.java index c1382a0..15f3bf4 100644 --- a/src/cc/eguid/livepush/handler/PushHandlerImpl.java +++ b/src/cc/eguid/livepush/handler/PushHandlerImpl.java @@ -16,78 +16,111 @@ import java.util.concurrent.ConcurrentMap; * @since jdk1.7 */ -public class PushHandlerImpl implements PushHandler -{ - /* - * "ffmpeg -i "+ "rtsp://admin:admin@192.168.2.236:37779/cam/realmonitor?channel=1&subtype=0 "+ - * " -f flv -r 25 -s 640x360 -an" + " rtmp://192.168.30.21/live/test" 推送流格式: - * name:应用名;input:接收地址;output:推送地址;fmt:视频格式;fps:视频帧率;rs:视频分辨率;disableAudio:是否开启音频 - */ - @Override - public ConcurrentMap push(Map paramMap) - throws Exception - { - // 从map里面取数据,组装成命令 - String comm = getComm4Map(paramMap); - ConcurrentMap resultMap = null; - // 执行命令行 - System.out.println("执行命令----start commond:" + comm); - final Process proc = Runtime.getRuntime().exec(comm); - OutHandler errorGobbler = new OutHandler(proc.getErrorStream(), paramMap.get("appName")); - // OutHandler outputGobbler = new OutHandler(proc.getInputStream(), "Info"); +public class PushHandlerImpl implements PushHandler { + + @Override + public ConcurrentMap push(Map paramMap) throws Exception { + ConcurrentMap resultMap = null; + Process proc =null; + OutHandler errorGobbler=null; + try{ + // 从map里面取数据,组装成命令 + String comm = getComm4Map(paramMap); + if(comm==null) + { + throw new Exception(); + } + // 执行命令行 + System.out.println("执行命令:" + comm); + proc = Runtime.getRuntime().exec(comm); + + errorGobbler = new OutHandler(proc.getErrorStream(), (String) paramMap.get("appName")); + errorGobbler.start(); + + // 返回参数 + resultMap = new ConcurrentHashMap(); + // resultMap.put("info", outputGobbler); + resultMap.put("error", errorGobbler); + resultMap.put("process", proc); + }catch(Exception e){ + if(proc!=null){ + proc.destroy(); + } + if(errorGobbler!=null){ + errorGobbler.destroy(); + } + throw e; + } + return resultMap; + } - errorGobbler.start(); - // outputGobbler.start(); - // 返回参数 - resultMap = new ConcurrentHashMap(); - // resultMap.put("info", outputGobbler); - resultMap.put("error", errorGobbler); - resultMap.put("process", proc); - return resultMap; - } - - /** - * 通过解析参数生成可执行的命令行字符串; - * name:应用名;input:接收地址;output:推送地址;fmt:视频格式;fps:视频帧率;rs:视频分辨率;disableAudio:是否开启音频 - * - * @param paramMap - * @throws Exception - * @return 命令行字符串 - */ - protected String getComm4Map(Map paramMap) throws Exception - { - - if (paramMap.containsKey("ffmpegPath")) - { - StringBuilder comm = new StringBuilder(paramMap.get("ffmpegPath") + " -i "); - // -i:输入流地址或者文件绝对地址 - - // 是否有必输项:输入地址,输出地址,应用名 - if (paramMap.containsKey("input") && paramMap.containsKey("output") - && paramMap.containsKey("appName")) - { - comm.append(paramMap.get("input")).append(" "); - // -f :转换格式,默认flv - comm.append(" -f ").append(paramMap.containsKey("fmt") ? paramMap.get("fmt") : "flv").append(" "); - // -r :帧率,默认25 - comm.append("-r ").append(paramMap.containsKey("fps") ? paramMap.get("fps") : "30").append(" "); - // -s 分辨率 默认是原分辨率 - comm.append("-s ").append(paramMap.containsKey("rs") ? paramMap.get("rs") : "").append(" "); - // -an 禁用音频 - comm.append("-an ").append(paramMap.containsKey("disableAudio") && ("true".equals(paramMap.get("disableAudio"))) ? "-an" : "").append(" "); - // 输出地址 - comm.append(paramMap.get("output")); - // 发布的应用名 - comm.append(paramMap.get("appName")); - // 一个视频源,可以有多个输出,第二个输出为拷贝源视频输出,不改变视频的各项参数并且命名为应用名+HD - comm.append(" ").append(" -vcodec copy -f flv -an ").append(paramMap.get("output")).append(paramMap.get("appName")).append("HD"); - return comm.toString(); - } - } - else - { - throw new Exception("重大错误:必输项不能为空!"); - } - return null; - } + /* + * "ffmpeg -i "+ + * "rtsp://admin:admin@192.168.2.236:37779/cam/realmonitor?channel=1&subtype=0 " + * + " -f flv -r 25 -s 640x360 -an" + " rtmp://192.168.30.21/live/test" + * 推送流格式: + * name:应用名;input:接收地址;output:推送地址;fmt:视频格式;fps:视频帧率;rs:视频分辨率 + * 是否开启音频 + */ + /** + * 通过解析参数生成可执行的命令行字符串; + * name:应用名;input:接收地址;output:推送地址;fmt:视频格式;fps:视频帧率;rs:视频分辨率 + * "ffmpeg -i rtsp://admin:admin@192.168.2.236:37779/cam/realmonitor?channel=1&subtype=0 -f flv -r 25 -s 640x360 -an rtmp://192.168.30.21/live/test" + * @param paramMap + * @throws Exception + * @return 命令行字符串 + */ + protected String getComm4Map(Map paramMap) throws Exception{ + try{ + if (paramMap.containsKey("ffmpegPath")) { + String ffmpegPath = (String) paramMap.get("ffmpegPath"); + // -i:输入流地址或者文件绝对地址 + StringBuilder comm = new StringBuilder(ffmpegPath + " -i "); + // 是否有必输项:输入地址,输出地址,应用名,twoPart:0-推一个元码流;1-推一个自定义推流;2-推两个流(一个是自定义,一个是元码) + if (paramMap.containsKey("input") && paramMap.containsKey("output") && paramMap.containsKey("appName")&& paramMap.containsKey("twoPart")) { + String input = (String) paramMap.get("input"); + String output = (String) paramMap.get("output"); + String appName = (String) paramMap.get("appName"); + String twoPart = (String) paramMap.get("twoPart"); + String codec=(String) paramMap.get("codec"); + //默认h264解码 + codec=(codec==null?"h264":(String) paramMap.get("codec")); + // 输入地址 + comm.append(input); + // 当twoPart为0时,只推一个元码流 + if ("0".equals(twoPart)) { + comm.append(" -vcodec "+codec+" -f flv -an "+output + appName); + }else{ + // -f :转换格式,默认flv + if (paramMap.containsKey("fmt")) { + String fmt = (String) paramMap.get("fmt"); + comm.append(" -f " + fmt); + } + // -r :帧率,默认25;-g :帧间隔 + if (paramMap.containsKey("fps")) { + String fps = (String) paramMap.get("fps"); + comm.append(" -r " + fps); + comm.append(" -g " + fps); + } + // -s 分辨率 默认是原分辨率 + if (paramMap.containsKey("rs")) { + String rs = (String) paramMap.get("rs"); + comm.append(" -s " + rs); + } + // 输出地址+发布的应用名 + comm.append(" -an "+output + appName); + // 当twoPart为2时推两个流,一个自定义流,一个元码流 + if ("2".equals(twoPart)) { + // 一个视频源,可以有多个输出,第二个输出为拷贝源视频输出,不改变视频的各项参数并且命名为应用名+HD + comm.append(" -vcodec copy -f flv -an ").append(output +appName+ "HD"); + } + } + return comm.toString(); + } + } + }catch(Exception e){ + throw e; + } + return null; + } } -- GitLab