Authored by 盖剑秋

Fix bugs and add new SDK from Tencent.

@@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
29 2E5FA8941D06DB2F00920FB4 /* YH_ChannelCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E5FA8931D06DB2F00920FB4 /* YH_ChannelCell.m */; }; 29 2E5FA8941D06DB2F00920FB4 /* YH_ChannelCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E5FA8931D06DB2F00920FB4 /* YH_ChannelCell.m */; };
30 2E64AB941D08099E004307A3 /* launchimage1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2E64AB921D08099E004307A3 /* launchimage1@2x.png */; }; 30 2E64AB941D08099E004307A3 /* launchimage1@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2E64AB921D08099E004307A3 /* launchimage1@2x.png */; };
31 2E64AB951D08099E004307A3 /* launchimage1@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2E64AB931D08099E004307A3 /* launchimage1@3x.png */; }; 31 2E64AB951D08099E004307A3 /* launchimage1@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2E64AB931D08099E004307A3 /* launchimage1@3x.png */; };
  32 + 2E6A3D9D1D18D407001A0E59 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E6A3D9C1D18D406001A0E59 /* libstdc++.tbd */; };
32 2EA13A2A1D05733B0037C9EB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA139F51D05733B0037C9EB /* AppDelegate.m */; }; 33 2EA13A2A1D05733B0037C9EB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA139F51D05733B0037C9EB /* AppDelegate.m */; };
33 2EA13A2B1D05733B0037C9EB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2EA139F61D05733B0037C9EB /* Assets.xcassets */; }; 34 2EA13A2B1D05733B0037C9EB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2EA139F61D05733B0037C9EB /* Assets.xcassets */; };
34 2EA13A2C1D05733B0037C9EB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2EA139F71D05733B0037C9EB /* LaunchScreen.storyboard */; }; 35 2EA13A2C1D05733B0037C9EB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2EA139F71D05733B0037C9EB /* LaunchScreen.storyboard */; };
@@ -36,7 +37,6 @@ @@ -36,7 +37,6 @@
36 2EA13A2E1D05733B0037C9EB /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2EA139FB1D05733B0037C9EB /* Info.plist */; }; 37 2EA13A2E1D05733B0037C9EB /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2EA139FB1D05733B0037C9EB /* Info.plist */; };
37 2EA13A2F1D05733B0037C9EB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA139FC1D05733B0037C9EB /* main.m */; }; 38 2EA13A2F1D05733B0037C9EB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA139FC1D05733B0037C9EB /* main.m */; };
38 2EA13A301D05733B0037C9EB /* PlayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA139FE1D05733B0037C9EB /* PlayController.m */; }; 39 2EA13A301D05733B0037C9EB /* PlayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA139FE1D05733B0037C9EB /* PlayController.m */; };
39 - 2EA13A311D05733B0037C9EB /* PublishController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EA13A001D05733B0037C9EB /* PublishController.m */; };  
40 2EA13A321D05733B0037C9EB /* adjust.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A021D05733B0037C9EB /* adjust.png */; }; 40 2EA13A321D05733B0037C9EB /* adjust.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A021D05733B0037C9EB /* adjust.png */; };
41 2EA13A331D05733B0037C9EB /* background@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A031D05733B0037C9EB /* background@2x.jpg */; }; 41 2EA13A331D05733B0037C9EB /* background@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A031D05733B0037C9EB /* background@2x.jpg */; };
42 2EA13A341D05733B0037C9EB /* beauty.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A041D05733B0037C9EB /* beauty.png */; }; 42 2EA13A341D05733B0037C9EB /* beauty.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A041D05733B0037C9EB /* beauty.png */; };
@@ -72,7 +72,6 @@ @@ -72,7 +72,6 @@
72 2EA13A541D05733B0037C9EB /* tab.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A241D05733B0037C9EB /* tab.png */; }; 72 2EA13A541D05733B0037C9EB /* tab.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A241D05733B0037C9EB /* tab.png */; };
73 2EA13A551D05733B0037C9EB /* tab2.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A251D05733B0037C9EB /* tab2.png */; }; 73 2EA13A551D05733B0037C9EB /* tab2.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A251D05733B0037C9EB /* tab2.png */; };
74 2EA13A561D05733B0037C9EB /* white.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A261D05733B0037C9EB /* white.png */; }; 74 2EA13A561D05733B0037C9EB /* white.png in Resources */ = {isa = PBXBuildFile; fileRef = 2EA13A261D05733B0037C9EB /* white.png */; };
75 - 2EA13A571D05733B0037C9EB /* ScanQRController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2EA13A281D05733B0037C9EB /* ScanQRController.mm */; };  
76 2EA13A5B1D0573AB0037C9EB /* TXRTMPSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2EA13A591D05736B0037C9EB /* TXRTMPSDK.framework */; }; 75 2EA13A5B1D0573AB0037C9EB /* TXRTMPSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2EA13A591D05736B0037C9EB /* TXRTMPSDK.framework */; };
77 2EEAD4BE1D112D04003EE0E9 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EEAD4BB1D112D04003EE0E9 /* GCDAsyncSocket.m */; }; 76 2EEAD4BE1D112D04003EE0E9 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EEAD4BB1D112D04003EE0E9 /* GCDAsyncSocket.m */; };
78 2EEAD4BF1D112D04003EE0E9 /* GCDAsyncSocket+SocketHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EEAD4BD1D112D04003EE0E9 /* GCDAsyncSocket+SocketHandler.m */; }; 77 2EEAD4BF1D112D04003EE0E9 /* GCDAsyncSocket+SocketHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EEAD4BD1D112D04003EE0E9 /* GCDAsyncSocket+SocketHandler.m */; };
@@ -104,6 +103,7 @@ @@ -104,6 +103,7 @@
104 2E5FA8931D06DB2F00920FB4 /* YH_ChannelCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YH_ChannelCell.m; sourceTree = "<group>"; }; 103 2E5FA8931D06DB2F00920FB4 /* YH_ChannelCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YH_ChannelCell.m; sourceTree = "<group>"; };
105 2E64AB921D08099E004307A3 /* launchimage1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "launchimage1@2x.png"; sourceTree = "<group>"; }; 104 2E64AB921D08099E004307A3 /* launchimage1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "launchimage1@2x.png"; sourceTree = "<group>"; };
106 2E64AB931D08099E004307A3 /* launchimage1@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "launchimage1@3x.png"; sourceTree = "<group>"; }; 105 2E64AB931D08099E004307A3 /* launchimage1@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "launchimage1@3x.png"; sourceTree = "<group>"; };
  106 + 2E6A3D9C1D18D406001A0E59 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
107 2EA139F41D05733B0037C9EB /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; 107 2EA139F41D05733B0037C9EB /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
108 2EA139F51D05733B0037C9EB /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; 108 2EA139F51D05733B0037C9EB /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
109 2EA139F61D05733B0037C9EB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 109 2EA139F61D05733B0037C9EB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -113,8 +113,6 @@ @@ -113,8 +113,6 @@
113 2EA139FC1D05733B0037C9EB /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; 113 2EA139FC1D05733B0037C9EB /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
114 2EA139FD1D05733B0037C9EB /* PlayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayController.h; sourceTree = "<group>"; }; 114 2EA139FD1D05733B0037C9EB /* PlayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayController.h; sourceTree = "<group>"; };
115 2EA139FE1D05733B0037C9EB /* PlayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayController.m; sourceTree = "<group>"; }; 115 2EA139FE1D05733B0037C9EB /* PlayController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayController.m; sourceTree = "<group>"; };
116 - 2EA139FF1D05733B0037C9EB /* PublishController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublishController.h; sourceTree = "<group>"; };  
117 - 2EA13A001D05733B0037C9EB /* PublishController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PublishController.m; sourceTree = "<group>"; };  
118 2EA13A021D05733B0037C9EB /* adjust.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = adjust.png; sourceTree = "<group>"; }; 116 2EA13A021D05733B0037C9EB /* adjust.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = adjust.png; sourceTree = "<group>"; };
119 2EA13A031D05733B0037C9EB /* background@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "background@2x.jpg"; sourceTree = "<group>"; }; 117 2EA13A031D05733B0037C9EB /* background@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "background@2x.jpg"; sourceTree = "<group>"; };
120 2EA13A041D05733B0037C9EB /* beauty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = beauty.png; sourceTree = "<group>"; }; 118 2EA13A041D05733B0037C9EB /* beauty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = beauty.png; sourceTree = "<group>"; };
@@ -150,8 +148,6 @@ @@ -150,8 +148,6 @@
150 2EA13A241D05733B0037C9EB /* tab.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab.png; sourceTree = "<group>"; }; 148 2EA13A241D05733B0037C9EB /* tab.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab.png; sourceTree = "<group>"; };
151 2EA13A251D05733B0037C9EB /* tab2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab2.png; sourceTree = "<group>"; }; 149 2EA13A251D05733B0037C9EB /* tab2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab2.png; sourceTree = "<group>"; };
152 2EA13A261D05733B0037C9EB /* white.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = white.png; sourceTree = "<group>"; }; 150 2EA13A261D05733B0037C9EB /* white.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = white.png; sourceTree = "<group>"; };
153 - 2EA13A271D05733B0037C9EB /* ScanQRController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanQRController.h; sourceTree = "<group>"; };  
154 - 2EA13A281D05733B0037C9EB /* ScanQRController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScanQRController.mm; sourceTree = "<group>"; };  
155 2EA13A591D05736B0037C9EB /* TXRTMPSDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TXRTMPSDK.framework; path = YohoLive/TXRTMPSDK.framework; sourceTree = "<group>"; }; 151 2EA13A591D05736B0037C9EB /* TXRTMPSDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TXRTMPSDK.framework; path = YohoLive/TXRTMPSDK.framework; sourceTree = "<group>"; };
156 2EEAD4BA1D112D04003EE0E9 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = "<group>"; }; 152 2EEAD4BA1D112D04003EE0E9 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = "<group>"; };
157 2EEAD4BB1D112D04003EE0E9 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = "<group>"; }; 153 2EEAD4BB1D112D04003EE0E9 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = "<group>"; };
@@ -170,6 +166,7 @@ @@ -170,6 +166,7 @@
170 isa = PBXFrameworksBuildPhase; 166 isa = PBXFrameworksBuildPhase;
171 buildActionMask = 2147483647; 167 buildActionMask = 2147483647;
172 files = ( 168 files = (
  169 + 2E6A3D9D1D18D407001A0E59 /* libstdc++.tbd in Frameworks */,
173 2EA13A5B1D0573AB0037C9EB /* TXRTMPSDK.framework in Frameworks */, 170 2EA13A5B1D0573AB0037C9EB /* TXRTMPSDK.framework in Frameworks */,
174 EFF834691CEB638B00345113 /* CoreTelephony.framework in Frameworks */, 171 EFF834691CEB638B00345113 /* CoreTelephony.framework in Frameworks */,
175 A09B25771CE57CAF00E68E28 /* SystemConfiguration.framework in Frameworks */, 172 A09B25771CE57CAF00E68E28 /* SystemConfiguration.framework in Frameworks */,
@@ -183,6 +180,7 @@ @@ -183,6 +180,7 @@
183 14DBC8FCBFC905B673B5534D /* Frameworks */ = { 180 14DBC8FCBFC905B673B5534D /* Frameworks */ = {
184 isa = PBXGroup; 181 isa = PBXGroup;
185 children = ( 182 children = (
  183 + 2E6A3D9C1D18D406001A0E59 /* libstdc++.tbd */,
186 A2F123EA9030672A0EFEF6CC /* libPods.a */, 184 A2F123EA9030672A0EFEF6CC /* libPods.a */,
187 ); 185 );
188 name = Frameworks; 186 name = Frameworks;
@@ -222,11 +220,7 @@ @@ -222,11 +220,7 @@
222 2EA139FC1D05733B0037C9EB /* main.m */, 220 2EA139FC1D05733B0037C9EB /* main.m */,
223 2EA139FD1D05733B0037C9EB /* PlayController.h */, 221 2EA139FD1D05733B0037C9EB /* PlayController.h */,
224 2EA139FE1D05733B0037C9EB /* PlayController.m */, 222 2EA139FE1D05733B0037C9EB /* PlayController.m */,
225 - 2EA139FF1D05733B0037C9EB /* PublishController.h */,  
226 - 2EA13A001D05733B0037C9EB /* PublishController.m */,  
227 2EA13A011D05733B0037C9EB /* resource */, 223 2EA13A011D05733B0037C9EB /* resource */,
228 - 2EA13A271D05733B0037C9EB /* ScanQRController.h */,  
229 - 2EA13A281D05733B0037C9EB /* ScanQRController.mm */,  
230 ); 224 );
231 path = YohoLive; 225 path = YohoLive;
232 sourceTree = "<group>"; 226 sourceTree = "<group>";
@@ -501,9 +495,7 @@ @@ -501,9 +495,7 @@
501 2E2E2D791D0E8B290067D118 /* YH_HTTPRequestSerializer.m in Sources */, 495 2E2E2D791D0E8B290067D118 /* YH_HTTPRequestSerializer.m in Sources */,
502 2E2E2D7C1D0E8BD90067D118 /* NSString+M16String.m in Sources */, 496 2E2E2D7C1D0E8BD90067D118 /* NSString+M16String.m in Sources */,
503 2EA13A2F1D05733B0037C9EB /* main.m in Sources */, 497 2EA13A2F1D05733B0037C9EB /* main.m in Sources */,
504 - 2EA13A571D05733B0037C9EB /* ScanQRController.mm in Sources */,  
505 2E5FA8911D06D2FD00920FB4 /* YH_ChannelModel.m in Sources */, 498 2E5FA8911D06D2FD00920FB4 /* YH_ChannelModel.m in Sources */,
506 - 2EA13A311D05733B0037C9EB /* PublishController.m in Sources */,  
507 2E5FA8941D06DB2F00920FB4 /* YH_ChannelCell.m in Sources */, 499 2E5FA8941D06DB2F00920FB4 /* YH_ChannelCell.m in Sources */,
508 2E4D5FC21D057C6100D508BB /* YH_RootViewController.m in Sources */, 500 2E4D5FC21D057C6100D508BB /* YH_RootViewController.m in Sources */,
509 2EA13A2A1D05733B0037C9EB /* AppDelegate.m in Sources */, 501 2EA13A2A1D05733B0037C9EB /* AppDelegate.m in Sources */,
@@ -8,7 +8,6 @@ @@ -8,7 +8,6 @@
8 8
9 #import "AppDelegate.h" 9 #import "AppDelegate.h"
10 #include "PlayController.h" 10 #include "PlayController.h"
11 -#include "PublishController.h"  
12 #ifdef CRASH_REPORT 11 #ifdef CRASH_REPORT
13 #import <Bugly/Bugly.h> 12 #import <Bugly/Bugly.h>
14 #endif 13 #endif
@@ -18,19 +18,23 @@ @@ -18,19 +18,23 @@
18 #import "AFHTTPSessionManager.h" 18 #import "AFHTTPSessionManager.h"
19 #import "YH_HTTPRequestSerializer.h" 19 #import "YH_HTTPRequestSerializer.h"
20 #import "GCDAsyncSocket+SocketHandler.h" 20 #import "GCDAsyncSocket+SocketHandler.h"
  21 +#import "AFNetworkReachabilityManager.h"
21 22
22 -static const NSInteger socketMaxRetryCount = 3; 23 +//static const NSInteger socketMaxRetryCount = 3;
23 24
24 // 清晰度定义 25 // 清晰度定义
25 #define HD_LEVEL_720P 1 // 1280 * 720 26 #define HD_LEVEL_720P 1 // 1280 * 720
26 -#define HD_LEVEL_640 2 // 640 * 360  
27 -#define HD_LEVEL_640_PLUS 3 // 640 * 360 且开启码率自适应 27 +#define HD_LEVEL_540P 2 // 960 * 560
  28 +#define HD_LEVEL_360P 3 // 640 * 360
  29 +#define HD_LEVEL_360_PLUS 4 // 640 * 360 且开启码率自适应
28 30
29 #define RTMP_PUBLISH_URL @"rtmp://2718.livepush.myqcloud.com/live/2718_01973243308211e6a2cba4dcbef5e35a?bizid=2718" //调试期间您可以修改之以避免输入地址的麻烦 31 #define RTMP_PUBLISH_URL @"rtmp://2718.livepush.myqcloud.com/live/2718_01973243308211e6a2cba4dcbef5e35a?bizid=2718" //调试期间您可以修改之以避免输入地址的麻烦
30 32
31 #define SOCKET_LIVE_HOST @"123.206.65.220" 33 #define SOCKET_LIVE_HOST @"123.206.65.220"
32 #define SOCKET_LIVE_PORT 9512 34 #define SOCKET_LIVE_PORT 9512
33 35
  36 +#define SOCKET_COMMAND @"cmd"
  37 +
34 @interface YH_RootViewController ()<TXLivePushListener, UITableViewDelegate, UITableViewDataSource> 38 @interface YH_RootViewController ()<TXLivePushListener, UITableViewDelegate, UITableViewDataSource>
35 39
36 @property (nonatomic, strong) TXLivePush *livePush; 40 @property (nonatomic, strong) TXLivePush *livePush;
@@ -59,6 +63,7 @@ static const NSInteger socketMaxRetryCount = 3; @@ -59,6 +63,7 @@ static const NSInteger socketMaxRetryCount = 3;
59 @property (nonatomic, strong) UISlider *sdWhitening; 63 @property (nonatomic, strong) UISlider *sdWhitening;
60 @property (nonatomic, strong) UIView *vHD; 64 @property (nonatomic, strong) UIView *vHD;
61 @property (nonatomic, strong) UIButton *radioBtnHD; 65 @property (nonatomic, strong) UIButton *radioBtnHD;
  66 +@property (nonatomic, strong) UIButton *radioBtnHD2;
62 @property (nonatomic, strong) UIButton *radioBtnSD; 67 @property (nonatomic, strong) UIButton *radioBtnSD;
63 @property (nonatomic, strong) UIButton *radioBtnAUTO; 68 @property (nonatomic, strong) UIButton *radioBtnAUTO;
64 69
@@ -150,14 +155,14 @@ static const NSInteger socketMaxRetryCount = 3; @@ -150,14 +155,14 @@ static const NSInteger socketMaxRetryCount = 3;
150 // if ([responseObject isKindOfClass:[NSDictionary class]]) { 155 // if ([responseObject isKindOfClass:[NSDictionary class]]) {
151 // id data = responseObject[@"data"]; 156 // id data = responseObject[@"data"];
152 // if (![data isKindOfClass:[NSArray class]]) { 157 // if (![data isKindOfClass:[NSArray class]]) {
153 -// [self toastTip:@"data formmat error"]; 158 +// [self toastTip:@"没有可用直播间"];
154 // return; 159 // return;
155 // } 160 // }
156 // NSMutableArray *tempAry = @[].mutableCopy; 161 // NSMutableArray *tempAry = @[].mutableCopy;
157 // [data enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 162 // [data enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
158 // if (![obj isKindOfClass:[NSDictionary class]]) { 163 // if (![obj isKindOfClass:[NSDictionary class]]) {
159 // *stop = YES; 164 // *stop = YES;
160 -// [self toastTip:@"data formmat error"]; 165 +// [self toastTip:@"没有可用直播间"];
161 // } 166 // }
162 // YH_ChannelModel *model = [YH_ChannelModel new]; 167 // YH_ChannelModel *model = [YH_ChannelModel new];
163 // model.roomTitle = obj[@"name"]; 168 // model.roomTitle = obj[@"name"];
@@ -209,29 +214,6 @@ static const NSInteger socketMaxRetryCount = 3; @@ -209,29 +214,6 @@ static const NSInteger socketMaxRetryCount = 3;
209 214
210 -(BOOL)startRtmp{ 215 -(BOOL)startRtmp{
211 216
212 - AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];  
213 - manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];  
214 - manager.requestSerializer = [YH_HTTPRequestSerializer new];  
215 - NSURLSessionDataTask *task = [manager  
216 - GET:@"http://newboys.test.yoho.cn/yohoboyins/v4/qcloud/closeLive"  
217 - parameters:@{@"cid":_currentChannel.room?:@"0"}  
218 - progress:^(NSProgress * _Nonnull downloadProgress) {  
219 - NSLog(@"aaaa");  
220 - }  
221 - success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {  
222 - NSLog(@"bbbb%@",responseObject);  
223 - }  
224 - failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  
225 - NSLog(@"ccc");  
226 - }];  
227 -  
228 - NSLog(@"%@",task.originalRequest.URL.absoluteString);  
229 -  
230 - _totalTime = 0;  
231 - _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateInfoView) userInfo:nil repeats:YES];  
232 - [_timer fire];  
233 -  
234 - [self clearLog];  
235 [UIApplication sharedApplication].idleTimerDisabled = YES;//stop lock screen. 217 [UIApplication sharedApplication].idleTimerDisabled = YES;//stop lock screen.
236 NSString* rtmpUrl = _currentChannel.roomURL; 218 NSString* rtmpUrl = _currentChannel.roomURL;
237 if (rtmpUrl.length == 0) { 219 if (rtmpUrl.length == 0) {
@@ -266,26 +248,8 @@ static const NSInteger socketMaxRetryCount = 3; @@ -266,26 +248,8 @@ static const NSInteger socketMaxRetryCount = 3;
266 248
267 249
268 - (void)stopRtmp { 250 - (void)stopRtmp {
269 - AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];  
270 - manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];  
271 - manager.requestSerializer = [YH_HTTPRequestSerializer new];  
272 -  
273 - NSURLSessionDataTask *task = [manager  
274 - GET:@"http://newboys.test.yoho.cn/yohoboyins/v4/qcloud/closeLive"  
275 - parameters:@{@"cid":_currentChannel.room?:@"0"}  
276 - progress:NULL  
277 - success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {  
278 - NSLog(@"bbbb%@",responseObject);  
279 - }  
280 - failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {  
281 - NSLog(@"ccc");  
282 - }];  
283 - NSLog(@"%@",task.originalRequest.URL.absoluteString);  
284 -  
285 - [self socketSendEndNotify];//通知结束。  
286 251
287 [UIApplication sharedApplication].idleTimerDisabled = NO; 252 [UIApplication sharedApplication].idleTimerDisabled = NO;
288 - [_timer invalidate];  
289 if(_livePush) 253 if(_livePush)
290 { 254 {
291 [_livePush stopPush]; 255 [_livePush stopPush];
@@ -312,7 +276,8 @@ static const NSInteger socketMaxRetryCount = 3; @@ -312,7 +276,8 @@ static const NSInteger socketMaxRetryCount = 3;
312 276
313 dispatch_async(dispatch_get_main_queue(), ^{ 277 dispatch_async(dispatch_get_main_queue(), ^{
314 if (EvtID == PUSH_ERR_NET_DISCONNECT) { 278 if (EvtID == PUSH_ERR_NET_DISCONNECT) {
315 - [self liveButtonPressed:_liveButton]; 279 + [self startRtmp];//不停的重试,只要在用户点击结束之前,都要进行重新连接操作。
  280 +// [self liveButtonPressed:_liveButton];
316 } 281 }
317 long long time = [(NSNumber*)[dict valueForKey:EVT_TIME] longLongValue]; 282 long long time = [(NSNumber*)[dict valueForKey:EVT_TIME] longLongValue];
318 int mil = time % 1000; 283 int mil = time % 1000;
@@ -364,10 +329,9 @@ static const NSInteger socketMaxRetryCount = 3; @@ -364,10 +329,9 @@ static const NSInteger socketMaxRetryCount = 3;
364 @"room":_currentChannel.room?:@"666", 329 @"room":_currentChannel.room?:@"666",
365 @"msg":@(666),//结束时的瞬时在线人数 330 @"msg":@(666),//结束时的瞬时在线人数
366 @"videoLen":_timeLabel.text, 331 @"videoLen":_timeLabel.text,
  332 + @"uid":@""
367 }; 333 };
368 -  
369 - [_socket writeDataWithParams:params tag:1];  
370 - _socketTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(socketSendEndNotify) userInfo:nil repeats:YES]; 334 + [_socket writeDataWithParams:params tag:2];
371 } else { 335 } else {
372 [self connectSocket]; 336 [self connectSocket];
373 } 337 }
@@ -380,12 +344,20 @@ static const NSInteger socketMaxRetryCount = 3; @@ -380,12 +344,20 @@ static const NSInteger socketMaxRetryCount = 3;
380 344
381 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port 345 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
382 { 346 {
383 - _currentRetryCount = 0;  
384 -  
385 - DLog(@"socket connect success!");  
386 -  
387 - [self socketSendEndNotify];  
388 347
  348 + dispatch_async(dispatch_get_main_queue(), ^{
  349 + _currentRetryCount = 0;
  350 + DLog(@"socket connect success!");
  351 + NSDictionary *params = @{@"cmd":@(1),
  352 + @"uid":@"",
  353 + @"room":_currentChannel.room?:@"666",
  354 + @"name":@"",
  355 + @"avatar":@""
  356 + };
  357 +
  358 + [_socket writeDataWithParams:params tag:1];
  359 + });
  360 +
389 } 361 }
390 362
391 - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{ 363 - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
@@ -400,14 +372,36 @@ static const NSInteger socketMaxRetryCount = 3; @@ -400,14 +372,36 @@ static const NSInteger socketMaxRetryCount = 3;
400 - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag 372 - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
401 { 373 {
402 dispatch_async(dispatch_get_main_queue(), ^{ 374 dispatch_async(dispatch_get_main_queue(), ^{
403 - DLog(@"通知结束成功");  
404 - [self toastTip:@"通知结束成功"];  
405 - [sock disconnect];  
406 - _inPushing = NO;  
407 - [_socketTimer invalidate]; 375 + if (tag == 1) {//登录成功了之后才继续后面的。。。。
  376 + [self socketSendEndNotify];
  377 + _socketTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(socketSendEndNotify) userInfo:nil repeats:YES];
  378 + }
408 }); 379 });
409 } 380 }
410 381
  382 +- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
  383 +{
  384 + dispatch_async(dispatch_get_main_queue(), ^{
  385 + NSError *error = nil;
  386 + NSDictionary *resDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
  387 + DLog(@"=======%@",resDic);
  388 + if (resDic && [resDic.allKeys containsObject:SOCKET_COMMAND]) {
  389 + int cmd = [[resDic objectForKey:SOCKET_COMMAND] intValue];
  390 + if (cmd == 12) {
  391 + dispatch_async(dispatch_get_main_queue(), ^{
  392 + DLog(@"通知结束成功");
  393 + [self toastTip:@"通知结束成功"];
  394 + [sock disconnect];
  395 + _inPushing = NO;
  396 + [_socketTimer invalidate];
  397 + });
  398 + }
  399 + }
  400 + });
  401 +
  402 +}
  403 +
  404 +
411 #pragma mark - Button actions... 405 #pragma mark - Button actions...
412 406
413 - (void)hdPressed:(UIButton *)sender { 407 - (void)hdPressed:(UIButton *)sender {
@@ -473,6 +467,7 @@ static const NSInteger socketMaxRetryCount = 3; @@ -473,6 +467,7 @@ static const NSInteger socketMaxRetryCount = 3;
473 } 467 }
474 468
475 - (void)channelPressed:(UIButton *)sender { 469 - (void)channelPressed:(UIButton *)sender {
  470 +
476 if (!_channels.count) { 471 if (!_channels.count) {
477 [self loadChannelData]; 472 [self loadChannelData];
478 [self toastTip:@"房间加载失败,稍后再试!"]; 473 [self toastTip:@"房间加载失败,稍后再试!"];
@@ -517,12 +512,65 @@ static const NSInteger socketMaxRetryCount = 3; @@ -517,12 +512,65 @@ static const NSInteger socketMaxRetryCount = 3;
517 } 512 }
518 513
519 - (void)liveButtonPressed:(UIButton *)sender { 514 - (void)liveButtonPressed:(UIButton *)sender {
  515 +
  516 + if (!_currentChannel) {
  517 + [self toastTip:@"请先选择房间"];
  518 + return;
  519 + }
  520 +
520 [self hideAllToolView]; 521 [self hideAllToolView];
521 _liveButton.selected = !_liveButton.selected; 522 _liveButton.selected = !_liveButton.selected;
522 if (_liveButton.selected) { 523 if (_liveButton.selected) {
523 - [self startRtmp]; 524 + if ([self startRtmp]) {
  525 + [self toastTip:@"开始直播"];
  526 + AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  527 + manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];
  528 + manager.requestSerializer = [YH_HTTPRequestSerializer new];
  529 + NSURLSessionDataTask *task = [manager
  530 + GET:@"http://newboys.test.yoho.cn/yohoboyins/v4/qcloud/startLive"
  531 + parameters:@{@"cid":_currentChannel.room?:@"0"}
  532 + progress:^(NSProgress * _Nonnull downloadProgress) {
  533 + NSLog(@"aaaa");
  534 + }
  535 + success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  536 + NSLog(@"bbbb%@",responseObject);
  537 + }
  538 + failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  539 + NSLog(@"ccc");
  540 + }];
  541 +
  542 + NSLog(@"%@",task.originalRequest.URL.absoluteString);
  543 +
  544 + _totalTime = 0;
  545 + _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateInfoView) userInfo:nil repeats:YES];
  546 + [_timer fire];
  547 +
  548 + [self clearLog];
  549 +
  550 + }
524 } else { 551 } else {
525 [self stopRtmp]; 552 [self stopRtmp];
  553 + AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  554 + manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];
  555 + manager.requestSerializer = [YH_HTTPRequestSerializer new];
  556 +
  557 + NSLog(@"%@----%@",_currentChannel.room,_currentChannel.cid);
  558 +
  559 + NSURLSessionDataTask *task = [manager
  560 + GET:@"http://newboys.test.yoho.cn/yohoboyins/v4/qcloud/closeLive"
  561 + parameters:@{@"cid":_currentChannel.room?:@"0"}
  562 + progress:NULL
  563 + success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  564 + NSLog(@"bbbb%@",responseObject);
  565 + }
  566 + failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  567 + NSLog(@"ccc");
  568 + }];
  569 + NSLog(@"%@",task.originalRequest.URL.absoluteString);
  570 +
  571 + [_timer invalidate];
  572 +
  573 + [self socketSendEndNotify];//通知结束。
526 } 574 }
527 } 575 }
528 576
@@ -642,27 +690,34 @@ static const NSInteger socketMaxRetryCount = 3; @@ -642,27 +690,34 @@ static const NSInteger socketMaxRetryCount = 3;
642 txtHD.frame = CGRectMake(0, 0, size.width, 50); 690 txtHD.frame = CGRectMake(0, 0, size.width, 50);
643 [txtHD setText:@"清晰度"]; 691 [txtHD setText:@"清晰度"];
644 [txtHD setFont:[UIFont fontWithName:@"" size:14]]; 692 [txtHD setFont:[UIFont fontWithName:@"" size:14]];
  693 + txtHD.textAlignment = NSTextAlignmentCenter;
645 694
646 [_vHD addSubview:txtHD]; 695 [_vHD addSubview:txtHD];
647 696
648 int gap = 30; 697 int gap = 30;
649 - int width = (size.width - gap*2 - 20) / 3; 698 + int width = (size.width - gap*3 - 20) / 4;
650 _radioBtnHD = [UIButton buttonWithType:UIButtonTypeCustom]; 699 _radioBtnHD = [UIButton buttonWithType:UIButtonTypeCustom];
651 _radioBtnHD.frame = CGRectMake(10, 60, width, 40); 700 _radioBtnHD.frame = CGRectMake(10, 60, width, 40);
652 [_radioBtnHD setTitle:@"720p" forState:UIControlStateNormal]; 701 [_radioBtnHD setTitle:@"720p" forState:UIControlStateNormal];
653 [_radioBtnHD addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside]; 702 [_radioBtnHD addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside];
654 703
  704 + _radioBtnHD2 = [UIButton buttonWithType:UIButtonTypeCustom];
  705 + _radioBtnHD2.frame = CGRectMake(10 + gap + width, 60, width, 40);
  706 + [_radioBtnHD2 setTitle:@"540p" forState:UIControlStateNormal];
  707 + [_radioBtnHD2 addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside];
  708 +
655 _radioBtnSD = [UIButton buttonWithType:UIButtonTypeCustom]; 709 _radioBtnSD = [UIButton buttonWithType:UIButtonTypeCustom];
656 - _radioBtnSD.frame = CGRectMake(10 + gap + width, 60, width, 40);  
657 - [_radioBtnSD setTitle:@"640" forState:UIControlStateNormal]; 710 + _radioBtnSD.frame = CGRectMake(10 + (gap + width)*2, 60, width, 40);
  711 + [_radioBtnSD setTitle:@"360p" forState:UIControlStateNormal];
658 [_radioBtnSD addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside]; 712 [_radioBtnSD addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside];
659 713
660 _radioBtnAUTO = [UIButton buttonWithType:UIButtonTypeCustom]; 714 _radioBtnAUTO = [UIButton buttonWithType:UIButtonTypeCustom];
661 _radioBtnAUTO.frame = CGRectMake(size.width - 10 - width, 60, width, 40); 715 _radioBtnAUTO.frame = CGRectMake(size.width - 10 - width, 60, width, 40);
662 - [_radioBtnAUTO setTitle:@"640+" forState:UIControlStateNormal]; 716 + [_radioBtnAUTO setTitle:@"360+" forState:UIControlStateNormal];
663 [_radioBtnAUTO addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside]; 717 [_radioBtnAUTO addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside];
664 718
665 [_vHD addSubview:_radioBtnHD]; 719 [_vHD addSubview:_radioBtnHD];
  720 + [_vHD addSubview:_radioBtnHD2];
666 [_vHD addSubview:_radioBtnSD]; 721 [_vHD addSubview:_radioBtnSD];
667 [_vHD addSubview:_radioBtnAUTO]; 722 [_vHD addSubview:_radioBtnAUTO];
668 723
@@ -670,7 +725,7 @@ static const NSInteger socketMaxRetryCount = 3; @@ -670,7 +725,7 @@ static const NSInteger socketMaxRetryCount = 3;
670 [self.view addSubview: _vHD]; 725 [self.view addSubview: _vHD];
671 726
672 // DEMO 默认采用 640 * 360 分辨率, 避免在4S等机型上出现编码不足 727 // DEMO 默认采用 640 * 360 分辨率, 避免在4S等机型上出现编码不足
673 - int _hd_level = [self isSuitableMachine] ? HD_LEVEL_720P : HD_LEVEL_640; 728 + int _hd_level = [self isSuitableMachine] ? HD_LEVEL_720P : HD_LEVEL_360_PLUS;
674 [self setHDUI:_hd_level]; 729 [self setHDUI:_hd_level];
675 } 730 }
676 731
@@ -679,34 +734,53 @@ static const NSInteger socketMaxRetryCount = 3; @@ -679,34 +734,53 @@ static const NSInteger socketMaxRetryCount = 3;
679 switch (level) { 734 switch (level) {
680 case HD_LEVEL_720P: 735 case HD_LEVEL_720P:
681 [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal]; 736 [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];
  737 + [_radioBtnHD2 setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
682 [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal]; 738 [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
683 [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal]; 739 [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
684 [_radioBtnHD setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 740 [_radioBtnHD setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  741 + [_radioBtnHD2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
685 [_radioBtnSD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 742 [_radioBtnSD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
686 [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 743 [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  744 + [_hdButton setTitle:@"高清" forState:UIControlStateNormal];
687 break; 745 break;
688 - case HD_LEVEL_640: 746 + case HD_LEVEL_540P:
689 [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal]; 747 [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  748 + [_radioBtnHD2 setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];
  749 + [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  750 + [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  751 + [_radioBtnHD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  752 + [_radioBtnHD2 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  753 + [_radioBtnSD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  754 + [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  755 + [_hdButton setTitle:@"高清" forState:UIControlStateNormal];
  756 + break;
  757 + case HD_LEVEL_360P:
  758 + [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  759 + [_radioBtnHD2 setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
690 [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal]; 760 [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];
691 [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal]; 761 [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
692 [_radioBtnHD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 762 [_radioBtnHD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  763 + [_radioBtnHD2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
693 [_radioBtnSD setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 764 [_radioBtnSD setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
694 [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 765 [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  766 + [_hdButton setTitle:@"标清" forState:UIControlStateNormal];
695 767
696 break; 768 break;
697 - case HD_LEVEL_640_PLUS: 769 + case HD_LEVEL_360_PLUS:
698 [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal]; 770 [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  771 + [_radioBtnHD2 setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
699 [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal]; 772 [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
700 [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal]; 773 [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];
701 [_radioBtnHD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 774 [_radioBtnHD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  775 + [_radioBtnHD2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
702 [_radioBtnSD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 776 [_radioBtnSD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
703 [_radioBtnAUTO setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 777 [_radioBtnAUTO setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  778 + [_hdButton setTitle:@"普清" forState:UIControlStateNormal];
704 default: 779 default:
705 break; 780 break;
706 } 781 }
707 } 782 }
708 783
709 -  
710 // iphone 6 及以上机型适合开启720p, 否则20帧的帧率可能无法达到, 这种"流畅不足,清晰有余"的效果并不好 784 // iphone 6 及以上机型适合开启720p, 否则20帧的帧率可能无法达到, 这种"流畅不足,清晰有余"的效果并不好
711 -(BOOL) isSuitableMachine 785 -(BOOL) isSuitableMachine
712 { 786 {
@@ -755,27 +829,33 @@ static const NSInteger socketMaxRetryCount = 3; @@ -755,27 +829,33 @@ static const NSInteger socketMaxRetryCount = 3;
755 _config.videoResolution = [self isSuitableMachine ] ? VIDEO_RESOLUTION_1280_720 : VIDEO_RESOLUTION_960_540; 829 _config.videoResolution = [self isSuitableMachine ] ? VIDEO_RESOLUTION_1280_720 : VIDEO_RESOLUTION_960_540;
756 _config.enableAutoBitrate = NO; 830 _config.enableAutoBitrate = NO;
757 [_livePush setConfig:_config]; 831 [_livePush setConfig:_config];
758 -  
759 - } else if ([btn.titleLabel.text isEqualToString:@"640"]) {  
760 - _hd_level = HD_LEVEL_640; 832 + }else if ([btn.titleLabel.text isEqualToString:@"540p"]) {
  833 + _hd_level = HD_LEVEL_540P;
761 834
762 TXLivePushConfig* _config = _livePush.config; 835 TXLivePushConfig* _config = _livePush.config;
763 _config.videoBitratePIN = 800; 836 _config.videoBitratePIN = 800;
  837 + _config.videoResolution = VIDEO_RESOLUTION_960_540;
  838 + _config.enableAutoBitrate = NO;
  839 + [_livePush setConfig:_config];
  840 + }else if ([btn.titleLabel.text isEqualToString:@"360p"]) {
  841 + _hd_level = HD_LEVEL_360P;
  842 +
  843 + TXLivePushConfig* _config = _livePush.config;
  844 + _config.videoBitratePIN = 600;
764 _config.videoResolution = VIDEO_RESOLUTION_640_360; 845 _config.videoResolution = VIDEO_RESOLUTION_640_360;
765 _config.enableAutoBitrate = NO; 846 _config.enableAutoBitrate = NO;
766 [_livePush setConfig:_config]; 847 [_livePush setConfig:_config];
767 848
768 - } else if ([btn.titleLabel.text isEqualToString:@"640+"]) {  
769 - _hd_level = HD_LEVEL_640_PLUS; 849 + } else if ([btn.titleLabel.text isEqualToString:@"360+"]) {
  850 + _hd_level = HD_LEVEL_360_PLUS;
770 851
771 TXLivePushConfig* _config = _livePush.config; 852 TXLivePushConfig* _config = _livePush.config;
772 - _config.videoBitrateMin = 500;  
773 - _config.videoBitrateMax = 1500; 853 + _config.videoBitrateMin = 100;
  854 + _config.videoBitrateMax = 1200;
774 _config.enableAutoBitrate = YES; 855 _config.enableAutoBitrate = YES;
775 _config.videoResolution = VIDEO_RESOLUTION_640_360; 856 _config.videoResolution = VIDEO_RESOLUTION_640_360;
776 [_livePush setConfig:_config]; // 此模式下设置bitrate无效 857 [_livePush setConfig:_config]; // 此模式下设置bitrate无效
777 } 858 }
778 -  
779 [self setHDUI:_hd_level]; 859 [self setHDUI:_hd_level];
780 _vHD.hidden = YES; 860 _vHD.hidden = YES;
781 861
@@ -806,6 +886,7 @@ static const NSInteger socketMaxRetryCount = 3; @@ -806,6 +886,7 @@ static const NSInteger socketMaxRetryCount = 3;
806 [_liveButton setTitle:@"开始直播" forState:UIControlStateNormal]; 886 [_liveButton setTitle:@"开始直播" forState:UIControlStateNormal];
807 [_liveButton setTitle:@"结束直播" forState:UIControlStateSelected]; 887 [_liveButton setTitle:@"结束直播" forState:UIControlStateSelected];
808 _liveButton.titleLabel.font = [UIFont systemFontOfSize:16]; 888 _liveButton.titleLabel.font = [UIFont systemFontOfSize:16];
  889 + [_liveButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
809 [_channelPannel addSubview:_liveButton]; 890 [_channelPannel addSubview:_liveButton];
810 891
811 892
@@ -916,6 +997,7 @@ static const NSInteger socketMaxRetryCount = 3; @@ -916,6 +997,7 @@ static const NSInteger socketMaxRetryCount = 3;
916 [self initEmojiPannel]; 997 [self initEmojiPannel];
917 [self initInfoPannel]; 998 [self initInfoPannel];
918 999
  1000 + UIImage *image = [UIImage imageNamed:@"icon_photoflash"];
919 _fullScreenButton = [UIButton buttonWithType:UIButtonTypeCustom]; 1001 _fullScreenButton = [UIButton buttonWithType:UIButtonTypeCustom];
920 [_fullScreenButton addTarget:self action:@selector(fullScreenPressed:) forControlEvents:UIControlEventTouchUpInside]; 1002 [_fullScreenButton addTarget:self action:@selector(fullScreenPressed:) forControlEvents:UIControlEventTouchUpInside];
921 [_fullScreenButton setImage:[UIImage imageNamed:@"icon_Exit-Full-Screen"] forState:UIControlStateNormal]; 1003 [_fullScreenButton setImage:[UIImage imageNamed:@"icon_Exit-Full-Screen"] forState:UIControlStateNormal];
@@ -1027,6 +1109,8 @@ static const NSInteger socketMaxRetryCount = 3; @@ -1027,6 +1109,8 @@ static const NSInteger socketMaxRetryCount = 3;
1027 return;//正在直播的情况下不得选择另外的房间,否则在通知结束的时候无法保证参数正确。。。 1109 return;//正在直播的情况下不得选择另外的房间,否则在通知结束的时候无法保证参数正确。。。
1028 } 1110 }
1029 _currentChannelIndex = indexPath.row; 1111 _currentChannelIndex = indexPath.row;
  1112 + _currentChannel = _channels[_currentChannelIndex];
  1113 + [_liveButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
1030 [_channelTable reloadData]; 1114 [_channelTable reloadData];
1031 } 1115 }
1032 1116
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <key>CFBundleDevelopmentRegion</key> 5 <key>CFBundleDevelopmentRegion</key>
6 <string>en</string> 6 <string>en</string>
7 <key>CFBundleDisplayName</key> 7 <key>CFBundleDisplayName</key>
8 - <string>YOHO!直播</string> 8 + <string>YOHO!推流</string>
9 <key>CFBundleExecutable</key> 9 <key>CFBundleExecutable</key>
10 <string>$(EXECUTABLE_NAME)</string> 10 <string>$(EXECUTABLE_NAME)</string>
11 <key>CFBundleIconFiles</key> 11 <key>CFBundleIconFiles</key>
@@ -7,7 +7,6 @@ @@ -7,7 +7,6 @@
7 // 7 //
8 8
9 #import "PlayController.h" 9 #import "PlayController.h"
10 -#import "ScanQRController.h"  
11 #import "TXLivePlayListener.h" 10 #import "TXLivePlayListener.h"
12 #import "TXRTMPAPI.h" 11 #import "TXRTMPAPI.h"
13 #import <mach/mach.h> 12 #import <mach/mach.h>
@@ -327,12 +326,7 @@ @@ -327,12 +326,7 @@
327 326
328 -(void) clickScan:(UIButton*) btn 327 -(void) clickScan:(UIButton*) btn
329 { 328 {
330 - [self stopRtmp];  
331 - _play_switch = NO;  
332 - [_btnPlay setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];  
333 - ScanQRController* vc = [[ScanQRController alloc] init];  
334 - vc.pvc = self;  
335 - [self.navigationController pushViewController:vc animated:NO]; 329 +
336 } 330 }
337 331
338 332
1 -//  
2 -// PublishController.h  
3 -// RTMPiOSDemo  
4 -//  
5 -// Created by 蓝鲸 on 16/4/1.  
6 -// Copyright © 2016年 tencent. All rights reserved.  
7 -//  
8 -  
9 -#import <UIKit/UIKit.h>  
10 -//#import <AVFoundation/AVFoundation.h>  
11 -#import "TXLivePush.h"  
12 -  
13 -@interface PublishController : UIViewController  
14 -{  
15 - BOOL _publish_switch;  
16 - BOOL _hardware_switch;  
17 - BOOL _log_switch;  
18 - BOOL _camera_switch;  
19 - int _beauty_level;  
20 - int _whitening_level;  
21 - int _hd_level;  
22 - BOOL _torch_switch;  
23 -  
24 - UIButton* _btnPublish;  
25 - UIButton* _btnCamera;  
26 - UIButton* _btnBeauty;  
27 - UIButton* _btnHardware;  
28 - UIButton* _btnLog;  
29 - UIButton* _btnResolution;  
30 - UIButton* _btnTorch;  
31 -  
32 - UIButton* _radioBtnHD;  
33 - UIButton* _radioBtnSD;  
34 - UIButton* _radioBtnAUTO;  
35 - UISlider* _sdBeauty;  
36 - UISlider* _sdWhitening;  
37 - UIView* _cover;  
38 -  
39 - UIControl* _vBeauty;  
40 - UIControl* _vHD;  
41 -  
42 - TXLivePush * _txLivePublisher;  
43 -  
44 - UITextView* _statusView;  
45 - UITextView* _logViewEvt;  
46 - unsigned long long _startTime;  
47 - unsigned long long _lastTime;  
48 -  
49 - //kuentest  
50 - NSString* _logMsg;  
51 - NSString* _tipsMsg;  
52 - NSString* _testPath;  
53 -  
54 -}  
55 -  
56 -@property (nonatomic, retain) UITextField* txtRtmpUrl;  
57 -  
58 -@end  
1 -//  
2 -// PublishController.m  
3 -// RTMPiOSDemo  
4 -//  
5 -// Created by 蓝鲸 on 16/4/1.  
6 -// Copyright © 2016年 tencent. All rights reserved.  
7 -//  
8 -  
9 -#import "PublishController.h"  
10 -#import "PlayController.h"  
11 -#import "ScanQRController.h"  
12 -//#import <Foundation/Foundation.h>  
13 -//#import "TXLiveSDKTypeDef.h"  
14 -#import <sys/types.h>  
15 -#import <sys/sysctl.h>  
16 -//#import <UIKit/UIKit.h>  
17 -//#import <mach/mach.h>  
18 -#import "TXRTMPAPI.h"  
19 -  
20 -// 清晰度定义  
21 -#define HD_LEVEL_720P 1 // 1280 * 720  
22 -#define HD_LEVEL_640 2 // 640 * 360  
23 -#define HD_LEVEL_640_PLUS 3 // 640 * 360 且开启码率自适应  
24 -  
25 -  
26 -#define RTMP_PUBLISH_URL @"请输入或扫二维码获取推流地址" //调试期间您可以修改之以避免输入地址的麻烦  
27 -//#define RTMP_PUBLISH_URL @"rtmp://2157.livepush.myqcloud.com/live/2157_6cfbca22ecad11e5b91fa4dcbef5e35a?bizid=2157"  
28 -  
29 -@interface PublishController ()<UITextFieldDelegate, TXLivePushListener>  
30 -  
31 -@end  
32 -  
33 -@implementation PublishController  
34 -{  
35 -}  
36 -  
37 -- (void)viewDidLoad {  
38 - [super viewDidLoad];  
39 -  
40 - [self initUI];  
41 -  
42 - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppActive:) name:UIApplicationDidBecomeActiveNotification object:nil];  
43 - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDeactive:) name:UIApplicationWillResignActiveNotification object:nil];  
44 -  
45 - _txLivePublisher = [[TXLivePush alloc] init];  
46 - [_txLivePublisher setLogLevel:LOGLEVEL_DEBUG];  
47 - TXLivePushConfig* _config = [[TXLivePushConfig alloc] init];  
48 - [_txLivePublisher setConfig:_config];  
49 -  
50 -  
51 -}  
52 -  
53 -  
54 -  
55 -- (void)didReceiveMemoryWarning {  
56 - [super didReceiveMemoryWarning];  
57 - // Dispose of any resources that can be recreated.  
58 -}  
59 -  
60 -#pragma -  
61 --(void) onAppActive:(UIApplication*)app  
62 -{  
63 - if (_publish_switch == YES) {  
64 - [self startRtmp];  
65 - }  
66 -}  
67 -  
68 --(void) onAppDeactive:(UIApplication*)app  
69 -{  
70 - if (_publish_switch == YES) {  
71 - [self stopRtmp];  
72 - }  
73 -}  
74 -  
75 -#pragma -  
76 -- (void)clearLog {  
77 - _tipsMsg = @"";  
78 - _logMsg = @"";  
79 - [_statusView setText:@""];  
80 - [_logViewEvt setText:@""];  
81 - _startTime = [[NSDate date]timeIntervalSince1970]*1000;  
82 - _lastTime = _startTime;  
83 -}  
84 -  
85 -  
86 --(BOOL)startRtmp{  
87 - [self clearLog];  
88 - NSString* rtmpUrl = self.txtRtmpUrl.text;  
89 - if (rtmpUrl.length == 0) {  
90 - rtmpUrl = RTMP_PUBLISH_URL;  
91 - }  
92 -  
93 - if (!([rtmpUrl hasPrefix:@"http:"] || [rtmpUrl hasPrefix:@"rtmp:"] )) {  
94 - [self toastTip:@"请输入正确的推流地址"];  
95 - return NO;  
96 - }  
97 -  
98 - //是否有摄像头权限  
99 - AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];  
100 - if (status == AVAuthorizationStatusDenied) {  
101 - [self toastTip:@"获取摄像头权限失败,请前往隐私-相机设置里面打开应用权限"];  
102 - return NO;  
103 - }  
104 -  
105 - NSArray* ver = [TXRtmpApi getSDKVersion];  
106 - if ([ver count] >= 3) {  
107 - _logMsg = [NSString stringWithFormat:@"rtmp sdk version: %@.%@.%@",ver[0],ver[1],ver[2]];  
108 - [_logViewEvt setText:_logMsg];  
109 - }  
110 -  
111 - if(_txLivePublisher != nil)  
112 - {  
113 - _txLivePublisher.delegate = self;  
114 - [_txLivePublisher startPreview:self.view];  
115 - [_txLivePublisher startPush:rtmpUrl];  
116 - }  
117 - return YES;  
118 -}  
119 -  
120 -  
121 -- (void)stopRtmp {  
122 - if(_txLivePublisher != nil)  
123 - {  
124 - _txLivePublisher.delegate = nil;  
125 - [_txLivePublisher stopPreview];  
126 - [_txLivePublisher stopPush];  
127 -  
128 - _sdBeauty.value = 0;  
129 - _sdWhitening.value = 0;  
130 - }  
131 -}  
132 -  
133 -// RTMP 推流事件通知  
134 -#pragma - TXLivePushListener  
135 --(void) appendLog:(NSString*) evt time:(NSDate*) date mills:(int)mil  
136 -{  
137 - NSDateFormatter* format = [[NSDateFormatter alloc] init];  
138 - format.dateFormat = @"hh:mm:ss";  
139 - NSString* time = [format stringFromDate:date];  
140 - NSString* log = [NSString stringWithFormat:@"[%@.%-3.3d] %@", time, mil, evt];  
141 - if (_logMsg == nil) {  
142 - _logMsg = @"";  
143 - }  
144 - _logMsg = [NSString stringWithFormat:@"%@\n%@", _logMsg, log];  
145 - [_logViewEvt setText:_logMsg];  
146 -}  
147 -  
148 --(void) onPushEvent:(int)EvtID WithParam:(NSDictionary*)param;  
149 -{  
150 - NSDictionary* dict = param;  
151 -  
152 - dispatch_async(dispatch_get_main_queue(), ^{  
153 - if (EvtID == PUSH_ERR_NET_DISCONNECT) {  
154 - [self clickPublish:_btnPublish];  
155 - }  
156 -// NSLog(@"evt:%d,%@", EvtID, dict);  
157 - long long time = [(NSNumber*)[dict valueForKey:EVT_TIME] longLongValue];  
158 - int mil = time % 1000;  
159 - NSDate* date = [NSDate dateWithTimeIntervalSince1970:time/1000];  
160 - NSString* Msg = (NSString*)[dict valueForKey:EVT_MSG];  
161 - [self appendLog:Msg time:date mills:mil];  
162 - });  
163 -}  
164 -  
165 --(void) onNetStatus:(NSDictionary*) param  
166 -{  
167 - NSDictionary* dict = param;  
168 -  
169 - dispatch_async(dispatch_get_main_queue(), ^{  
170 - int netspeed = [(NSNumber*)[dict valueForKey:NET_STATUS_NET_SPEED] intValue];  
171 - int vbitrate = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_BITRATE] intValue];  
172 - int abitrate = [(NSNumber*)[dict valueForKey:NET_STATUS_AUDIO_BITRATE] intValue];  
173 - int cachesize = [(NSNumber*)[dict valueForKey:NET_STATUS_CACHE_SIZE] intValue];  
174 - int dropsize = [(NSNumber*)[dict valueForKey:NET_STATUS_DROP_SIZE] intValue];  
175 - int jitter = [(NSNumber*)[dict valueForKey:NET_STATUS_NET_JITTER] intValue];  
176 - int fps = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_FPS] intValue];  
177 - int width = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_WIDTH] intValue];  
178 - int height = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_HEIGHT] intValue];  
179 - float cpu_usage = [(NSNumber*)[dict valueForKey:NET_STATUS_CPU_USAGE] floatValue];  
180 -  
181 -  
182 - NSString* log = [NSString stringWithFormat:@"CPU:%.1f%%\tRES:%d*%d\tSPD:%dkb/s\nJITT:%d\tFPS:%d\tARA:%dkb/s\nQUE:%d\tDRP:%d\tVRA:%dkb/s",  
183 - cpu_usage*100,  
184 - width,  
185 - height,  
186 - netspeed,  
187 - jitter,  
188 - fps,  
189 - abitrate,  
190 - cachesize,  
191 - dropsize,  
192 - vbitrate];  
193 - [_statusView setText:log];  
194 -  
195 - });  
196 -}  
197 -  
198 -  
199 -#pragma - ui util  
200 --(void) initUI  
201 -{  
202 - //主界面排版  
203 -  
204 - [self.view setBackgroundColor:[UIColor orangeColor]];  
205 -  
206 - CGSize size = [[UIScreen mainScreen] bounds].size;  
207 -  
208 - int icon_size = size.width / 10;  
209 -  
210 - _cover = [[UIView alloc]init];  
211 - _cover.frame = CGRectMake(10.0f, 55 + 2*icon_size, size.width - 20, size.height - 75 - 3 * icon_size);  
212 - _cover.backgroundColor = [UIColor whiteColor];  
213 - _cover.alpha = 0.5;  
214 - _cover.hidden = YES;  
215 - [self.view addSubview:_cover];  
216 -  
217 - int logheadH = 50;  
218 - _statusView = [[UITextView alloc] initWithFrame:CGRectMake(10.0f, 55 + 2*icon_size, size.width - 20, logheadH)];  
219 - _statusView.backgroundColor = [UIColor clearColor];  
220 - _statusView.alpha = 1;  
221 - _statusView.textColor = [UIColor blackColor];  
222 - _statusView.editable = NO;  
223 - _statusView.hidden = YES;  
224 - [self.view addSubview:_statusView];  
225 -  
226 - _logViewEvt = [[UITextView alloc] initWithFrame:CGRectMake(10.0f, 55 + 2*icon_size + logheadH, size.width - 20, size.height - 75 - 3 * icon_size - logheadH)];  
227 - _logViewEvt.backgroundColor = [UIColor clearColor];  
228 - _logViewEvt.alpha = 1;  
229 - _logViewEvt.textColor = [UIColor blackColor];  
230 - _logViewEvt.editable = NO;  
231 - _logViewEvt.hidden = YES;  
232 - [self.view addSubview:_logViewEvt];  
233 -  
234 -  
235 - NSArray *scArray = [[NSArray alloc] initWithObjects:@"推流",@"播放", nil];  
236 - UISegmentedControl* scSwitch = [[UISegmentedControl alloc] initWithItems:scArray];  
237 - scSwitch.frame = CGRectMake(75, 40, size.width-150, icon_size);  
238 - scSwitch.selectedSegmentIndex = 0;  
239 - scSwitch.tintColor = [UIColor blackColor];  
240 -  
241 - [scSwitch addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged];  
242 - [self.view addSubview:scSwitch];  
243 - [self.txtRtmpUrl setBorderStyle:UITextBorderStyleRoundedRect];  
244 -  
245 - self.txtRtmpUrl = [[UITextField alloc] initWithFrame:CGRectMake(10, 40 + icon_size + 10, size.width- 25 - icon_size, icon_size)];  
246 - self.txtRtmpUrl.placeholder = RTMP_PUBLISH_URL;  
247 - self.txtRtmpUrl.background = [UIImage imageNamed:@"Input_box"];  
248 - self.txtRtmpUrl.alpha = 0.5;  
249 - self.txtRtmpUrl.autocapitalizationType = UITextAutocorrectionTypeNo;  
250 - self.txtRtmpUrl.delegate = self;  
251 -  
252 - [self.view addSubview:self.txtRtmpUrl];  
253 -  
254 - UIButton* btnScan = [UIButton buttonWithType:UIButtonTypeCustom];  
255 - btnScan.frame = CGRectMake(size.width - 10 - icon_size , 40 + icon_size + 10, icon_size, icon_size);  
256 - [btnScan setImage:[UIImage imageNamed:@"QR_code"] forState:UIControlStateNormal];  
257 - [btnScan addTarget:self action:@selector(clickScan:) forControlEvents:UIControlEventTouchUpInside];  
258 - [self.view addSubview:btnScan];  
259 -  
260 - int icon_gap = 3*icon_size/8;  
261 -  
262 - //start or stop 按钮  
263 - _publish_switch = NO;  
264 - _btnPublish = [UIButton buttonWithType:UIButtonTypeCustom];  
265 - _btnPublish.frame = CGRectMake(icon_gap, size.height - icon_size - 10, icon_size, icon_size);  
266 - [_btnPublish setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];  
267 - [_btnPublish addTarget:self action:@selector(clickPublish:) forControlEvents:UIControlEventTouchUpInside];  
268 - [self.view addSubview:_btnPublish];  
269 -  
270 -  
271 - //前置后置摄像头切换  
272 - _camera_switch = NO;  
273 - _btnCamera = [UIButton buttonWithType:UIButtonTypeCustom];  
274 - _btnCamera.frame = CGRectMake(2*icon_gap + icon_size, size.height - 10 - icon_size, icon_size, icon_size);  
275 - [_btnCamera setImage:[UIImage imageNamed:@"camera"] forState:UIControlStateNormal];  
276 - [_btnCamera addTarget:self action:@selector(clickCamera:) forControlEvents:UIControlEventTouchUpInside];  
277 - [self.view addSubview:_btnCamera];  
278 -  
279 - //美颜开关按钮  
280 - _beauty_level = 0;  
281 - _btnBeauty = [UIButton buttonWithType:UIButtonTypeCustom];  
282 - _btnBeauty.frame = CGRectMake(3*icon_gap + 2*icon_size, size.height - 10 - icon_size, icon_size, icon_size);  
283 - [_btnBeauty setImage:[UIImage imageNamed:@"beauty"] forState:UIControlStateNormal];  
284 - [_btnBeauty addTarget:self action:@selector(clickBeauty:) forControlEvents:UIControlEventTouchUpInside];  
285 - [self.view addSubview:_btnBeauty];  
286 -  
287 - //硬件加速  
288 - _hardware_switch = NO;  
289 - _btnHardware = [UIButton buttonWithType:UIButtonTypeCustom];  
290 - _btnHardware.frame = CGRectMake(size.width - 3*icon_gap - 3*icon_size, size.height - 10 - icon_size, icon_size, icon_size);  
291 - [_btnHardware setImage:[UIImage imageNamed:@"quick"] forState:UIControlStateNormal];  
292 - [_btnHardware addTarget:self action:@selector(clickHardware:) forControlEvents:UIControlEventTouchUpInside];  
293 - [self.view addSubview:_btnHardware];  
294 -  
295 - //log显示或隐藏  
296 - _log_switch = NO;  
297 - _btnLog = [UIButton buttonWithType:UIButtonTypeCustom];  
298 - _btnLog.frame = CGRectMake(size.width - 2*icon_gap - 2*icon_size, size.height - 10 - icon_size, icon_size, icon_size);  
299 - [_btnLog setImage:[UIImage imageNamed:@"log"] forState:UIControlStateNormal];  
300 - [_btnLog addTarget:self action:@selector(clickLog:) forControlEvents:UIControlEventTouchUpInside];  
301 - [self.view addSubview:_btnLog];  
302 -  
303 - //清晰度按钮  
304 - _btnResolution = [UIButton buttonWithType:UIButtonTypeCustom];  
305 - _btnResolution.frame = CGRectMake(size.width - icon_gap - icon_size, size.height - 10 - icon_size, icon_size, icon_size);  
306 - [_btnResolution setImage:[UIImage imageNamed:@"SD"] forState:UIControlStateNormal];  
307 - [_btnResolution addTarget:self action:@selector(clickHD:) forControlEvents:UIControlEventTouchUpInside];  
308 - [self.view addSubview:_btnResolution];  
309 -  
310 - //开启闪关灯按钮  
311 - _torch_switch= NO;  
312 - _btnTorch = [UIButton buttonWithType:UIButtonTypeCustom];  
313 - _btnTorch.frame = CGRectMake(size.width - 4*icon_gap - 4*icon_size, size.height - 10 - icon_size, icon_size, icon_size);  
314 - [_btnTorch setImage:[UIImage imageNamed:@"flash_off"] forState:UIControlStateNormal];  
315 - [_btnTorch setImage:[UIImage imageNamed:@"flash_on"] forState:UIControlStateSelected];  
316 - [_btnTorch addTarget:self action:@selector(clickTorch:) forControlEvents:UIControlEventTouchUpInside];  
317 - [self.view addSubview:_btnTorch];  
318 -  
319 - //美颜拉杆浮层  
320 - _vBeauty = [[UIControl alloc] init];  
321 - _vBeauty.frame = CGRectMake(0, size.height-120, size.width, 120);  
322 - [_vBeauty setBackgroundColor:[UIColor whiteColor]];  
323 -  
324 - UILabel* txtBeauty = [[UILabel alloc]init];  
325 - txtBeauty.frame = CGRectMake(20, 25, 150, 150);  
326 - [txtBeauty setText:@"美颜效果"];  
327 - [txtBeauty setFont:[UIFont fontWithName:@"" size:14]];  
328 - [txtBeauty sizeToFit];  
329 -  
330 - _sdBeauty = [[UISlider alloc] init];  
331 - _sdBeauty.frame = CGRectMake(txtBeauty.frame.origin.x + txtBeauty.frame.size.width + 10, 0, size.width - txtBeauty.frame.origin.x - txtBeauty.frame.size.width - 40, 60);  
332 - _sdBeauty.minimumValue = 0;  
333 - _sdBeauty.maximumValue = 9;  
334 - _sdBeauty.value = 0;  
335 - _sdBeauty.center = CGPointMake(_sdBeauty.center.x, txtBeauty.center.y);  
336 -  
337 - [_sdBeauty setThumbImage:[UIImage imageNamed:@"circle"] forState:UIControlStateNormal];  
338 - [_sdBeauty setMinimumTrackTintColor:[UIColor blackColor]];  
339 - [_sdBeauty setMaximumTrackTintColor:[UIColor blackColor]];  
340 - [_sdBeauty addTarget:self action:@selector(sliderValueChange:) forControlEvents:UIControlEventValueChanged];  
341 - _sdBeauty.tag = 0;  
342 -  
343 - UILabel* txtWhitening = [[UILabel alloc] init];  
344 - txtWhitening.frame = CGRectMake(20, txtBeauty.frame.origin.y + txtBeauty.frame.size.height + 25, 150, 150);  
345 - [txtWhitening setText:@"美白效果"];  
346 - [txtWhitening setFont:[UIFont fontWithName:@"" size:14]];  
347 - [txtWhitening sizeToFit];  
348 -  
349 - _sdWhitening = [[UISlider alloc] init];  
350 - _sdWhitening.frame = CGRectMake(txtWhitening.frame.origin.x + txtWhitening.frame.size.width + 10, 0, size.width - txtWhitening.frame.origin.x - txtWhitening.frame.size.width - 40, 60);  
351 - _sdWhitening.minimumValue = 0;  
352 - _sdWhitening.maximumValue = 9;  
353 - _sdWhitening.center = CGPointMake(_sdWhitening.center.x, txtWhitening.center.y);  
354 -  
355 - [_sdWhitening setThumbImage:[UIImage imageNamed:@"circle"] forState:UIControlStateNormal];  
356 - [_sdWhitening setMinimumTrackTintColor:[UIColor blackColor]];  
357 - [_sdWhitening setMaximumTrackTintColor:[UIColor blackColor]];  
358 - [_sdWhitening addTarget:self action:@selector(sliderValueChange:) forControlEvents:UIControlEventValueChanged];  
359 - _sdWhitening.tag = 1;  
360 -  
361 -  
362 - [_vBeauty addSubview:txtBeauty];  
363 - [_vBeauty addSubview:_sdBeauty];  
364 - [_vBeauty addSubview:txtWhitening];  
365 - [_vBeauty addSubview:_sdWhitening];  
366 -  
367 - _vBeauty.hidden = YES;  
368 - [self.view addSubview: _vBeauty];  
369 -  
370 - // 清晰度选项: 720p - 640 - 640+ (此处使用了三个普通按钮来模拟单选框, 目的是跟android demo 保持界面风格一致)  
371 - _vHD = [[UIControl alloc]init];  
372 - _vHD.frame = CGRectMake(0, size.height-120, size.width, 120);  
373 - [_vHD setBackgroundColor:[UIColor whiteColor]];  
374 -  
375 - UILabel* txtHD= [[UILabel alloc]init];  
376 - txtHD.frame = CGRectMake(0, 0, size.width, 50);  
377 - [txtHD setText:@"清晰度"];  
378 - [txtHD setFont:[UIFont fontWithName:@"" size:14]];  
379 -  
380 - [_vHD addSubview:txtHD];  
381 -  
382 - int gap = 30;  
383 - int width = (size.width - gap*2 - 20) / 3;  
384 - _radioBtnHD = [UIButton buttonWithType:UIButtonTypeCustom];  
385 - _radioBtnHD.frame = CGRectMake(10, 60, width, 40);  
386 - [_radioBtnHD setTitle:@"720p" forState:UIControlStateNormal];  
387 - [_radioBtnHD addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside];  
388 -  
389 - _radioBtnSD = [UIButton buttonWithType:UIButtonTypeCustom];  
390 - _radioBtnSD.frame = CGRectMake(10 + gap + width, 60, width, 40);  
391 - [_radioBtnSD setTitle:@"640" forState:UIControlStateNormal];  
392 - [_radioBtnSD addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside];  
393 -  
394 - _radioBtnAUTO = [UIButton buttonWithType:UIButtonTypeCustom];  
395 - _radioBtnAUTO.frame = CGRectMake(size.width - 10 - width, 60, width, 40);  
396 - [_radioBtnAUTO setTitle:@"640+" forState:UIControlStateNormal];  
397 - [_radioBtnAUTO addTarget:self action:@selector(changeHD:) forControlEvents:UIControlEventTouchUpInside];  
398 -  
399 - [_vHD addSubview:_radioBtnHD];  
400 - [_vHD addSubview:_radioBtnSD];  
401 - [_vHD addSubview:_radioBtnAUTO];  
402 -  
403 - _vHD.hidden = YES;  
404 - [self.view addSubview: _vHD];  
405 -  
406 - // DEMO 默认采用 640 * 360 分辨率, 避免在4S等机型上出现编码不足  
407 - _hd_level = [self isSuitableMachine] ? HD_LEVEL_720P : HD_LEVEL_640;  
408 - [self setHDUI:_hd_level];  
409 -  
410 -#if TARGET_IPHONE_SIMULATOR  
411 - [self toastTip:@"iOS模拟器不支持推流和播放,请使用真机体验"];  
412 -#endif  
413 -  
414 -}  
415 -  
416 --(void) setHDUI:(int) level  
417 -{  
418 - switch (level) {  
419 - case HD_LEVEL_720P:  
420 - [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];  
421 - [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];  
422 - [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];  
423 - [_radioBtnHD setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];  
424 - [_radioBtnSD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
425 - [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
426 - [_btnResolution setImage:[UIImage imageNamed:@"HD"] forState:UIControlStateNormal];  
427 - break;  
428 - case HD_LEVEL_640:  
429 - [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];  
430 - [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];  
431 - [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];  
432 - [_radioBtnHD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
433 - [_radioBtnSD setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];  
434 - [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
435 - [_btnResolution setImage:[UIImage imageNamed:@"SD"] forState:UIControlStateNormal];  
436 -  
437 - break;  
438 - case HD_LEVEL_640_PLUS:  
439 - [_radioBtnHD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];  
440 - [_radioBtnSD setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];  
441 - [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];  
442 - [_radioBtnHD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
443 - [_radioBtnSD setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
444 - [_radioBtnAUTO setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];  
445 - [_btnResolution setImage:[UIImage imageNamed:@"PU"] forState:UIControlStateNormal];  
446 - default:  
447 - break;  
448 - }  
449 -}  
450 -  
451 -#pragma - 事件处理  
452 -- (void) segmentAction:(UISegmentedControl*) sc  
453 -{  
454 - NSInteger idx = sc.selectedSegmentIndex;  
455 - if (idx == 1) {  
456 - PlayController *vc = [[PlayController alloc] init];  
457 - [self.navigationController pushViewController:vc animated:YES];  
458 -  
459 - sc.selectedSegmentIndex = 0;  
460 - [_btnPublish setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];  
461 - _publish_switch = NO;  
462 - [self stopRtmp];  
463 - }  
464 -}  
465 -  
466 --(void) clickScan:(UIButton*) btn  
467 -{  
468 - [_btnPublish setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];  
469 - _publish_switch = NO;  
470 - [self stopRtmp];  
471 - ScanQRController* vc = [[ScanQRController alloc] init];  
472 - vc.pvc = self;  
473 - [self.navigationController pushViewController:vc animated:NO];  
474 -}  
475 -  
476 --(void) clickPublish:(UIButton*) btn  
477 -{  
478 - if (_publish_switch == YES) {  
479 - [self stopRtmp];  
480 - [_btnPublish setImage:[UIImage imageNamed:@"start"] forState:UIControlStateNormal];  
481 - _publish_switch = NO;  
482 - [[UIApplication sharedApplication] setIdleTimerDisabled:NO];  
483 - }  
484 - else  
485 - {  
486 - if(![self startRtmp])  
487 - {  
488 - return;  
489 - }  
490 - [_btnPublish setImage:[UIImage imageNamed:@"suspend"] forState:UIControlStateNormal];  
491 - _publish_switch = YES;  
492 - [[UIApplication sharedApplication] setIdleTimerDisabled:YES];  
493 - }  
494 -}  
495 -  
496 -  
497 --(void) clickCamera:(UIButton*) btn  
498 -{  
499 - _camera_switch = !_camera_switch;  
500 -  
501 - [btn setImage:[UIImage imageNamed:(_camera_switch? @"camera2" : @"camera")] forState:UIControlStateNormal];  
502 - [_txLivePublisher switchCamera];  
503 -}  
504 -  
505 --(void) clickBeauty:(UIButton*) btn  
506 -{  
507 - _sdBeauty.value = _beauty_level;  
508 - _vBeauty.hidden = NO;  
509 -}  
510 -  
511 -/**  
512 - @method 获取指定宽度width的字符串在UITextView上的高度  
513 - @param textView 待计算的UITextView  
514 - @param Width 限制字符串显示区域的宽度  
515 - @result float 返回的高度  
516 - */  
517 -- (float) heightForString:(UITextView *)textView andWidth:(float)width{  
518 - CGSize sizeToFit = [textView sizeThatFits:CGSizeMake(width, MAXFLOAT)];  
519 - return sizeToFit.height;  
520 -}  
521 -- (void) toastTip:(NSString*)toastInfo  
522 -{  
523 - CGRect frameRC = [[UIScreen mainScreen] bounds];  
524 - frameRC.origin.y = frameRC.size.height - 110;  
525 - frameRC.size.height -= 110;  
526 - __block UITextView * toastView = [[UITextView alloc] init];  
527 -  
528 - toastView.editable = NO;  
529 - toastView.selectable = NO;  
530 -  
531 - frameRC.size.height = [self heightForString:toastView andWidth:frameRC.size.width];  
532 -  
533 - toastView.frame = frameRC;  
534 -  
535 - toastView.text = toastInfo;  
536 - toastView.backgroundColor = [UIColor whiteColor];  
537 - toastView.alpha = 0.5;  
538 -  
539 - [self.view addSubview:toastView];  
540 -  
541 - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);  
542 -  
543 - dispatch_after(popTime, dispatch_get_main_queue(), ^(){  
544 - [toastView removeFromSuperview];  
545 - toastView = nil;  
546 - });  
547 -}  
548 -  
549 --(void) clickHardware:(UIButton*) btn  
550 -{  
551 - if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {  
552 - [self toastTip:@"iOS 版本低于8.0,不支持硬件加速."];  
553 - return;  
554 - }  
555 -  
556 - if(_txLivePublisher != nil) {  
557 - if (_publish_switch == YES) {  
558 - [self stopRtmp];  
559 - }  
560 -  
561 - TXLivePushConfig * configTmp = _txLivePublisher.config;  
562 - if (configTmp.enableHWAcceleration == NO)  
563 - {  
564 - NSString* strTip = @"iOS SDK启用硬件加速.";  
565 - if (_publish_switch == YES)  
566 - {  
567 - strTip = @"iOS SDK启用硬件加速,切换后会重新开始推流";  
568 - }  
569 -  
570 - [self toastTip:strTip];  
571 - configTmp.enableHWAcceleration = YES;  
572 - [btn setImage:[UIImage imageNamed:@"quick"] forState:UIControlStateNormal];  
573 - }  
574 - else  
575 - {  
576 - NSString* strTip = @"iOS SDK停止硬件加速.";  
577 - if (_publish_switch == YES)  
578 - {  
579 - strTip = @"iOS SDK停止硬件加速,切换后会重新开始推流";  
580 - }  
581 -  
582 - [self toastTip:strTip];  
583 - configTmp.enableHWAcceleration = NO;  
584 - [btn setImage:[UIImage imageNamed:@"quick2"] forState:UIControlStateNormal];  
585 - }  
586 - _txLivePublisher.config = configTmp;  
587 -  
588 - if (_publish_switch == YES) {  
589 - [self startRtmp];  
590 - }  
591 - }  
592 -}  
593 -  
594 --(void) clickLog:(UIButton*) btn  
595 -{  
596 - if (_log_switch == YES)  
597 - {  
598 - _statusView.hidden = YES;  
599 - _logViewEvt.hidden = YES;  
600 - [btn setImage:[UIImage imageNamed:@"log"] forState:UIControlStateNormal];  
601 - _cover.hidden = YES;  
602 - _log_switch = NO;  
603 - }  
604 - else  
605 - {  
606 - _statusView.hidden = NO;  
607 - _logViewEvt.hidden = NO;  
608 - [btn setImage:[UIImage imageNamed:@"log2"] forState:UIControlStateNormal];  
609 - _cover.hidden = NO;  
610 - _log_switch = YES;  
611 - }  
612 -  
613 -}  
614 -  
615 --(void) clickTorch:(UIButton*) btn  
616 -{  
617 - if (_txLivePublisher) {  
618 - btn.selected = !btn.selected;  
619 - _torch_switch = !_torch_switch;  
620 -// if (![_txLivePublisher toggleTorch:_torch_switch]) {  
621 -// _torch_switch = !_torch_switch;  
622 -// [self toastTip:@"闪光灯启动失败"];  
623 -// }  
624 - AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
625 -  
626 - if (_torch_switch) {  
627 - if ([device hasTorch]) {  
628 - [device lockForConfiguration:nil];  
629 - [device setTorchMode: AVCaptureTorchModeOn];  
630 - [device unlockForConfiguration];  
631 - }else {  
632 - [self toastTip:@"闪光灯启动失败"];  
633 - }  
634 - }else {  
635 - if ([device hasTorch]) {  
636 - [device lockForConfiguration:nil];  
637 - [device setTorchMode: AVCaptureTorchModeOff];  
638 - [device unlockForConfiguration];  
639 - }  
640 - }  
641 - }  
642 -}  
643 -  
644 --(void) clickHD:(UIButton*) btn  
645 -{  
646 - _vHD.hidden = NO;  
647 -}  
648 -  
649 -  
650 --(void) changeHD:(UIButton*) btn  
651 -{  
652 - if ([btn.titleLabel.text isEqualToString:@"720p"] && NO == [self isSuitableMachine]) {  
653 - UIAlertView * alert = [[UIAlertView alloc] initWithTitle: @"硬件加速"  
654 - message: @"iphone 6 及以上机型适合开启720p!"  
655 - delegate: nil  
656 - cancelButtonTitle: @"确认"  
657 - otherButtonTitles: nil];  
658 - [alert show];  
659 - return;  
660 - }  
661 -  
662 - if (_txLivePublisher == nil) return;  
663 -  
664 - if (_publish_switch == YES) {  
665 - [self stopRtmp];  
666 - }  
667 -  
668 - if ([btn.titleLabel.text isEqualToString:@"720p"]) {  
669 - _hd_level = HD_LEVEL_720P;  
670 -  
671 - TXLivePushConfig* _config = _txLivePublisher.config;  
672 - _config.videoBitratePIN = 1500;  
673 - _config.videoResolution = [self isSuitableMachine ] ? VIDEO_RESOLUTION_1280_720 : VIDEO_RESOLUTION_960_540;  
674 - _config.enableAutoBitrate = NO;  
675 - [_txLivePublisher setConfig:_config];  
676 -  
677 - } else if ([btn.titleLabel.text isEqualToString:@"640"]) {  
678 - _hd_level = HD_LEVEL_640;  
679 -  
680 - TXLivePushConfig* _config = _txLivePublisher.config;  
681 - _config.videoBitratePIN = 800;  
682 - _config.videoResolution = VIDEO_RESOLUTION_640_360;  
683 - _config.enableAutoBitrate = NO;  
684 - [_txLivePublisher setConfig:_config];  
685 -  
686 - } else if ([btn.titleLabel.text isEqualToString:@"640+"]) {  
687 - _hd_level = HD_LEVEL_640_PLUS;  
688 -  
689 - TXLivePushConfig* _config = _txLivePublisher.config;  
690 - _config.videoBitrateMin = 500;  
691 - _config.videoBitrateMax = 1500;  
692 - _config.enableAutoBitrate = YES;  
693 - _config.videoResolution = VIDEO_RESOLUTION_640_360;  
694 - [_txLivePublisher setConfig:_config]; // 此模式下设置bitrate无效  
695 - }  
696 -  
697 - [self setHDUI:_hd_level];  
698 - _vHD.hidden = YES;  
699 -  
700 - if (_publish_switch == YES) {  
701 - [self startRtmp];  
702 - }  
703 -}  
704 -  
705 --(void) sliderValueChange:(UISlider*) obj  
706 -{  
707 - // todo  
708 - if (obj.tag == 0) { //美颜  
709 - _beauty_level = obj.value;  
710 - } else if (obj.tag == 1) { //美白  
711 - _whitening_level = obj.value;  
712 - }  
713 -  
714 - [_txLivePublisher setBeautyFilterDepth:_beauty_level setWhiteningFilterDepth:_whitening_level];  
715 -}  
716 -  
717 -  
718 -// iphone 6 及以上机型适合开启720p, 否则20帧的帧率可能无法达到, 这种"流畅不足,清晰有余"的效果并不好  
719 --(BOOL) isSuitableMachine  
720 -{  
721 - int mib[2] = {CTL_HW, HW_MACHINE};  
722 - size_t len = 0;  
723 - char* machine;  
724 -  
725 - sysctl(mib, 2, NULL, &len, NULL, 0);  
726 -  
727 - machine = (char*)malloc(len);  
728 - sysctl(mib, 2, machine, &len, NULL, 0);  
729 -  
730 - NSString* platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];  
731 - free(machine);  
732 - if ([platform length] > 6) {  
733 - NSString * platNum = [NSString stringWithFormat:@"%C", [platform characterAtIndex: 6 ]];  
734 - return ([platNum intValue] >= 7);  
735 - } else {  
736 - return NO;  
737 - }  
738 -  
739 -}  
740 -  
741 -  
742 -  
743 -#pragma -- UITextFieldDelegate  
744 -- (BOOL)textFieldShouldReturn:(UITextField *)textField {  
745 - [textField resignFirstResponder];  
746 - return YES;  
747 -}  
748 -  
749 -- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event  
750 -{  
751 - [self.txtRtmpUrl resignFirstResponder];  
752 - _vHD.hidden = YES;  
753 - _vBeauty.hidden = YES;  
754 -}  
755 -@end  
1 -//  
2 -// ScanQRController.h  
3 -// RTMPiOSDemo  
4 -//  
5 -// Created by 蓝鲸 on 16/4/1.  
6 -// Copyright © 2016年 tencent. All rights reserved.  
7 -//  
8 -  
9 -#import <UIKit/UIKit.h>  
10 -#import <AVFoundation/AVFoundation.h>  
11 -  
12 -  
13 -@interface ScanQRController : UIViewController  
14 -{  
15 - BOOL _qrResult;  
16 - AVCaptureSession * _captureSession;  
17 - AVCaptureVideoPreviewLayer *_videoPreviewLayer;  
18 -  
19 -  
20 -}  
21 -  
22 -@property (nonatomic, retain) UIViewController* pvc;  
23 -  
24 -  
25 -@end  
1 -//  
2 -// ScanQRController.m  
3 -// RTMPiOSDemo  
4 -//  
5 -// Created by 蓝鲸 on 16/4/1.  
6 -// Copyright © 2016年 tencent. All rights reserved.  
7 -//  
8 -  
9 -#import "ScanQRController.h"  
10 -#import "PlayController.h"  
11 -#import "PublishController.h"  
12 -static const char *kScanQRCodeQueueName = "ScanQRCodeQueue";  
13 -  
14 -  
15 -@interface ScanQRController ()<AVCaptureMetadataOutputObjectsDelegate>  
16 -{  
17 -  
18 -}  
19 -  
20 -@end  
21 -  
22 -@implementation ScanQRController  
23 -- (void)viewDidLoad {  
24 - [super viewDidLoad];  
25 - // Do any additional setup after loading the view.  
26 - _qrResult = NO;  
27 -  
28 - [self startScan];  
29 -  
30 - CGSize size = [[UIScreen mainScreen] bounds].size;  
31 - int c_x = size.width/2;  
32 - int c_y = size.height/2;  
33 - int roi = 160/2;  
34 -  
35 - UIView* top = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, c_y - roi)];  
36 - top.backgroundColor = [UIColor blackColor];  
37 - top.alpha = 0.8;  
38 - [self.view addSubview:top];  
39 -  
40 -  
41 - UIView* left = [[UIView alloc] initWithFrame:CGRectMake(0, c_y - roi, c_x - roi, 2*roi)];  
42 - left.backgroundColor = [UIColor blackColor];  
43 - left.alpha = 0.8;  
44 - [self.view addSubview:left];  
45 -  
46 - UIView* right = [[UIView alloc] initWithFrame:CGRectMake(c_x + roi , c_y-roi, c_x - roi, 2*roi)];  
47 - right.backgroundColor = [UIColor blackColor];  
48 - right.alpha = 0.8;  
49 - [self.view addSubview:right];  
50 -  
51 - UIView* bottom = [[UIView alloc] initWithFrame:CGRectMake(0, c_y + roi, size.width, c_y - roi)];  
52 - bottom.backgroundColor = [UIColor blackColor];  
53 - bottom.alpha = 0.8;  
54 - [self.view addSubview:bottom];  
55 -  
56 -  
57 -}  
58 -  
59 -- (void)didReceiveMemoryWarning {  
60 - [super didReceiveMemoryWarning];  
61 - // Dispose of any resources that can be recreated.  
62 -}  
63 -  
64 -- (void)startScan  
65 -{  
66 - NSError * error;  
67 - AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
68 -  
69 -  
70 - if ([captureDevice lockForConfiguration:nil]) {  
71 - //对焦模式,自动对焦  
72 - if (captureDevice && [captureDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {  
73 - [captureDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];  
74 - }  
75 - else if(captureDevice && [captureDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]){  
76 - [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];  
77 - }  
78 -  
79 - // 自动白平衡  
80 - if (captureDevice && [captureDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) {  
81 - captureDevice.whiteBalanceMode = AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance;  
82 - }  
83 - else if (captureDevice && [captureDevice isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {  
84 - captureDevice.whiteBalanceMode = AVCaptureWhiteBalanceModeAutoWhiteBalance;  
85 - }  
86 -  
87 - if (captureDevice && [captureDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {  
88 - captureDevice.exposureMode = AVCaptureExposureModeContinuousAutoExposure;  
89 - }  
90 - else if (captureDevice && [captureDevice isExposureModeSupported:AVCaptureExposureModeAutoExpose]) {  
91 - captureDevice.exposureMode = AVCaptureExposureModeAutoExpose;  
92 - }  
93 -  
94 - [captureDevice unlockForConfiguration];  
95 - }  
96 -  
97 -  
98 - AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];  
99 - if (!input) {  
100 - NSLog(@"%@", [error localizedDescription]);  
101 - return ;  
102 - }  
103 -  
104 - // 创建会话  
105 - _captureSession = [[AVCaptureSession alloc] init];  
106 - // 添加输入流  
107 - [_captureSession addInput:input];  
108 - // 初始化输出流  
109 - AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];  
110 - // 添加输出流  
111 - [_captureSession addOutput:captureMetadataOutput];  
112 -  
113 - // 创建dispatch queue.  
114 - dispatch_queue_t dispatchQueue;  
115 - dispatchQueue = dispatch_queue_create(kScanQRCodeQueueName, NULL);  
116 - [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];  
117 - // 设置元数据类型 AVMetadataObjectTypeQRCode  
118 - [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];  
119 - // captureMetadataOutput.rectOfInterest=CGRectMake(0.25,025,0.5, 0.5);  
120 - // 创建输出对象  
121 - _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];  
122 - [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];  
123 - [_videoPreviewLayer setFrame:self.view.layer.bounds];  
124 - [self.view.layer addSublayer:_videoPreviewLayer];  
125 -  
126 - [_captureSession startRunning];  
127 -  
128 -}  
129 -  
130 -  
131 -- (void)stopScanQRCode {  
132 - [_captureSession stopRunning];  
133 - _captureSession = nil;  
134 -  
135 - [_videoPreviewLayer removeFromSuperlayer];  
136 - _videoPreviewLayer = nil;  
137 -}  
138 -  
139 -  
140 -  
141 -- (void)handleScanResult:(NSString *)result  
142 -{  
143 - [self stopScanQRCode];  
144 - if (_qrResult) {  
145 - return;  
146 - }  
147 - _qrResult = YES;  
148 - if ([self.pvc isKindOfClass:[PlayController class]]) {  
149 - PlayController* vc = (PlayController*)self.pvc;  
150 - [vc.txtRtmpUrl setText:result];  
151 - }  
152 -  
153 - if ([self.pvc isKindOfClass:[PublishController class]]) {  
154 - PublishController* vc = (PublishController*)self.pvc;  
155 - [vc.txtRtmpUrl setText:result];  
156 - }  
157 - [self.navigationController popToViewController:self.pvc animated:NO];  
158 -}  
159 -  
160 -- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {  
161 - if (metadataObjects.count>0) {  
162 - AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];  
163 - if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {  
164 - [self performSelectorOnMainThread:@selector(handleScanResult:) withObject:metadataObj.stringValue waitUntilDone:NO];  
165 - }  
166 -  
167 - }  
168 -}  
169 -  
170 -- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event  
171 -{  
172 - [self stopScanQRCode];  
173 - [self.navigationController popViewControllerAnimated:NO];  
174 -}  
175 -  
176 -@end  
  1 +//
  2 +// TXLivePlayConfig.h
  3 +// TXRTMPSDK
  4 +//
  5 +// Created by realingzhou on 16/5/31.
  6 +//
  7 +//
  8 +#import <Foundation/NSObject.h>
  9 +
  10 +@interface TXLivePlayConfig : NSObject
  11 +
  12 +//播放器缓存时间 : 单位秒,取值需要大于0
  13 +@property (nonatomic, assign) int cacheTime;
  14 +
  15 +//是否自动调整播放器缓存时间 : YES:启用自动调整,自动调整的最大值和最小值可以分别通过修改maxCacheTime和minCacheTime来设置;
  16 +// NO:关闭自动调整,采用默认的指定缓存时间(1s),可以通过修改cacheTime来调整缓存时间.
  17 +@property (nonatomic, assign) BOOL bAutoAdjustCacheTime;
  18 +
  19 +//播放器缓存自动调整的最大时间 : 单位秒,取值需要大于0
  20 +@property (nonatomic, assign) int maxAutoAdjustCacheTime;
  21 +
  22 +//播放器缓存自动调整的最小时间 : 单位秒,取值需要大于0
  23 +@property (nonatomic, assign) int minAutoAdjustCacheTime;
  24 +
  25 +//播放器连接重试次数 : 最小值为 1, 最大值为 10, 默认值为 3
  26 +@property (nonatomic, assign) int connectRetryCount;
  27 +
  28 +//播放器连接重试间隔 : 单位秒,最小值为 3, 最大值为 30, 默认值为 3
  29 +@property (nonatomic, assign) int connectRetryInterval;
  30 +
  31 +@end