├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README_zh.md ├── android ├── .gitignore ├── CMakeLists.txt ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libs │ ├── VERSION.txt │ ├── ZegoLiveRoom.jar │ ├── arm64-v8a │ │ ├── include │ │ │ ├── audio_capture.h │ │ │ ├── audio_in_output.h │ │ │ ├── media_player.h │ │ │ ├── video_capture.h │ │ │ ├── video_format.h │ │ │ └── zego-api-sdk-property.h │ │ └── libZegoLiveRoom.so │ ├── armeabi-v7a │ │ ├── include │ │ │ ├── audio_capture.h │ │ │ ├── audio_in_output.h │ │ │ ├── media_player.h │ │ │ ├── video_capture.h │ │ │ ├── video_format.h │ │ │ └── zego-api-sdk-property.h │ │ └── libZegoLiveRoom.so │ ├── x86 │ │ ├── include │ │ │ ├── audio_capture.h │ │ │ ├── audio_in_output.h │ │ │ ├── media_player.h │ │ │ ├── video_capture.h │ │ │ ├── video_format.h │ │ │ └── zego-api-sdk-property.h │ │ └── libZegoLiveRoom.so │ └── x86_64 │ │ ├── include │ │ ├── audio_capture.h │ │ ├── audio_in_output.h │ │ ├── media_player.h │ │ ├── video_capture.h │ │ ├── video_format.h │ │ └── zego-api-sdk-property.h │ │ └── libZegoLiveRoom.so ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── cpp │ └── zego_log_jni.cpp │ └── java │ └── com │ └── zego │ └── zegoliveroomplugin │ ├── ZegoLiveRoomPlugin.java │ ├── ZegoLogJNI.java │ ├── ZegoPlatformView.java │ ├── ZegoPlatformViewFactory.java │ ├── ZegoViewRenderer.java │ ├── constants │ └── ZegoEventType.java │ ├── module │ ├── audioplayer │ │ ├── IZegoAudioPlayerControllerCallback.java │ │ └── ZegoAudioPlayerController.java │ └── mediaplayer │ │ ├── IZegoMediaPlayerControllerCallback.java │ │ └── ZegoMediaPlayerController.java │ └── utils │ └── ZegoFileHelper.java ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── app │ │ ├── .settings │ │ │ └── org.eclipse.buildship.core.prefs │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── zego │ │ │ │ │ ├── ExternalVideoFilter │ │ │ │ │ ├── VideoFilter │ │ │ │ │ │ ├── VideoFilterAsyncI420MemDemo.java │ │ │ │ │ │ ├── VideoFilterHybridDemo.java │ │ │ │ │ │ ├── VideoFilterMemDemo.java │ │ │ │ │ │ ├── VideoFilterSurfaceTextureDemo.java │ │ │ │ │ │ └── VideoFilterSyncGlTexture2dDemo.java │ │ │ │ │ ├── VideoFilterFactoryDemo.java │ │ │ │ │ └── ve_gl │ │ │ │ │ │ ├── EglBase.java │ │ │ │ │ │ ├── EglBase10.java │ │ │ │ │ │ ├── EglBase14.java │ │ │ │ │ │ ├── GlRectDrawer.java │ │ │ │ │ │ ├── GlShader.java │ │ │ │ │ │ └── GlUtil.java │ │ │ │ │ ├── externalvideocapture │ │ │ │ │ ├── MediaPlayerVideoCapture.java │ │ │ │ │ └── VideoCaptureFactory.java │ │ │ │ │ └── flutter │ │ │ │ │ └── example │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MyApplication.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── ios │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Flutter.podspec │ │ └── Release.xcconfig │ ├── Podfile │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── ExternalVideoCapture │ │ ├── ZGExternalVideoCaptureFactory.h │ │ ├── ZGExternalVideoCaptureFactory.m │ │ ├── ZGVideoCaptureForMediaPlayer.h │ │ └── ZGVideoCaptureForMediaPlayer.mm │ │ ├── ExternalVideoFilter │ │ ├── VideoFilter │ │ │ ├── ZGVideoFilterAsyncDemo.h │ │ │ ├── ZGVideoFilterAsyncDemo.m │ │ │ ├── ZGVideoFilterSyncDemo.h │ │ │ └── ZGVideoFilterSyncDemo.m │ │ ├── ZGPixelBufferUtils.h │ │ ├── ZGPixelBufferUtils.m │ │ ├── ZGVideoFilterFactoryDemo.h │ │ └── ZGVideoFilterFactoryDemo.m │ │ ├── Info.plist │ │ └── main.m ├── lib │ ├── config │ │ └── zego_config.dart │ ├── main.dart │ ├── pages │ │ ├── init_sdk_page.dart │ │ ├── login_room_page.dart │ │ ├── mediaplayer_page.dart │ │ ├── play_stream_page.dart │ │ ├── play_stream_platformview_page.dart │ │ ├── publish_settings_page.dart │ │ ├── publish_stream_page.dart │ │ └── publish_stream_platformview_page.dart │ └── ui │ │ └── zego_ui_tool.dart ├── pubspec.yaml ├── resources │ └── images │ │ ├── 2.0x │ │ ├── bottom_microphone_off_icon.png │ │ ├── bottom_microphone_on_icon.png │ │ ├── bottom_switchcamera_icon.png │ │ └── settings_tips.png │ │ ├── 3.0x │ │ ├── bottom_microphone_off_icon.png │ │ ├── bottom_microphone_on_icon.png │ │ ├── bottom_switchcamera_icon.png │ │ └── settings_tips.png │ │ ├── bottom_microphone_off_icon.png │ │ ├── bottom_microphone_on_icon.png │ │ ├── bottom_switchcamera_icon.png │ │ └── settings_tips.png └── test │ └── widget_test.dart ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── ZegoAudioPlayerController.h │ ├── ZegoAudioPlayerController.mm │ ├── ZegoLiveRoomPlugin.h │ ├── ZegoLiveRoomPlugin.mm │ ├── ZegoLog.h │ ├── ZegoLog.m │ ├── ZegoMediaplayerController.h │ ├── ZegoMediaplayerController.mm │ ├── ZegoPlatformView.h │ ├── ZegoPlatformView.m │ ├── ZegoPlatformViewFactory.h │ ├── ZegoPlatformViewFactory.m │ ├── ZegoRendererController.h │ ├── ZegoRendererController.mm │ ├── ZegoViewRenderer.h │ └── ZegoViewRenderer.mm └── zegoliveroom_plugin.podspec ├── lib ├── src │ ├── zego_api_defines.dart │ ├── zego_api_error_code.dart │ ├── zego_audioplayer.dart │ ├── zego_liveroom.dart │ ├── zego_liveroom_audio.dart │ ├── zego_liveroom_event_channel.dart │ ├── zego_liveroom_player.dart │ ├── zego_liveroom_publisher.dart │ ├── zego_media_recorder.dart │ ├── zego_media_side_info.dart │ ├── zego_mediaplayer.dart │ └── zego_sound_level.dart └── zegoliveroom_plugin.dart ├── pubspec.yaml ├── zego_defines.h ├── zegoliveroom_plugin.iml └── zegoliveroom_plugin_android.iml /.gitattributes: -------------------------------------------------------------------------------- 1 | *.m linguist-language=Dart 2 | *.mm linguist-language=Dart 3 | *.java linguist-language=Dart 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # pub 2 | .dart_tool/ 3 | .packages 4 | build/ 5 | pubspec.lock 6 | 7 | # api doc 8 | doc/api/ 9 | 10 | # IntelliJ 11 | *.iml 12 | *.ipr 13 | *.iws 14 | .idea/ 15 | 16 | .settings 17 | .project 18 | .classpath 19 | .flutter-plugins-dependencies 20 | flutter_export_environment.sh 21 | 22 | # mac 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | ## ⚠️❗️ This project is a **legacy** SDK and and will be deprecated in the future, only used to support the maintenance for existing users, it is recommended to migrate and upgrade to the new SDK as soon as possible 4 | 5 | ## **🚀 Please use the brand new [`ZegoExpressEngine Flutter SDK`](https://pub.dev/packages/zego_express_engine)** 6 | 7 | ## 1.7.0 8 | 1. Support max 4 mediaplayers 9 | 10 | ## 1.5.1 11 | 12 | 1. Add some MediaPlayer API and `setCaptureVolume` API 13 | 14 | ## 1.5.0 15 | 16 | 1. Add feature of MediaPlayer Rendering and publishing 17 | 18 | ## 1.4.0 19 | 20 | 1. Optimization: Limit iOS memory allocation to avoid the problem of untimely memory release in some versions of flutter 21 | 2. Update Native SDK to 1.21.3.18 22 | 23 | ## 1.3.6 24 | 25 | 1. Update Native SDK to 1.21.1.27 26 | 27 | ## 1.3.5 28 | 29 | 1. Update Native SDK to 1.21.1.16 30 | 31 | ## 1.3.4 32 | 33 | 1. Add [`takePublishStreamSnapshot`](https://pub.dev/documentation/zegoliveroom_plugin/latest/zegoliveroom_plugin/ZegoLiveRoomPublisherPlugin/takePublishStreamSnapshot.html) and [`takePlayStreamSnapshot`](https://pub.dev/documentation/zegoliveroom_plugin/latest/zegoliveroom_plugin/ZegoLiveRoomPlayerPlugin/takePlayStreamSnapshot.html) APIs 34 | 35 | ## 1.3.3 36 | 37 | 1. update native sdk. 38 | 39 | 2. add `setPlayVolume` API. 40 | 41 | ## 1.3.2 42 | 43 | 1. update native ios sdk. 44 | 45 | ## 1.3.1 46 | 47 | 1. update native sdk. 48 | 2. fix `onPublishStateUpdate` streamInfo is sometimes null. 49 | 50 | ## 1.3.0 51 | 52 | 1. update native sdk(2020.10.15). 53 | 2. add `switchRoom` API. 54 | 55 | ## 1.2.18 56 | 57 | 1. Update project configuration and README 58 | 2. Fix a crash in Android example demo 59 | 60 | ## 1.2.17 61 | 62 | 1. Fix problem with `setLogConfig` not working 63 | 64 | ## 1.2.16 65 | 66 | 1. fix crash when multi thread read/write the input CVPixelBuffer 67 | 68 | ## 1.2.15 69 | 70 | 1. fix the input CVPixelBuffer lifecycle issue. 71 | 72 | ## 1.2.14 73 | 74 | 1. fix CVPixelBuffer release crash. 75 | 76 | ## 1.2.13 77 | 78 | 1. add `setLogConfig` to set log path and log size 79 | 2. add `onDeviceError` for Notifying device abnormalities 80 | 3. add MediaPlayer module new API(for playing network sources): `setOnlineResourceCache`、`getOnlineResourceCache`、`setBufferThreshold`、`setLoadResourceTimeout` 81 | 82 | ## 1.2.12 83 | 84 | 1. add `MediaPlayer`(only audio module) 85 | 86 | ## 1.2.11 87 | 88 | 1. Update iOS native SDK to version `200424_175024_release-new-0-gb8ff47533_video_mediaplayer_bn3845_12` 89 | 90 | 2. Update Android native SDK to version `200424_175024_release-new-0-gb8ff47533_video_mediaplayer_bn3845_12` 91 | 92 | ## 1.2.10 93 | 94 | - Add `setCamZoomFactor`, `getCamMaxZoomFactor` to adjust the camera zoom factor. 95 | 96 | ## 1.2.9 97 | 98 | 1. Add `sendBigRoomMessage`, `onRecvBigRoomMessage` to send and receive big room messages. 99 | 100 | 2. Add `onUpdateOnlineCount` callback to received online user number updates. 101 | 102 | ## 1.2.8 103 | 104 | 1. Update iOS native SDK to version `200415_195052_release-new-0-g18e243156_video_mediaplayer_bn3792_12` 105 | 106 | 2. Update Android native SDK to version `200410_212545_release-new-0-g18e243156_video_mediaplayer_bn3760_12` 107 | 108 | ## 1.2.7 109 | 110 | 1. Add log for texture render. 111 | 112 | 2. Optimize the code when calling `updatePreviewRenderSize` and `updatePlayRenderSize` 113 | 114 | ## 1.2.6 115 | 116 | 1. Added `setConfig` for setting additional configuration information. 117 | 118 | 2. Update iOS/Android native SDK to version `200316_163753_release-new-0-gb76c836cd_video_mediaplayer_bn3590_12` 119 | 120 | ## 1.2.5 121 | 122 | 1. Update ios/android native sdk to version `200309_200607_release-new-0-g54f488a0c_video_mediaplayer_bn3549_12` 123 | 124 | 2. Fix bug of external filter module on Android. 125 | 126 | ## 1.2.4 127 | 128 | - Add external video filter interface and corresponding sample code. 129 | 130 | ## 1.2.3 131 | 132 | - Add `setSharpenFactor` to set the sharpening factor for beauty. 133 | 134 | ## 1.2.2 135 | 136 | - Add `sendRoomMessage`, `onRecvRoomMessage` to send and receive room messages. 137 | 138 | ## 1.2.1 139 | 140 | - Update android native sdk. 141 | 142 | ## 1.2.0 143 | 144 | 1. Add `seekTo` `getTotalDuration` `getCurrentDuration` in AudioPlayer. 145 | 146 | 2. Add `enableLoopback` `setLoopbackVolume` to listen captured voice. 147 | 148 | ## 1.1.9 149 | 150 | - Update iOS/Android native sdk (2020.2.9 hotfix) 151 | 152 | ## 1.1.8 153 | 154 | - Update iOS/Android native sdk (2020.2.9) 155 | 156 | ## 1.1.7 157 | 158 | - Fix bug of init page in example. 159 | 160 | ## 1.1.6 161 | 162 | 1. This new version is compatible with AndroidX. 163 | 164 | 2. Fix the Android example crash in release mode because of the obfuscation. 165 | 166 | ## 1.1.5 167 | 168 | - Fix iOS: use platform view render failed. 169 | 170 | ## 1.1.4 171 | 172 | - Fix AudioPlayer bug. 173 | 174 | ## 1.1.3 175 | 176 | - Add Audio Precessing API: `VirtualStereo`, `Reverb`, `VoiceChanger` 177 | 178 | ## 1.1.2 179 | 180 | 1. Fix iOS callback doesn’t work when call `initSDK` failed 181 | 182 | 2. iOS native framework uses cocoapods dependency instead 183 | 184 | ## 1.1.1 185 | 186 | 1. Add audio player module 187 | 188 | 2. Update texture's API comment 189 | 190 | ## 1.0.12 191 | 192 | - Update iOS/Android native sdk (12.9) 193 | 194 | ## 1.0.11 195 | 196 | 1. Add onInnerError 197 | 198 | 2. Update iOS/Android native sdk 199 | 200 | ## 1.0.10 201 | 202 | 1. Add relay CDN methods: `setPublishConfig`, `addPublishTarget`, `deletePublishTarget`, and callback: `onRelayCDNStateUpdate` 203 | 204 | 2. Fix bug that xcode11 can't run in debug mode 205 | 206 | 3. Update iOS/Android native sdk 207 | 208 | ## 1.0.9 209 | 210 | - Fix the problem that Android can't receive media sideinfo callback 211 | 212 | ## 1.0.8 213 | 214 | 1. Add setVideoMirrorMode API 215 | 216 | 2. Update iOS/Android native sdk 217 | 218 | ## 1.0.7 219 | 220 | 1. Fix android texture render crash into background 221 | 222 | 2. Fix android startPlayingStream bugs 223 | 224 | 3. Update android native sdk 225 | 226 | ## 1.0.6 227 | 228 | 1. Fix some bug and crash 229 | 230 | 2. Add log system 231 | 232 | ## 1.0.5 233 | 234 | 1. Add peer to peer delay/package lost rate. 235 | 236 | 2. Add remote user's device state notification(on/off) 237 | 238 | 3. Add remote user's first frame notification 239 | 240 | 4. Update native sdk 241 | 242 | 5. promote stability 243 | 244 | ## 1.0.4 245 | 246 | 1. Add sound-level module 247 | 248 | 2. Add error-code module 249 | 250 | 3. Update native sdk 251 | 252 | ## 1.0.3 253 | 254 | - Add Platform View API 255 | 256 | ## 1.0.2 257 | 258 | 1. Update native sdk 259 | 260 | 2. Fix crash 261 | 262 | 3. Refactor api structure 263 | 264 | ## 1.0.1 265 | 266 | - Add format interface 267 | 268 | ## 1.0.0 269 | 270 | - Initial release 271 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2019, zegoim 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zegoliveroom_plugin **(Deprecated)** 2 | 3 | ![Deprecated](https://img.shields.io/badge/Legacy%20Project-Deprecated-yellow) 4 | [![pub package](https://img.shields.io/pub/v/zegoliveroom_plugin.svg)](https://pub.dartlang.org/packages/zegoliveroom_plugin) 5 | 6 | **[English](https://github.com/zegoim/zego-flutter-sdk/blob/master/README.md) | [中文](https://github.com/zegoim/zego-flutter-sdk/blob/master/README_zh.md)** 7 | 8 | Zego's audio and video LiveRoom Flutter SDK **(Deprecated)**, provides live video and real-time audio and video services. 9 | 10 | Learn more about the solution: [https://www.zego.im](https://www.zego.im) 11 | 12 | ## ⚠️❗️ This project is a **deprecated** SDK, only used to support the maintenance for existing users, it is recommended to migrate and upgrade to the new SDK as soon as possible 13 | 14 | ## **🚀 Please use the brand new [`ZegoExpressEngine Flutter SDK`](https://pub.dev/packages/zego_express_engine)** 15 | 16 | - pub: **[https://pub.dev/packages/zego_express_engine](https://pub.dev/packages/zego_express_engine)** 17 | 18 | - Github: **[https://github.com/zegoim/zego-express-flutter-sdk](https://github.com/zegoim/zego-express-flutter-sdk)** 19 | 20 | - Documents: **[https://doc-en.zego.im/en/5560.html](https://doc-en.zego.im/en/5560.html)** 21 | 22 | > 🌞 The new redesigned API is easier to use, updated in sync with the ZEGO native SDK, and has more complete functions! 23 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # zegoliveroom_plugin **(Deprecated)** 2 | 3 | ![Deprecated](https://img.shields.io/badge/Legacy%20Project-Deprecated-yellow) 4 | [![pub package](https://img.shields.io/pub/v/zegoliveroom_plugin.svg)](https://pub.dartlang.org/packages/zegoliveroom_plugin) 5 | 6 | **[English](https://github.com/zegoim/zego-flutter-sdk/blob/master/README.md) | [中文](https://github.com/zegoim/zego-flutter-sdk/blob/master/README_zh.md)** 7 | 8 | 即构科技(Zego)音视频 LiveRoom Flutter SDK **(已废弃)** ,提供视频直播以及实时音视频服务。 9 | 10 | 了解更多解决方案:[https://www.zego.im](https://www.zego.im) 11 | 12 | ## ⚠️❗️ 此项目为 **旧版** SDK,仅用于支持老用户维护使用,建议尽快迁移升级到新版 SDK 13 | 14 | ## **🚀 请使用新版 [`ZegoExpressEngine Flutter SDK`](https://pub.dev/packages/zego_express_engine)** 15 | 16 | - pub: **[https://pub.dev/packages/zego_express_engine](https://pub.dev/packages/zego_express_engine)** 17 | 18 | - Github: **[https://github.com/zegoim/zego-express-flutter-sdk](https://github.com/zegoim/zego-express-flutter-sdk)** 19 | 20 | - 官方文档: **[https://doc-zh.zego.im/zh/5424.html](https://doc-zh.zego.im/zh/5424.html)** 21 | 22 | > 🌞 经过重新设计的全新 API 更易于接入使用,与 ZEGO 原生 SDK 同步更新,功能更加齐全! 23 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /bin 9 | /captures 10 | .externalNativeBuild 11 | .classpath 12 | .settings 13 | .project 14 | .cxx 15 | -------------------------------------------------------------------------------- /android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 3.4.1) 3 | 4 | add_library( # Sets the name of the library. 5 | ZegoLog 6 | 7 | # Sets the library as a shared library. 8 | SHARED 9 | 10 | # Provides a relative path to your source file(s). 11 | src/main/cpp/zego_log_jni.cpp) 12 | 13 | add_library( 14 | ZegoLiveRoom 15 | SHARED 16 | IMPORTED 17 | ) 18 | 19 | set_target_properties(ZegoLiveRoom 20 | PROPERTIES IMPORTED_LOCATION 21 | ${CMAKE_CURRENT_LIST_DIR}/libs/${ANDROID_ABI}/libZegoLiveRoom.so 22 | ) 23 | 24 | target_link_libraries( # Specifies the target library. 25 | 26 | ZegoLog 27 | ZegoLiveRoom 28 | ) -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.zego.zegoliveroomplugin' 2 | version '1.0-SNAPSHOT' 3 | 4 | buildscript { 5 | repositories { 6 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 7 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } 8 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } 9 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/gradle-plugin' } 10 | google() 11 | jcenter() 12 | 13 | } 14 | 15 | dependencies { 16 | classpath 'com.android.tools.build:gradle:4.2.1' 17 | } 18 | } 19 | 20 | rootProject.allprojects { 21 | repositories { 22 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 23 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } 24 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } 25 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/gradle-plugin' } 26 | google() 27 | jcenter() 28 | 29 | } 30 | } 31 | 32 | apply plugin: 'com.android.library' 33 | 34 | android { 35 | compileSdkVersion 28 36 | 37 | defaultConfig { 38 | minSdkVersion 16 39 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 40 | externalNativeBuild { 41 | cmake { 42 | cppFlags "-std=c++11" 43 | } 44 | } 45 | ndk { 46 | //设置支持的SO库架构 47 | abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86' 48 | } 49 | } 50 | 51 | lintOptions { 52 | disable 'InvalidPackage' 53 | } 54 | 55 | compileOptions { 56 | targetCompatibility JavaVersion.VERSION_1_8 57 | sourceCompatibility JavaVersion.VERSION_1_8 58 | } 59 | /*sourceSets { 60 | main { 61 | jniLibs.srcDirs = ['libs'] 62 | } 63 | }*/ 64 | 65 | externalNativeBuild { 66 | cmake { 67 | path "CMakeLists.txt" 68 | } 69 | } 70 | } 71 | 72 | dependencies { 73 | api fileTree(dir: 'libs', include: ['*.jar']) 74 | } 75 | 76 | allprojects { 77 | gradle.projectsEvaluated { 78 | tasks.withType(JavaCompile) { 79 | options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Nov 15 12:41:02 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /android/libs/VERSION.txt: -------------------------------------------------------------------------------- 1 | 6.16.2.25372 2 | ZegoLiveRoom 3 | COMMON_BUILD_VIDEO=true -------------------------------------------------------------------------------- /android/libs/ZegoLiveRoom.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/android/libs/ZegoLiveRoom.jar -------------------------------------------------------------------------------- /android/libs/arm64-v8a/include/audio_capture.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOAudioCapture_h 2 | #define ZEGOAudioCapture_h 3 | 4 | namespace AVE { 5 | enum AudioBufferType { 6 | BufferTypeAudioApp = 0, 7 | BufferTypeAudioMic, 8 | }; 9 | 10 | struct AudioCaptureFormat { 11 | AudioCaptureFormat() : sample_rate(0), num_channels(0), bit_depth(0), is_big_endian(false) { 12 | } 13 | 14 | int sample_rate; 15 | int num_channels; 16 | int bit_depth; 17 | bool is_big_endian; 18 | }; 19 | 20 | class SupportsAudioCapture { 21 | public: 22 | 23 | }; 24 | 25 | class AudioCaptureCallback { 26 | public: 27 | virtual void OnCapturedAudioData(const char *pData, int data_len, 28 | const AudioCaptureFormat& format, 29 | AudioBufferType buffer_type, 30 | double timestamp_ms) = 0; 31 | virtual void SetMicVolume(int volume) = 0; 32 | virtual void SetAppVolume(int volume) = 0; 33 | }; 34 | } 35 | #endif /* ZEGOAudioCapture_h */ 36 | -------------------------------------------------------------------------------- /android/libs/arm64-v8a/include/video_format.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOVideoFormat_h 2 | #define ZEGOVideoFormat_h 3 | 4 | namespace AVE 5 | { 6 | enum VideoPixelFormat 7 | { 8 | PIXEL_FORMAT_UNKNOWN = 0, 9 | PIXEL_FORMAT_I420 = 1, 10 | PIXEL_FORMAT_NV12 = 2, 11 | PIXEL_FORMAT_NV21 = 3, 12 | PIXEL_FORMAT_BGRA32 = 4, 13 | PIXEL_FORMAT_RGBA32 = 5, 14 | PIXEL_FORMAT_ARGB32 = 6, 15 | PIXEL_FORMAT_ABGR32 = 7, 16 | PIXEL_FORMAT_I422 = 8, 17 | PIXEL_FORMAT_AVC_AVCC = 9, 18 | PIXEL_FORMAT_AVC_ANNEXB = 10, 19 | PIXEL_FORMAT_YUY2 = 11, 20 | PIXEL_FORMAT_UYVY = 12, 21 | }; 22 | 23 | struct VideoDataFormat 24 | { 25 | VideoDataFormat() 26 | { 27 | width = 0; 28 | height = 0; 29 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 30 | rotation = 0; 31 | pixel_format = PIXEL_FORMAT_UNKNOWN; 32 | } 33 | 34 | VideoDataFormat(int width, int height, VideoPixelFormat pixel_format) 35 | { 36 | this->width = width; 37 | this->height = height; 38 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 39 | rotation = 0; 40 | this->pixel_format = pixel_format; 41 | } 42 | 43 | bool operator==(const VideoDataFormat& other) 44 | { 45 | return (width == other.width && height == other.height && 46 | strides[0] == other.strides[0] && strides[1] == other.strides[1] && 47 | strides[2] == other.strides[2] && strides[3] == other.strides[3] && 48 | rotation == other.rotation && pixel_format == other.pixel_format); 49 | } 50 | 51 | bool operator!=(const VideoDataFormat& other) 52 | { 53 | return !(*this == other); 54 | } 55 | 56 | int width; 57 | int height; 58 | int strides[4]; 59 | int rotation; 60 | VideoPixelFormat pixel_format; 61 | }; 62 | } 63 | #endif /* ZEGOVideoFormat_h */ 64 | -------------------------------------------------------------------------------- /android/libs/arm64-v8a/include/zego-api-sdk-property.h: -------------------------------------------------------------------------------- 1 | #ifndef zego_api_sdk_property_h 2 | #define zego_api_sdk_property_h 3 | 4 | /// SDK version 5 | #define ZEGO_SDK_VERSION "6.16.2.25372-stable-221115-214357-49d0aee6dd" 6 | #define ZEGO_SDK_SEMANTIC_VERSION "6.16.2.25372" 7 | #define ZEGO_SDK_PROJECT "ZegoLiveRoom" 8 | 9 | /// Git repository commit revision 10 | #define ZEGO_SDK_EXPRESS_COMMIT_REVISION "5ac6360ac3" 11 | #define ZEGO_SDK_LIVEROOM_COMMIT_REVISION "49d0aee6dd" 12 | #define ZEGO_SDK_CONNECTION_COMMIT_REVISION "7901c1c178" 13 | 14 | #endif // zego_api_sdk_property_h 15 | -------------------------------------------------------------------------------- /android/libs/arm64-v8a/libZegoLiveRoom.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/android/libs/arm64-v8a/libZegoLiveRoom.so -------------------------------------------------------------------------------- /android/libs/armeabi-v7a/include/audio_capture.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOAudioCapture_h 2 | #define ZEGOAudioCapture_h 3 | 4 | namespace AVE { 5 | enum AudioBufferType { 6 | BufferTypeAudioApp = 0, 7 | BufferTypeAudioMic, 8 | }; 9 | 10 | struct AudioCaptureFormat { 11 | AudioCaptureFormat() : sample_rate(0), num_channels(0), bit_depth(0), is_big_endian(false) { 12 | } 13 | 14 | int sample_rate; 15 | int num_channels; 16 | int bit_depth; 17 | bool is_big_endian; 18 | }; 19 | 20 | class SupportsAudioCapture { 21 | public: 22 | 23 | }; 24 | 25 | class AudioCaptureCallback { 26 | public: 27 | virtual void OnCapturedAudioData(const char *pData, int data_len, 28 | const AudioCaptureFormat& format, 29 | AudioBufferType buffer_type, 30 | double timestamp_ms) = 0; 31 | virtual void SetMicVolume(int volume) = 0; 32 | virtual void SetAppVolume(int volume) = 0; 33 | }; 34 | } 35 | #endif /* ZEGOAudioCapture_h */ 36 | -------------------------------------------------------------------------------- /android/libs/armeabi-v7a/include/video_format.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOVideoFormat_h 2 | #define ZEGOVideoFormat_h 3 | 4 | namespace AVE 5 | { 6 | enum VideoPixelFormat 7 | { 8 | PIXEL_FORMAT_UNKNOWN = 0, 9 | PIXEL_FORMAT_I420 = 1, 10 | PIXEL_FORMAT_NV12 = 2, 11 | PIXEL_FORMAT_NV21 = 3, 12 | PIXEL_FORMAT_BGRA32 = 4, 13 | PIXEL_FORMAT_RGBA32 = 5, 14 | PIXEL_FORMAT_ARGB32 = 6, 15 | PIXEL_FORMAT_ABGR32 = 7, 16 | PIXEL_FORMAT_I422 = 8, 17 | PIXEL_FORMAT_AVC_AVCC = 9, 18 | PIXEL_FORMAT_AVC_ANNEXB = 10, 19 | PIXEL_FORMAT_YUY2 = 11, 20 | PIXEL_FORMAT_UYVY = 12, 21 | }; 22 | 23 | struct VideoDataFormat 24 | { 25 | VideoDataFormat() 26 | { 27 | width = 0; 28 | height = 0; 29 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 30 | rotation = 0; 31 | pixel_format = PIXEL_FORMAT_UNKNOWN; 32 | } 33 | 34 | VideoDataFormat(int width, int height, VideoPixelFormat pixel_format) 35 | { 36 | this->width = width; 37 | this->height = height; 38 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 39 | rotation = 0; 40 | this->pixel_format = pixel_format; 41 | } 42 | 43 | bool operator==(const VideoDataFormat& other) 44 | { 45 | return (width == other.width && height == other.height && 46 | strides[0] == other.strides[0] && strides[1] == other.strides[1] && 47 | strides[2] == other.strides[2] && strides[3] == other.strides[3] && 48 | rotation == other.rotation && pixel_format == other.pixel_format); 49 | } 50 | 51 | bool operator!=(const VideoDataFormat& other) 52 | { 53 | return !(*this == other); 54 | } 55 | 56 | int width; 57 | int height; 58 | int strides[4]; 59 | int rotation; 60 | VideoPixelFormat pixel_format; 61 | }; 62 | } 63 | #endif /* ZEGOVideoFormat_h */ 64 | -------------------------------------------------------------------------------- /android/libs/armeabi-v7a/include/zego-api-sdk-property.h: -------------------------------------------------------------------------------- 1 | #ifndef zego_api_sdk_property_h 2 | #define zego_api_sdk_property_h 3 | 4 | /// SDK version 5 | #define ZEGO_SDK_VERSION "6.16.2.25372-stable-221115-214357-49d0aee6dd" 6 | #define ZEGO_SDK_SEMANTIC_VERSION "6.16.2.25372" 7 | #define ZEGO_SDK_PROJECT "ZegoLiveRoom" 8 | 9 | /// Git repository commit revision 10 | #define ZEGO_SDK_EXPRESS_COMMIT_REVISION "5ac6360ac3" 11 | #define ZEGO_SDK_LIVEROOM_COMMIT_REVISION "49d0aee6dd" 12 | #define ZEGO_SDK_CONNECTION_COMMIT_REVISION "7901c1c178" 13 | 14 | #endif // zego_api_sdk_property_h 15 | -------------------------------------------------------------------------------- /android/libs/armeabi-v7a/libZegoLiveRoom.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/android/libs/armeabi-v7a/libZegoLiveRoom.so -------------------------------------------------------------------------------- /android/libs/x86/include/audio_capture.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOAudioCapture_h 2 | #define ZEGOAudioCapture_h 3 | 4 | namespace AVE { 5 | enum AudioBufferType { 6 | BufferTypeAudioApp = 0, 7 | BufferTypeAudioMic, 8 | }; 9 | 10 | struct AudioCaptureFormat { 11 | AudioCaptureFormat() : sample_rate(0), num_channels(0), bit_depth(0), is_big_endian(false) { 12 | } 13 | 14 | int sample_rate; 15 | int num_channels; 16 | int bit_depth; 17 | bool is_big_endian; 18 | }; 19 | 20 | class SupportsAudioCapture { 21 | public: 22 | 23 | }; 24 | 25 | class AudioCaptureCallback { 26 | public: 27 | virtual void OnCapturedAudioData(const char *pData, int data_len, 28 | const AudioCaptureFormat& format, 29 | AudioBufferType buffer_type, 30 | double timestamp_ms) = 0; 31 | virtual void SetMicVolume(int volume) = 0; 32 | virtual void SetAppVolume(int volume) = 0; 33 | }; 34 | } 35 | #endif /* ZEGOAudioCapture_h */ 36 | -------------------------------------------------------------------------------- /android/libs/x86/include/video_format.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOVideoFormat_h 2 | #define ZEGOVideoFormat_h 3 | 4 | namespace AVE 5 | { 6 | enum VideoPixelFormat 7 | { 8 | PIXEL_FORMAT_UNKNOWN = 0, 9 | PIXEL_FORMAT_I420 = 1, 10 | PIXEL_FORMAT_NV12 = 2, 11 | PIXEL_FORMAT_NV21 = 3, 12 | PIXEL_FORMAT_BGRA32 = 4, 13 | PIXEL_FORMAT_RGBA32 = 5, 14 | PIXEL_FORMAT_ARGB32 = 6, 15 | PIXEL_FORMAT_ABGR32 = 7, 16 | PIXEL_FORMAT_I422 = 8, 17 | PIXEL_FORMAT_AVC_AVCC = 9, 18 | PIXEL_FORMAT_AVC_ANNEXB = 10, 19 | PIXEL_FORMAT_YUY2 = 11, 20 | PIXEL_FORMAT_UYVY = 12, 21 | }; 22 | 23 | struct VideoDataFormat 24 | { 25 | VideoDataFormat() 26 | { 27 | width = 0; 28 | height = 0; 29 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 30 | rotation = 0; 31 | pixel_format = PIXEL_FORMAT_UNKNOWN; 32 | } 33 | 34 | VideoDataFormat(int width, int height, VideoPixelFormat pixel_format) 35 | { 36 | this->width = width; 37 | this->height = height; 38 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 39 | rotation = 0; 40 | this->pixel_format = pixel_format; 41 | } 42 | 43 | bool operator==(const VideoDataFormat& other) 44 | { 45 | return (width == other.width && height == other.height && 46 | strides[0] == other.strides[0] && strides[1] == other.strides[1] && 47 | strides[2] == other.strides[2] && strides[3] == other.strides[3] && 48 | rotation == other.rotation && pixel_format == other.pixel_format); 49 | } 50 | 51 | bool operator!=(const VideoDataFormat& other) 52 | { 53 | return !(*this == other); 54 | } 55 | 56 | int width; 57 | int height; 58 | int strides[4]; 59 | int rotation; 60 | VideoPixelFormat pixel_format; 61 | }; 62 | } 63 | #endif /* ZEGOVideoFormat_h */ 64 | -------------------------------------------------------------------------------- /android/libs/x86/include/zego-api-sdk-property.h: -------------------------------------------------------------------------------- 1 | #ifndef zego_api_sdk_property_h 2 | #define zego_api_sdk_property_h 3 | 4 | /// SDK version 5 | #define ZEGO_SDK_VERSION "6.16.2.25372-stable-221115-214357-49d0aee6dd" 6 | #define ZEGO_SDK_SEMANTIC_VERSION "6.16.2.25372" 7 | #define ZEGO_SDK_PROJECT "ZegoLiveRoom" 8 | 9 | /// Git repository commit revision 10 | #define ZEGO_SDK_EXPRESS_COMMIT_REVISION "5ac6360ac3" 11 | #define ZEGO_SDK_LIVEROOM_COMMIT_REVISION "49d0aee6dd" 12 | #define ZEGO_SDK_CONNECTION_COMMIT_REVISION "7901c1c178" 13 | 14 | #endif // zego_api_sdk_property_h 15 | -------------------------------------------------------------------------------- /android/libs/x86/libZegoLiveRoom.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/android/libs/x86/libZegoLiveRoom.so -------------------------------------------------------------------------------- /android/libs/x86_64/include/audio_capture.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOAudioCapture_h 2 | #define ZEGOAudioCapture_h 3 | 4 | namespace AVE { 5 | enum AudioBufferType { 6 | BufferTypeAudioApp = 0, 7 | BufferTypeAudioMic, 8 | }; 9 | 10 | struct AudioCaptureFormat { 11 | AudioCaptureFormat() : sample_rate(0), num_channels(0), bit_depth(0), is_big_endian(false) { 12 | } 13 | 14 | int sample_rate; 15 | int num_channels; 16 | int bit_depth; 17 | bool is_big_endian; 18 | }; 19 | 20 | class SupportsAudioCapture { 21 | public: 22 | 23 | }; 24 | 25 | class AudioCaptureCallback { 26 | public: 27 | virtual void OnCapturedAudioData(const char *pData, int data_len, 28 | const AudioCaptureFormat& format, 29 | AudioBufferType buffer_type, 30 | double timestamp_ms) = 0; 31 | virtual void SetMicVolume(int volume) = 0; 32 | virtual void SetAppVolume(int volume) = 0; 33 | }; 34 | } 35 | #endif /* ZEGOAudioCapture_h */ 36 | -------------------------------------------------------------------------------- /android/libs/x86_64/include/video_format.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEGOVideoFormat_h 2 | #define ZEGOVideoFormat_h 3 | 4 | namespace AVE 5 | { 6 | enum VideoPixelFormat 7 | { 8 | PIXEL_FORMAT_UNKNOWN = 0, 9 | PIXEL_FORMAT_I420 = 1, 10 | PIXEL_FORMAT_NV12 = 2, 11 | PIXEL_FORMAT_NV21 = 3, 12 | PIXEL_FORMAT_BGRA32 = 4, 13 | PIXEL_FORMAT_RGBA32 = 5, 14 | PIXEL_FORMAT_ARGB32 = 6, 15 | PIXEL_FORMAT_ABGR32 = 7, 16 | PIXEL_FORMAT_I422 = 8, 17 | PIXEL_FORMAT_AVC_AVCC = 9, 18 | PIXEL_FORMAT_AVC_ANNEXB = 10, 19 | PIXEL_FORMAT_YUY2 = 11, 20 | PIXEL_FORMAT_UYVY = 12, 21 | }; 22 | 23 | struct VideoDataFormat 24 | { 25 | VideoDataFormat() 26 | { 27 | width = 0; 28 | height = 0; 29 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 30 | rotation = 0; 31 | pixel_format = PIXEL_FORMAT_UNKNOWN; 32 | } 33 | 34 | VideoDataFormat(int width, int height, VideoPixelFormat pixel_format) 35 | { 36 | this->width = width; 37 | this->height = height; 38 | strides[0] = strides[1] = strides[2] = strides[3] = 0; 39 | rotation = 0; 40 | this->pixel_format = pixel_format; 41 | } 42 | 43 | bool operator==(const VideoDataFormat& other) 44 | { 45 | return (width == other.width && height == other.height && 46 | strides[0] == other.strides[0] && strides[1] == other.strides[1] && 47 | strides[2] == other.strides[2] && strides[3] == other.strides[3] && 48 | rotation == other.rotation && pixel_format == other.pixel_format); 49 | } 50 | 51 | bool operator!=(const VideoDataFormat& other) 52 | { 53 | return !(*this == other); 54 | } 55 | 56 | int width; 57 | int height; 58 | int strides[4]; 59 | int rotation; 60 | VideoPixelFormat pixel_format; 61 | }; 62 | } 63 | #endif /* ZEGOVideoFormat_h */ 64 | -------------------------------------------------------------------------------- /android/libs/x86_64/include/zego-api-sdk-property.h: -------------------------------------------------------------------------------- 1 | #ifndef zego_api_sdk_property_h 2 | #define zego_api_sdk_property_h 3 | 4 | /// SDK version 5 | #define ZEGO_SDK_VERSION "6.16.2.25372-stable-221115-214357-49d0aee6dd" 6 | #define ZEGO_SDK_SEMANTIC_VERSION "6.16.2.25372" 7 | #define ZEGO_SDK_PROJECT "ZegoLiveRoom" 8 | 9 | /// Git repository commit revision 10 | #define ZEGO_SDK_EXPRESS_COMMIT_REVISION "5ac6360ac3" 11 | #define ZEGO_SDK_LIVEROOM_COMMIT_REVISION "49d0aee6dd" 12 | #define ZEGO_SDK_CONNECTION_COMMIT_REVISION "7901c1c178" 13 | 14 | #endif // zego_api_sdk_property_h 15 | -------------------------------------------------------------------------------- /android/libs/x86_64/libZegoLiveRoom.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/android/libs/x86_64/libZegoLiveRoom.so -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'zegoliveroom_plugin' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/cpp/zego_log_jni.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../../../zego_defines.h" 4 | 5 | std::string jstring2string(JNIEnv* env, jstring jstr) 6 | { 7 | jclass strClass = env->FindClass("java/lang/String"); 8 | jstring encoding = env->NewStringUTF("UTF-8"); 9 | jmethodID methodId = env->GetMethodID(strClass, "getBytes", "(Ljava/lang/String;)[B"); 10 | jbyteArray byteArr = (jbyteArray)env->CallObjectMethod(jstr, methodId, encoding); // String .getByte("UTF-8"); 11 | jsize arrLength = env->GetArrayLength(byteArr); //获取长度 12 | jbyte* bytePtr = env->GetByteArrayElements(byteArr, JNI_FALSE); // jbyteArray 转为 jbyte* 13 | 14 | std::string str{(char *)bytePtr, (size_t)arrLength}; 15 | 16 | env->ReleaseByteArrayElements(byteArr, bytePtr, 0); //释放掉 17 | env->DeleteLocalRef(byteArr); 18 | env->DeleteLocalRef(encoding); 19 | env->DeleteLocalRef(strClass); 20 | 21 | return str; 22 | } 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | JNIEXPORT void JNICALL Java_com_zego_zegoliveroomplugin_ZegoLogJNI_logNotice(JNIEnv *env, jclass, jstring content) { 29 | 30 | std::string strContent = jstring2string(env, content); 31 | return ZegoExternalLogWithNotice(strContent.c_str()); 32 | } 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/ZegoLogJNI.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin; 2 | 3 | final public class ZegoLogJNI { 4 | static { 5 | System.loadLibrary("ZegoLog"); 6 | } 7 | 8 | public static native void logNotice(String content); 9 | } 10 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/ZegoPlatformView.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin; 2 | 3 | import android.content.Context; 4 | import android.view.Surface; 5 | import android.view.SurfaceHolder; 6 | import android.view.SurfaceView; 7 | import android.view.View; 8 | 9 | import io.flutter.plugin.platform.PlatformView; 10 | 11 | public class ZegoPlatformView implements PlatformView, SurfaceHolder.Callback { 12 | 13 | private SurfaceView mSurfaceView; 14 | private int mViewID; 15 | 16 | public ZegoPlatformView(Context context, int viewID) { 17 | this.mViewID = viewID; 18 | this.mSurfaceView = new SurfaceView(context); 19 | this.mSurfaceView.getHolder().addCallback(this); 20 | 21 | ZegoLogJNI.logNotice("[ZegoPlatformView] new, viewID: " + viewID + ", context: " + context); 22 | 23 | } 24 | 25 | public SurfaceView getSurfaceView() { 26 | return mSurfaceView; 27 | } 28 | 29 | @Override 30 | public View getView() { 31 | return mSurfaceView; 32 | } 33 | 34 | @Override 35 | public void dispose() { 36 | ZegoLogJNI.logNotice("[ZegoPlatformView] dispose, viewID: " + mViewID); 37 | if(mSurfaceView != null) { 38 | mSurfaceView.getHolder().removeCallback(this); 39 | Surface surface = mSurfaceView.getHolder().getSurface(); 40 | if(surface != null) 41 | surface.release(); 42 | 43 | mSurfaceView = null; 44 | } 45 | } 46 | 47 | @Override 48 | public void surfaceCreated(SurfaceHolder holder) { 49 | ZegoLogJNI.logNotice("[ZegoPlatformView] onSurfaceCreated, viewID: " + mViewID); 50 | } 51 | 52 | @Override 53 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 54 | ZegoLogJNI.logNotice("[ZegoPlatformView] onSurfaceChanged, viewID: " + mViewID + ", size: (" + width + ", " + height + ")" + ", format: " + format); 55 | } 56 | 57 | @Override 58 | public void surfaceDestroyed(SurfaceHolder holder) { 59 | ZegoLogJNI.logNotice("[ZegoPlatformView] onSurfaceDestroyed"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/ZegoPlatformViewFactory.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin; 2 | 3 | import android.content.Context; 4 | 5 | import java.util.HashMap; 6 | 7 | import io.flutter.plugin.common.MessageCodec; 8 | import io.flutter.plugin.common.StandardMessageCodec; 9 | import io.flutter.plugin.platform.PlatformView; 10 | import io.flutter.plugin.platform.PlatformViewFactory; 11 | 12 | public class ZegoPlatformViewFactory extends PlatformViewFactory{ 13 | 14 | private static ZegoPlatformViewFactory sInstance; 15 | 16 | private HashMap mViews; 17 | 18 | public static ZegoPlatformViewFactory shareInstance() { 19 | if(sInstance == null) { 20 | sInstance = new ZegoPlatformViewFactory(StandardMessageCodec.INSTANCE); 21 | ZegoLogJNI.logNotice("[ZegoPlatformViewFactory] instance init"); 22 | } 23 | 24 | return sInstance; 25 | } 26 | 27 | private ZegoPlatformViewFactory(MessageCodec createArgsCodec) { 28 | super(createArgsCodec); 29 | mViews = new HashMap<>(); 30 | } 31 | 32 | public void addView(int viewID, ZegoPlatformView view) { 33 | ZegoLogJNI.logNotice("[ZegoPlatformViewFactory] addView: " + viewID); 34 | mViews.put(Integer.valueOf(viewID), view); 35 | } 36 | 37 | public boolean removeView(int viewID) { 38 | 39 | if(!mViews.containsKey(Integer.valueOf(viewID))) { 40 | ZegoLogJNI.logNotice("[ZegoPlatformViewFactory] removeView failed, no such view: " + viewID); 41 | return false; 42 | } 43 | 44 | ZegoLogJNI.logNotice("[ZegoPlatformViewFactory] removeView: " + viewID); 45 | mViews.remove(Integer.valueOf(viewID)); 46 | return true; 47 | } 48 | 49 | public ZegoPlatformView getPlatformView(int viewID) { 50 | ZegoLogJNI.logNotice("[ZegoPlatformViewFactory] getView: " + viewID); 51 | return mViews.get(Integer.valueOf(viewID)); 52 | } 53 | 54 | @Override 55 | public PlatformView create(Context context, int viewID, Object args) { 56 | ZegoLogJNI.logNotice("[ZegoPlatformViewFactory] create view, viewID: " + viewID); 57 | ZegoPlatformView view = new ZegoPlatformView(context, viewID); 58 | addView(viewID, view); 59 | 60 | return view; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/ZegoViewRenderer.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.view.Surface; 5 | import io.flutter.view.TextureRegistry; 6 | 7 | 8 | public class ZegoViewRenderer { 9 | 10 | private final TextureRegistry.SurfaceTextureEntry textureEntry; 11 | 12 | private final long mTextureID; 13 | private SurfaceTexture surfaceTexture; 14 | private Surface surface; 15 | 16 | private int mViewWidth; 17 | private int mViewHeight; 18 | 19 | private boolean mIsInited; 20 | 21 | 22 | public ZegoViewRenderer(TextureRegistry.SurfaceTextureEntry textureEntry, 23 | int viewWidth, 24 | int viewHeight) { 25 | this.textureEntry = textureEntry; 26 | this.mTextureID = textureEntry.id(); 27 | this.surfaceTexture = textureEntry.surfaceTexture(); 28 | this.surfaceTexture.setDefaultBufferSize(viewWidth, viewHeight); 29 | this.surface = new Surface(this.surfaceTexture); 30 | 31 | this.mViewWidth = viewWidth; 32 | this.mViewHeight = viewHeight; 33 | 34 | 35 | init(); 36 | } 37 | 38 | public void init() { 39 | mIsInited = true; 40 | } 41 | 42 | public void release() { 43 | 44 | textureEntry.release(); 45 | 46 | if(surface != null) { 47 | surface.release(); 48 | } 49 | 50 | 51 | 52 | mIsInited = false; 53 | } 54 | 55 | public boolean updateRenderSize(final int width, final int height) { 56 | 57 | if(mViewWidth != width || mViewHeight != height) { 58 | mViewWidth = width; 59 | mViewHeight = height; 60 | 61 | surfaceTexture.setDefaultBufferSize(mViewWidth, mViewHeight); 62 | surface.release(); 63 | 64 | surface = new Surface(surfaceTexture); 65 | 66 | return true; 67 | } 68 | 69 | return false; 70 | } 71 | 72 | public Surface getSurface() { 73 | return surface; 74 | } 75 | 76 | public long getTextureID() { 77 | return mTextureID; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/constants/ZegoEventType.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin.constants; 2 | 3 | public class ZegoEventType { 4 | 5 | public static final int TYPE_ROOM_EVENT = 0; 6 | public static final int TYPE_PUBLISH_EVENT = 1; 7 | public static final int TYPE_PLAY_EVENT = 2; 8 | public static final int TYPE_MEDIA_SIDE_INFO_EVENT = 3; 9 | public static final int TYPE_SOUND_LEVEL_EVENT = 4; 10 | public static final int TYPE_MEDIA_PLAYER_EVENT = 5; 11 | public static final int TYPE_AUDIO_PLAYER_EVENT = 10; 12 | public static final int TYPE_MEDIA_RECORD_EVENT = 11; 13 | } 14 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/module/audioplayer/IZegoAudioPlayerControllerCallback.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin.module.audioplayer; 2 | 3 | public interface IZegoAudioPlayerControllerCallback { 4 | void onAudioPlayEnd(int soundID); 5 | void onAudioPlayBegin(int soundID,int errorCode); 6 | void onAudioLoad(int soundID,int errorCode); 7 | void onAudioLoadComplete(int soundID); 8 | } 9 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/module/mediaplayer/IZegoMediaPlayerControllerCallback.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin.module.mediaplayer; 2 | 3 | public interface IZegoMediaPlayerControllerCallback { 4 | void onPlayEnd(int playerIndex); 5 | 6 | void onPlayError(int errorCode,int playerIndex); 7 | 8 | void onBufferBegin(int playerIndex); 9 | 10 | void onBufferEnd(int playerIndex); 11 | 12 | void onProcessInterval(long timestamp,int playerIndex); 13 | 14 | void onPlayBegin(int playerIndex); 15 | 16 | void onPlayStop(int playerIndex); 17 | 18 | void onPlayPause(int playerIndex); 19 | 20 | void onPlayResume(int playerIndex); 21 | 22 | void onSeekComplete(int errorCode, long millisecond,int playerIndex); 23 | 24 | void onAudioBegin(int playerIndex); 25 | 26 | void onVideoBegin(int playerIndex); 27 | } 28 | -------------------------------------------------------------------------------- /android/src/main/java/com/zego/zegoliveroomplugin/utils/ZegoFileHelper.java: -------------------------------------------------------------------------------- 1 | package com.zego.zegoliveroomplugin.utils; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.File; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | public class ZegoFileHelper { 11 | /** 12 | * 将文件从assets目录,拷贝到 /data/data/包名/files/ 目录中。assets 目录中的文件,会不经压缩打包至APK包中,使用时还应从apk包中导出来 13 | * 14 | * @param context 上下文对象 15 | * @param fileName 文件名,如aaa.txt 16 | */ 17 | public static String copyAssetsFile2Phone(Context context, String fileName) { 18 | InputStream inputStream = null; 19 | FileOutputStream fos = null; 20 | try { 21 | // getFilesDir() 获得当前APP的安装路径 /data/data/包名/files 目录 22 | File file = new File(context.getFilesDir().getAbsolutePath() + File.separator + fileName); 23 | inputStream = context.getAssets().open(fileName); 24 | 25 | // 如果文件不存在(新建),或者文件大小不一致(覆盖) 26 | if (!file.exists() || file.length() != inputStream.available()) { 27 | //如果文件不存在,FileOutputStream会自动创建文件 28 | File folder = file.getParentFile(); 29 | if (!folder.exists()) { 30 | folder.mkdirs(); 31 | } 32 | 33 | fos = new FileOutputStream(file); 34 | int len; 35 | byte[] buffer = new byte[1024 * 8]; 36 | while ((len = inputStream.read(buffer)) != -1) { 37 | fos.write(buffer, 0, len); 38 | } 39 | fos.flush();//刷新缓存区 40 | } 41 | return file.getPath(); 42 | } catch (IOException e) { 43 | e.printStackTrace(); 44 | } finally { 45 | if (inputStream != null) { 46 | try { 47 | inputStream.close(); 48 | } catch (IOException ignore) { 49 | } 50 | } 51 | if (fos != null) { 52 | try { 53 | fos.close(); 54 | } catch (IOException ignore) { 55 | } 56 | } 57 | } 58 | return null; 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # Visual Studio Code related 19 | .vscode/ 20 | 21 | # Flutter/Dart/Pub related 22 | **/doc/api/ 23 | .dart_tool/ 24 | .flutter-plugins 25 | .flutter-plugins-dependencies 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | /build/ 30 | pubspec.lock 31 | 32 | # Android related 33 | **/android/**/gradle-wrapper.jar 34 | **/android/.gradle 35 | **/android/**/.settings 36 | **/android/**/.project 37 | **/android/captures/ 38 | **/android/gradlew 39 | **/android/gradlew.bat 40 | **/android/local.properties 41 | **/android/**/.classpath 42 | **/android/**/GeneratedPluginRegistrant.java 43 | 44 | # iOS/XCode related 45 | **/ios/**/*.mode1v3 46 | **/ios/**/*.mode2v3 47 | **/ios/**/*.moved-aside 48 | **/ios/**/*.pbxuser 49 | **/ios/**/*.perspectivev3 50 | **/ios/**/*sync/ 51 | **/ios/**/.sconsign.dblite 52 | **/ios/**/.tags* 53 | **/ios/**/.vagrant/ 54 | **/ios/**/DerivedData/ 55 | **/ios/**/Icon? 56 | **/ios/**/Pods/ 57 | **/ios/**/.symlinks/ 58 | **/ios/**/profile 59 | **/ios/**/xcuserdata 60 | **/ios/.generated/ 61 | **/ios/Flutter/.last_build_id 62 | **/ios/Flutter/App.framework 63 | **/ios/Flutter/Flutter.framework 64 | **/ios/Flutter/Generated.xcconfig 65 | **/ios/Flutter/app.flx 66 | **/ios/Flutter/app.zip 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/Flutter/flutter_assets/ 69 | **/ios/ServiceDefinitions.json 70 | **/ios/Runner/GeneratedPluginRegistrant.* 71 | **/ios/Podfile.lock 72 | 73 | # Exceptions to above rules. 74 | !**/ios/**/default.mode1v3 75 | !**/ios/**/default.mode2v3 76 | !**/ios/**/default.pbxuser 77 | !**/ios/**/default.perspectivev3 78 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 79 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 88fa7ea4031f5c86225573e58e5558dc4ea1c251 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # zegoliveroom_plugin_example 2 | 3 | Demonstrates how to use the zegoliveroom_plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/android/app/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | applicationId "com.zego.flutter.example" 36 | minSdkVersion 16 37 | targetSdkVersion 28 38 | versionCode flutterVersionCode.toInteger() 39 | versionName flutterVersionName 40 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 41 | } 42 | 43 | buildTypes { 44 | debug { 45 | signingConfig signingConfigs.debug 46 | 47 | ndk { 48 | //debug 版本 libflutter.so 支持多种架构 49 | abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86' 50 | } 51 | } 52 | 53 | release { 54 | // TODO: Add your own signing config for the release build. 55 | // Signing with the debug keys for now, so `flutter run --release` works. 56 | signingConfig signingConfigs.debug 57 | minifyEnabled true // 混淆 58 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 59 | ndk { 60 | //release 版本 libflutter.so 不能同时支持32位与64位架构,因此都使用armeabi-v7a,避免64位架构打开出现闪退问题 61 | abiFilters 'armeabi-v7a' 62 | } 63 | } 64 | } 65 | } 66 | 67 | flutter { 68 | source '../..' 69 | } 70 | dependencies { 71 | testImplementation 'junit:junit:4.12' 72 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 73 | implementation files('../../../android/libs/ZegoLiveRoom.jar') 74 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' 75 | implementation 'com.tencent.bugly:crashreport:2.6.6' 76 | implementation 'com.tencent.bugly:nativecrashreport:3.3.1' 77 | } 78 | -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -keep class com.zego.**{*;} 24 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 28 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/ExternalVideoFilter/VideoFilter/VideoFilterAsyncI420MemDemo.java: -------------------------------------------------------------------------------- 1 | package com.zego.ExternalVideoFilter.VideoFilter; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.os.Build; 5 | import android.os.Handler; 6 | import android.os.HandlerThread; 7 | import android.util.Log; 8 | 9 | import com.zego.zegoavkit2.videofilter.ZegoVideoFilter; 10 | 11 | import java.nio.ByteBuffer; 12 | import java.util.ArrayList; 13 | import java.util.concurrent.ConcurrentLinkedQueue; 14 | import java.util.concurrent.CountDownLatch; 15 | 16 | /** 17 | * Created by robotding on 17/5/3. 18 | */ 19 | 20 | public class VideoFilterAsyncI420MemDemo extends ZegoVideoFilter { 21 | private static final String TAG = "VideoFilterMemDemo"; 22 | 23 | private ZegoVideoFilter.Client mClient = null; 24 | private HandlerThread mThread = null; 25 | private volatile Handler mHandler = null; 26 | 27 | static class PixelBuffer { 28 | public int width; 29 | public int height; 30 | public int stride; 31 | public long timestamp_100n; 32 | public ByteBuffer buffer; 33 | } 34 | private ArrayList mProduceQueue = new ArrayList(); 35 | private int mWriteIndex = 0; 36 | private int mWriteRemain = 0; 37 | private ConcurrentLinkedQueue mConsumeQueue = new ConcurrentLinkedQueue(); 38 | private int mMaxBufferSize = 0; 39 | 40 | private boolean mIsRunning = false; 41 | 42 | @Override 43 | protected void allocateAndStart(Client client) { 44 | mClient = client; 45 | mThread = new HandlerThread("video-filter"); 46 | mThread.start(); 47 | mHandler = new Handler(mThread.getLooper()); 48 | mIsRunning = true; 49 | 50 | mProduceQueue.clear(); 51 | mConsumeQueue.clear(); 52 | mWriteIndex = 0; 53 | mWriteRemain = 0; 54 | mMaxBufferSize = 0; 55 | } 56 | 57 | @Override 58 | protected void stopAndDeAllocate() { 59 | mIsRunning = false; 60 | 61 | final CountDownLatch barrier = new CountDownLatch(1); 62 | mHandler.post(new Runnable() { 63 | @Override 64 | public void run() { 65 | barrier.countDown(); 66 | } 67 | }); 68 | try { 69 | barrier.await(); 70 | } catch (InterruptedException e) { 71 | e.printStackTrace(); 72 | } 73 | mHandler = null; 74 | 75 | if (Build.VERSION.SDK_INT >= 18) { 76 | mThread.quitSafely(); 77 | } else { 78 | mThread.quit(); 79 | } 80 | mThread = null; 81 | 82 | mClient.destroy(); 83 | mClient = null; 84 | } 85 | 86 | @Override 87 | protected int supportBufferType() { 88 | return BUFFER_TYPE_ASYNC_I420_MEM; 89 | } 90 | 91 | @Override 92 | protected synchronized int dequeueInputBuffer(int width, int height, int stride) { 93 | if (stride * height * 3 / 2 > mMaxBufferSize) { 94 | if (mMaxBufferSize != 0) { 95 | mProduceQueue.clear(); 96 | } 97 | 98 | mMaxBufferSize = stride * height * 3 / 2; 99 | createPixelBufferPool(3); 100 | } 101 | 102 | if (mWriteRemain == 0) { 103 | return -1; 104 | } 105 | 106 | mWriteRemain--; 107 | return (mWriteIndex + 1) % mProduceQueue.size(); 108 | } 109 | 110 | @Override 111 | protected synchronized ByteBuffer getInputBuffer(int index) { 112 | if (mProduceQueue.isEmpty()) { 113 | return null; 114 | } 115 | ByteBuffer buffer = mProduceQueue.get(index).buffer; 116 | buffer.position(0); 117 | return buffer; 118 | } 119 | 120 | @Override 121 | protected synchronized void queueInputBuffer(int bufferIndex, final int width, int height, int stride, long timestamp_100n) { 122 | if (bufferIndex == -1) { 123 | return ; 124 | } 125 | 126 | PixelBuffer pixelBuffer = mProduceQueue.get(bufferIndex); 127 | pixelBuffer.width = width; 128 | pixelBuffer.height = height; 129 | pixelBuffer.stride = stride; 130 | pixelBuffer.timestamp_100n = timestamp_100n; 131 | pixelBuffer.buffer.limit(height * stride * 3 / 2); 132 | mConsumeQueue.add(pixelBuffer); 133 | 134 | mWriteIndex = (mWriteIndex + 1) % mProduceQueue.size(); 135 | 136 | mHandler.post(new Runnable() { 137 | @Override 138 | public void run() { 139 | if (!mIsRunning) { 140 | Log.e(TAG, "already stopped"); 141 | return ; 142 | } 143 | 144 | PixelBuffer pixelBuffer = getConsumerPixelBuffer(); 145 | 146 | int index = mClient.dequeueInputBuffer(pixelBuffer.width, pixelBuffer.height, pixelBuffer.stride); 147 | if (index >= 0) { 148 | ByteBuffer dst = mClient.getInputBuffer(index); 149 | dst.position(0); 150 | pixelBuffer.buffer.position(0); 151 | dst.put(pixelBuffer.buffer); 152 | 153 | mClient.queueInputBuffer(index, pixelBuffer.width, pixelBuffer.height, pixelBuffer.stride, pixelBuffer.timestamp_100n); 154 | } 155 | 156 | returnProducerPixelBuffer(pixelBuffer); 157 | } 158 | }); 159 | } 160 | 161 | @Override 162 | protected SurfaceTexture getSurfaceTexture() { 163 | return null; 164 | } 165 | 166 | @Override 167 | protected void onProcessCallback(int textureId, int width, int height, long timestamp_100n) { 168 | 169 | } 170 | 171 | private void createPixelBufferPool(int count) { 172 | for (int i = 0; i < count; i++) { 173 | PixelBuffer pixelBuffer = new PixelBuffer(); 174 | pixelBuffer.buffer = ByteBuffer.allocateDirect(mMaxBufferSize); 175 | mProduceQueue.add(pixelBuffer); 176 | } 177 | 178 | mWriteRemain = count; 179 | mWriteIndex = -1; 180 | } 181 | 182 | private PixelBuffer getConsumerPixelBuffer() { 183 | if (mConsumeQueue.isEmpty()) { 184 | return null; 185 | } 186 | return mConsumeQueue.poll(); 187 | } 188 | 189 | private synchronized void returnProducerPixelBuffer(PixelBuffer pixelBuffer) { 190 | if (pixelBuffer.buffer.capacity() == mMaxBufferSize) { 191 | mWriteRemain++; 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/ExternalVideoFilter/VideoFilter/VideoFilterSyncGlTexture2dDemo.java: -------------------------------------------------------------------------------- 1 | package com.zego.ExternalVideoFilter.VideoFilter; 2 | 3 | import android.graphics.SurfaceTexture; 4 | import android.opengl.GLES20; 5 | 6 | import com.zego.ExternalVideoFilter.ve_gl.GlRectDrawer; 7 | import com.zego.ExternalVideoFilter.ve_gl.GlUtil; 8 | import com.zego.zegoavkit2.videofilter.ZegoVideoFilter; 9 | 10 | import java.nio.ByteBuffer; 11 | 12 | /** 13 | * 外部滤镜采用 BUFFER_TYPE_SYNC_GL_TEXTURE_2D(同步传递 texture2d)方式传递数据给 SDK。 14 | * 15 | * SDK 不推荐采用同步滤镜(BUFFER_TYPE_SYNC_GL_TEXTURE_2D)实现外部滤镜, 16 | * 因为在同一线程中,OpenGL ES 的上下文、设置、uniform、attribute 是共用的, 17 | * 倘若对 OpenGL ES 不是很熟悉,极易在细节上出现不可预知的 Bug。 18 | * 19 | * Created by robotding on 17/2/23. 20 | */ 21 | 22 | public class VideoFilterSyncGlTexture2dDemo extends ZegoVideoFilter { 23 | // SDK 内部实现 ZegoVideoFilter.Client 协议的对象 24 | private ZegoVideoFilter.Client mClient = null; 25 | 26 | private GlRectDrawer mDrawer; 27 | private int mTextureId = 0; 28 | private int mFrameBufferId = 0; 29 | private float[] transformationMatrix = new float[]{1.0f, 0.0f, 0.0f, 0.0f, 30 | 0.0f, 1.0f, 0.0f, 0.0f, 31 | 0.0f, 0.0f, 1.0f, 0.0f, 32 | 0.0f, 0.0f, 0.0f, 1.0f}; 33 | 34 | private int mWidth = 0; 35 | private int mHeight = 0; 36 | 37 | /** 38 | * 初始化资源,比如图像绘制、美颜组件等 39 | * @param client SDK 内部实现 ZegoVideoFilter.Client 协议的对象 40 | * 41 | * 注意:client 必须保存为强引用对象,在 stopAndDeAllocate 被调用前必须一直被保存。 42 | * SDK 不负责管理 client 的生命周期。 43 | */ 44 | @Override 45 | protected void allocateAndStart(Client client) { 46 | mClient = client; 47 | mWidth = mHeight = 0; 48 | if (mDrawer == null) { 49 | mDrawer = new GlRectDrawer(); 50 | } 51 | } 52 | 53 | /** 54 | * 释放资源 55 | * 注意:必须调用 client 的 destroy 方法,否则会造成内存泄漏。 56 | */ 57 | @Override 58 | protected void stopAndDeAllocate() { 59 | if (mTextureId != 0) { 60 | int[] textures = new int[]{mTextureId}; 61 | GLES20.glDeleteTextures(1, textures, 0); 62 | mTextureId = 0; 63 | } 64 | 65 | if (mFrameBufferId != 0) { 66 | int[] frameBuffers = new int[]{mFrameBufferId}; 67 | GLES20.glDeleteFramebuffers(1, frameBuffers, 0); 68 | mFrameBufferId = 0; 69 | } 70 | 71 | if (mDrawer != null) { 72 | mDrawer.release(); 73 | mDrawer = null; 74 | } 75 | 76 | // 建议在同步停止滤镜任务后再清理 client 对象,保证 SDK 调用 stopAndDeAllocate 后,没有残留的异步任务导致野指针 crash 77 | mClient.destroy(); 78 | mClient = null; 79 | } 80 | 81 | /** 82 | * 指定滤镜的传递数据类型,同步传递 texture2d 83 | * SDK 需要根据 supportBufferType 返回的类型值创建不同的 client 对象。 84 | * @return 返回类型值 85 | */ 86 | @Override 87 | protected int supportBufferType() { 88 | return BUFFER_TYPE_SYNC_GL_TEXTURE_2D; 89 | } 90 | 91 | @Override 92 | protected int dequeueInputBuffer(int width, int height, int stride) { 93 | return 0; 94 | } 95 | 96 | @Override 97 | protected ByteBuffer getInputBuffer(int index) { 98 | return null; 99 | } 100 | 101 | @Override 102 | protected void queueInputBuffer(int bufferIndex, int width, int height, int stride, long timestamp_100n) { 103 | 104 | } 105 | 106 | @Override 107 | protected SurfaceTexture getSurfaceTexture() { 108 | return null; 109 | } 110 | 111 | /** 112 | * 绘制图像 113 | * @param textureId SDK 采集数据的纹理 ID 114 | * @param width 图像数据宽 115 | * @param height 图像数据高 116 | * @param timestamp_100n 时间戳 117 | */ 118 | @Override 119 | protected void onProcessCallback(int textureId, int width, int height, long timestamp_100n) { 120 | if (mWidth != width || mHeight != height) { 121 | if (mTextureId != 0) { 122 | int[] textures = new int[]{mTextureId}; 123 | GLES20.glDeleteTextures(1, textures, 0); 124 | mTextureId = 0; 125 | } 126 | 127 | if (mFrameBufferId != 0) { 128 | int[] frameBuffers = new int[]{mFrameBufferId}; 129 | GLES20.glDeleteFramebuffers(1, frameBuffers, 0); 130 | mFrameBufferId = 0; 131 | } 132 | 133 | mWidth = width; 134 | mHeight = height; 135 | } 136 | 137 | if (mTextureId == 0) { 138 | GLES20.glActiveTexture(GLES20.GL_TEXTURE1); 139 | mTextureId = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D); 140 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); 141 | 142 | mFrameBufferId = GlUtil.generateFrameBuffer(mTextureId); 143 | } else { 144 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferId); 145 | } 146 | 147 | GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 148 | mDrawer.drawRgb(textureId, transformationMatrix, 149 | width, height, 0, 0, width, height); 150 | 151 | // 使用此 textureId 用做本地预览的视图渲染 152 | mClient.onProcessCallback(textureId, width, height, timestamp_100n); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/ExternalVideoFilter/VideoFilterFactoryDemo.java: -------------------------------------------------------------------------------- 1 | package com.zego.ExternalVideoFilter; 2 | 3 | /** 4 | * Created by Patrick Fu on 2020-03-05. 5 | */ 6 | 7 | import com.zego.zegoavkit2.videofilter.ZegoVideoFilterFactory; 8 | import com.zego.zegoavkit2.videofilter.ZegoVideoFilter; 9 | 10 | import com.zego.ExternalVideoFilter.VideoFilter.*; 11 | 12 | public class VideoFilterFactoryDemo extends ZegoVideoFilterFactory { 13 | 14 | public FilterType filterType = FilterType.FilterTypeSurfaceTexture; 15 | 16 | private ZegoVideoFilter mFilter = null; 17 | 18 | // 外部滤镜类型枚举 19 | public enum FilterType { 20 | FilterTypeMem, 21 | FilterTypeHybridMem, 22 | FilterTypeSyncGLTexture2D, 23 | FilterTypeSurfaceTexture, 24 | FilterTypeAsyncI420Mem 25 | } 26 | 27 | // 创建外部滤镜实例 28 | public ZegoVideoFilter create() { 29 | switch (filterType) { 30 | case FilterTypeMem: 31 | mFilter = new VideoFilterMemDemo(); 32 | break; 33 | case FilterTypeHybridMem: 34 | mFilter = new VideoFilterHybridDemo(); 35 | break; 36 | case FilterTypeSyncGLTexture2D: 37 | mFilter = new VideoFilterSyncGlTexture2dDemo(); 38 | break; 39 | case FilterTypeSurfaceTexture: 40 | mFilter = new VideoFilterSurfaceTextureDemo(); 41 | break; 42 | case FilterTypeAsyncI420Mem: 43 | mFilter = new VideoFilterAsyncI420MemDemo(); 44 | break; 45 | } 46 | 47 | return mFilter; 48 | } 49 | 50 | // 销毁外部滤镜实例 51 | public void destroy(ZegoVideoFilter filter) { 52 | mFilter = null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/ExternalVideoFilter/ve_gl/EglBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | package com.zego.ExternalVideoFilter.ve_gl; 12 | 13 | import android.graphics.SurfaceTexture; 14 | import android.view.Surface; 15 | 16 | import javax.microedition.khronos.egl.EGL10; 17 | 18 | /** 19 | * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EGLDisplay, 20 | * and an EGLSurface. 21 | */ 22 | public abstract class EglBase { 23 | // EGL wrapper for an actual EGLContext. 24 | public static class Context {} 25 | 26 | // According to the documentation, EGL can be used from multiple threads at the same time if each 27 | // thread has its own EGLContext, but in practice it deadlocks on some devices when doing this. 28 | // Therefore, synchronize on this global lock before calling dangerous EGL functions that might 29 | // deadlock. See https://bugs.chromium.org/p/webrtc/issues/detail?id=5702 for more info. 30 | public static final Object lock = new Object(); 31 | 32 | // These constants are taken from EGL14.EGL_OPENGL_ES2_BIT and EGL14.EGL_CONTEXT_CLIENT_VERSION. 33 | // https://android.googlesource.com/platform/frameworks/base/+/master/opengl/java/android/opengl/EGL14.java 34 | // This is similar to how GlSurfaceView does: 35 | // http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/opengl/GLSurfaceView.java#760 36 | private static final int EGL_OPENGL_ES2_BIT = 4; 37 | // Android-specific extension. 38 | private static final int EGL_RECORDABLE_ANDROID = 0x3142; 39 | 40 | // clang-format off 41 | public static final int[] CONFIG_PLAIN = { 42 | EGL10.EGL_RED_SIZE, 8, 43 | EGL10.EGL_GREEN_SIZE, 8, 44 | EGL10.EGL_BLUE_SIZE, 8, 45 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 46 | EGL10.EGL_NONE 47 | }; 48 | public static final int[] CONFIG_RGBA = { 49 | EGL10.EGL_RED_SIZE, 8, 50 | EGL10.EGL_GREEN_SIZE, 8, 51 | EGL10.EGL_BLUE_SIZE, 8, 52 | EGL10.EGL_ALPHA_SIZE, 8, 53 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 54 | EGL10.EGL_NONE 55 | }; 56 | public static final int[] CONFIG_PIXEL_BUFFER = { 57 | EGL10.EGL_RED_SIZE, 8, 58 | EGL10.EGL_GREEN_SIZE, 8, 59 | EGL10.EGL_BLUE_SIZE, 8, 60 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 61 | EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT, 62 | EGL10.EGL_NONE 63 | }; 64 | public static final int[] CONFIG_PIXEL_RGBA_BUFFER = { 65 | EGL10.EGL_RED_SIZE, 8, 66 | EGL10.EGL_GREEN_SIZE, 8, 67 | EGL10.EGL_BLUE_SIZE, 8, 68 | EGL10.EGL_ALPHA_SIZE, 8, 69 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 70 | EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT, 71 | EGL10.EGL_NONE 72 | }; 73 | public static final int[] CONFIG_RECORDABLE = { 74 | EGL10.EGL_RED_SIZE, 8, 75 | EGL10.EGL_GREEN_SIZE, 8, 76 | EGL10.EGL_BLUE_SIZE, 8, 77 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 78 | EGL_RECORDABLE_ANDROID, 1, //表示该EGL使用的Surface将用做实时采集 79 | EGL10.EGL_NONE 80 | }; 81 | // clang-format on 82 | 83 | // Create a new context with the specified config attributes, sharing data with sharedContext. 84 | // |sharedContext| can be null. 85 | public static EglBase create(Context sharedContext, int[] configAttributes) { 86 | return (EglBase14.isEGL14Supported() 87 | && (sharedContext == null || sharedContext instanceof EglBase14.Context)) 88 | ? new EglBase14((EglBase14.Context) sharedContext, configAttributes) 89 | : new EglBase10((EglBase10.Context) sharedContext, configAttributes); 90 | } 91 | 92 | public static EglBase create() { 93 | return create(null, CONFIG_PLAIN); 94 | } 95 | 96 | public static EglBase create(Context sharedContext) { 97 | return create(sharedContext, CONFIG_PLAIN); 98 | } 99 | 100 | public abstract void createSurface(Surface surface); 101 | 102 | // Create EGLSurface from the Android SurfaceTexture. 103 | public abstract void createSurface(SurfaceTexture surfaceTexture); 104 | 105 | // Create dummy 1x1 pixel buffer surface so the context can be made current. 106 | public abstract void createDummyPbufferSurface(); 107 | 108 | public abstract void createPbufferSurface(int width, int height); 109 | 110 | public abstract Context getEglBaseContext(); 111 | 112 | public abstract boolean hasSurface(); 113 | 114 | public abstract int surfaceWidth(); 115 | 116 | public abstract int surfaceHeight(); 117 | 118 | public abstract void releaseSurface(); 119 | 120 | public abstract void release(); 121 | 122 | public abstract void makeCurrent(); 123 | 124 | // Detach the current EGL context, so that it can be made current on another thread. 125 | public abstract void detachCurrent(); 126 | 127 | public abstract void swapBuffers(); 128 | } 129 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/ExternalVideoFilter/ve_gl/GlShader.java: -------------------------------------------------------------------------------- 1 | package com.zego.ExternalVideoFilter.ve_gl; 2 | 3 | import android.opengl.GLES20; 4 | import android.util.Log; 5 | 6 | import java.nio.FloatBuffer; 7 | 8 | // Helper class for handling OpenGL shaders and shader programs. 9 | public class GlShader { 10 | private static final String TAG = "GlShader"; 11 | 12 | private static int compileShader(int shaderType, String source) { 13 | final int shader = GLES20.glCreateShader(shaderType); 14 | if (shader == 0) { 15 | throw new RuntimeException("glCreateShader() failed. GLES20 error: " + GLES20.glGetError()); 16 | } 17 | GLES20.glShaderSource(shader, source); 18 | GLES20.glCompileShader(shader); 19 | int[] compileStatus = new int[] { 20 | GLES20.GL_FALSE 21 | }; 22 | GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 23 | if (compileStatus[0] != GLES20.GL_TRUE) { 24 | Log.e(TAG, "Could not compile shader " + shaderType + ":" + 25 | GLES20.glGetShaderInfoLog(shader)); 26 | throw new RuntimeException(GLES20.glGetShaderInfoLog(shader)); 27 | } 28 | GlUtil.checkNoGLES2Error("compileShader"); 29 | return shader; 30 | } 31 | 32 | private int program; 33 | 34 | public GlShader(String vertexSource, String fragmentSource) { 35 | final int vertexShader = compileShader(GLES20.GL_VERTEX_SHADER, vertexSource); 36 | final int fragmentShader = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 37 | program = GLES20.glCreateProgram(); 38 | if (program == 0) { 39 | throw new RuntimeException("glCreateProgram() failed. GLES20 error: " + GLES20.glGetError()); 40 | } 41 | GLES20.glAttachShader(program, vertexShader); 42 | GLES20.glAttachShader(program, fragmentShader); 43 | GLES20.glLinkProgram(program); 44 | int[] linkStatus = new int[] { 45 | GLES20.GL_FALSE 46 | }; 47 | GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 48 | if (linkStatus[0] != GLES20.GL_TRUE) { 49 | Log.e(TAG, "Could not link program: " + 50 | GLES20.glGetProgramInfoLog(program)); 51 | throw new RuntimeException(GLES20.glGetProgramInfoLog(program)); 52 | } 53 | // According to the documentation of glLinkProgram(): 54 | // "After the link operation, applications are free to modify attached shader objects, compile 55 | // attached shader objects, detach shader objects, delete shader objects, and attach additional 56 | // shader objects. None of these operations affects the information log or the program that is 57 | // part of the program object." 58 | // But in practice, detaching shaders from the program seems to break some devices. Deleting the 59 | // shaders are fine however - it will delete them when they are no longer attached to a program. 60 | GLES20.glDeleteShader(vertexShader); 61 | GLES20.glDeleteShader(fragmentShader); 62 | GlUtil.checkNoGLES2Error("Creating GlShader"); 63 | } 64 | 65 | public int getAttribLocation(String label) { 66 | if (program == -1) { 67 | throw new RuntimeException("The program has been released"); 68 | } 69 | int location = GLES20.glGetAttribLocation(program, label); 70 | if (location < 0) { 71 | throw new RuntimeException("Could not locate '" + label + "' in program"); 72 | } 73 | return location; 74 | } 75 | 76 | /** 77 | * Enable and upload a vertex array for attribute |label|. The vertex data is specified in 78 | * |buffer| with |dimension| number of components per vertex. 79 | */ 80 | public void setVertexAttribArray(String label, int dimension, FloatBuffer buffer) { 81 | if (program == -1) { 82 | throw new RuntimeException("The program has been released"); 83 | } 84 | int location = getAttribLocation(label); 85 | GLES20.glEnableVertexAttribArray(location); 86 | GLES20.glVertexAttribPointer(location, dimension, GLES20.GL_FLOAT, false, 0, buffer); 87 | GlUtil.checkNoGLES2Error("setVertexAttribArray"); 88 | } 89 | 90 | public int getUniformLocation(String label) { 91 | if (program == -1) { 92 | throw new RuntimeException("The program has been released"); 93 | } 94 | int location = GLES20.glGetUniformLocation(program, label); 95 | if (location < 0) { 96 | throw new RuntimeException("Could not locate uniform '" + label + "' in program"); 97 | } 98 | return location; 99 | } 100 | 101 | public void useProgram() { 102 | if (program == -1) { 103 | throw new RuntimeException("The program has been released"); 104 | } 105 | GLES20.glUseProgram(program); 106 | GlUtil.checkNoGLES2Error("glUseProgram"); 107 | } 108 | 109 | public void release() { 110 | Log.d(TAG, "Deleting shader."); 111 | // Delete program, automatically detaching any shaders from it. 112 | if (program != -1) { 113 | GLES20.glDeleteProgram(program); 114 | program = -1; 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/ExternalVideoFilter/ve_gl/GlUtil.java: -------------------------------------------------------------------------------- 1 | package com.zego.ExternalVideoFilter.ve_gl; 2 | 3 | import android.opengl.GLES20; 4 | 5 | import java.nio.ByteBuffer; 6 | import java.nio.ByteOrder; 7 | import java.nio.FloatBuffer; 8 | 9 | /** 10 | * Some OpenGL static utility functions. 11 | */ 12 | public class GlUtil { 13 | private GlUtil() {} 14 | 15 | // Assert that no OpenGL ES 2.0 error has been raised. 16 | public static void checkNoGLES2Error(String msg) { 17 | int error = GLES20.glGetError(); 18 | if (error != GLES20.GL_NO_ERROR) { 19 | throw new RuntimeException(msg + ": GLES20 error: " + error); 20 | } 21 | } 22 | 23 | public static FloatBuffer createFloatBuffer(float[] coords) { 24 | // Allocate a direct ByteBuffer, using 4 bytes per float, and copy coords into it. 25 | ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * 4); 26 | bb.order(ByteOrder.nativeOrder()); 27 | FloatBuffer fb = bb.asFloatBuffer(); 28 | fb.put(coords); 29 | fb.position(0); 30 | return fb; 31 | } 32 | 33 | /** 34 | * Generate texture with standard parameters. 35 | */ 36 | public static int generateTexture(int target) { 37 | final int textureArray[] = new int[1]; 38 | GLES20.glGenTextures(1, textureArray, 0); 39 | final int textureId = textureArray[0]; 40 | GLES20.glBindTexture(target, textureId); 41 | GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 42 | GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 43 | GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); 44 | GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); 45 | checkNoGLES2Error("generateTexture"); 46 | return textureId; 47 | } 48 | 49 | public static int generateFrameBuffer(int textureId) { 50 | final int frameBufferArray[] = new int[1]; 51 | GLES20.glGenFramebuffers(1, frameBufferArray, 0); 52 | final int frameBufferId = frameBufferArray[0]; 53 | // 绑定帧缓冲区 54 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId); 55 | // 将2D纹理附着到帧缓冲对象 56 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, textureId, 0); 57 | // 检查帧缓冲区是否完整 58 | int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 59 | 60 | if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) { 61 | return -1; 62 | } 63 | 64 | checkNoGLES2Error("generateFrameBuffer"); 65 | return frameBufferId; 66 | } 67 | } -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/externalvideocapture/MediaPlayerVideoCapture.java: -------------------------------------------------------------------------------- 1 | package com.zego.externalvideocapture; 2 | 3 | import android.os.Build; 4 | import android.os.SystemClock; 5 | import android.util.Log; 6 | import android.view.View; 7 | import com.zego.zegoavkit2.IZegoMediaPlayerVideoPlayWithIndexCallback; 8 | import com.zego.zegoavkit2.ZegoVideoCaptureDevice; 9 | import com.zego.zegoavkit2.ZegoVideoDataFormat; 10 | import com.zego.zegoliveroom.constants.ZegoVideoViewMode; 11 | import java.nio.ByteBuffer; 12 | import java.util.concurrent.TimeUnit; 13 | import java.util.concurrent.atomic.AtomicBoolean; 14 | 15 | public class MediaPlayerVideoCapture extends ZegoVideoCaptureDevice implements 16 | IZegoMediaPlayerVideoPlayWithIndexCallback { 17 | 18 | private static final String TAG = "VideoCapture"; 19 | 20 | // 因为生命周期回调和mediaPlayer回调是不同线程, 使用原子类 21 | AtomicBoolean runState = new AtomicBoolean(false); 22 | 23 | private Client mClient = null; 24 | 25 | volatile PixelBuffer pixelBuffer = null; 26 | 27 | private int mMaxBufferSize = 0; 28 | 29 | public MediaPlayerVideoCapture() { 30 | } 31 | 32 | /** 33 | * 开发者在 allocateAndStart 中获取到 client 34 | * 35 | * @param client 用于通知 SDK 采集结果, 包括设置采集的view模式 36 | */ 37 | @Override 38 | protected void allocateAndStart(Client client) { 39 | Log.e(TAG, "allocateAndStart"); 40 | mClient = client; 41 | mClient.setFillMode(ZegoVideoViewMode.ScaleToFill); 42 | } 43 | 44 | /** 45 | * 用于释放销毁一些资源 46 | */ 47 | @Override 48 | protected void stopAndDeAllocate() { 49 | Log.e(TAG, "stopAndDeAllocate"); 50 | mClient.destroy(); 51 | mClient = null; 52 | } 53 | 54 | /** 55 | * 启用采集,sdk开始推流或开始预览的时候会调用该 56 | * 方法通知到开发者 57 | * 58 | * @return 59 | */ 60 | @Override 61 | protected int startCapture() { 62 | Log.e(TAG, "startCapture"); 63 | // sdk开始采集 64 | runState.set(true); 65 | return 0; 66 | } 67 | 68 | /** 69 | * 停止采集,sdk停止推流或停止预览时会调用该方法 70 | * 通知到开发者 71 | * 72 | * @return 73 | */ 74 | @Override 75 | protected int stopCapture() { 76 | Log.e(TAG, "stopCapture"); 77 | // sdk停止采集, 此时需要修改状态 78 | runState.set(false); 79 | return 0; 80 | } 81 | 82 | @Override 83 | protected int supportBufferType() { 84 | // sdk外部采集的方式, 使用内存模式 85 | return PIXEL_BUFFER_TYPE_MEM; 86 | } 87 | 88 | // mediaPlayer视频帧回调处理 89 | @Override 90 | public void onPlayVideoData(byte[] bytes, int size, ZegoVideoDataFormat f, int index) { 91 | // 获取buffer, 重复利用一个buff 92 | if (runState.get()) { 93 | long now; 94 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 95 | now = SystemClock.elapsedRealtimeNanos(); 96 | } else { 97 | now = TimeUnit.MILLISECONDS.toNanos(SystemClock.elapsedRealtime()); 98 | } 99 | 100 | // 视频帧传给ZEGO sdk 101 | PixelBuffer pixelBuffer = obtainPixelBuffer(bytes, size, f); 102 | mClient.onByteBufferFrameCaptured(pixelBuffer.buffer, size, pixelBuffer.format, now, 1000000000); 103 | } 104 | } 105 | 106 | private synchronized PixelBuffer obtainPixelBuffer(final byte[] bytes, int size, final ZegoVideoDataFormat format) { 107 | // buff大小变化才进行创建 108 | if (pixelBuffer == null || size != mMaxBufferSize) { 109 | if (pixelBuffer != null) { 110 | pixelBuffer.buffer.clear(); 111 | } else { 112 | pixelBuffer = new PixelBuffer(); 113 | pixelBuffer.format = new VideoCaptureFormat(); 114 | } 115 | 116 | // TODO 创建buff要用allocateDirect方式创建, sdk才能正常收到数据 117 | pixelBuffer.buffer = ByteBuffer.allocateDirect(size); 118 | mMaxBufferSize = size; 119 | 120 | // TODO: 4/9/21 121 | // 设置编解码分辨率 122 | // ZGManager.getInstance().setZegoAvConfig(width, height); 123 | } else { 124 | pixelBuffer.buffer.clear(); 125 | } 126 | 127 | pixelBuffer.buffer.put(bytes, 0, size); 128 | pixelBuffer.format.width = format.width; 129 | pixelBuffer.format.height = format.height; 130 | pixelBuffer.format.strides = format.strides; 131 | pixelBuffer.format.rotation = 0; 132 | pixelBuffer.format.pixel_format = PIXEL_FORMAT_BGRA32; 133 | 134 | return pixelBuffer; 135 | } 136 | 137 | private static class PixelBuffer { 138 | public ByteBuffer buffer; 139 | public VideoCaptureFormat format; 140 | } 141 | 142 | /* -------------以下是目前不需要关注的回调------------- */ 143 | 144 | @Override 145 | protected int setFrameRate(int i) { 146 | return 0; 147 | } 148 | 149 | @Override 150 | protected int setResolution(int i, int i1) { 151 | return 0; 152 | } 153 | 154 | @Override 155 | protected int setFrontCam(int i) { 156 | return 0; 157 | } 158 | 159 | @Override 160 | protected int setView(View view) { 161 | return 0; 162 | } 163 | 164 | @Override 165 | protected int setViewMode(int i) { 166 | return 0; 167 | } 168 | 169 | @Override 170 | protected int setViewRotation(int i) { 171 | return 0; 172 | } 173 | 174 | @Override 175 | protected int setCaptureRotation(int i) { 176 | return 0; 177 | } 178 | 179 | @Override 180 | protected int startPreview() { 181 | return 0; 182 | } 183 | 184 | @Override 185 | protected int stopPreview() { 186 | return 0; 187 | } 188 | 189 | @Override 190 | protected int enableTorch(boolean b) { 191 | return 0; 192 | } 193 | 194 | @Override 195 | protected int takeSnapshot() { 196 | return 0; 197 | } 198 | 199 | @Override 200 | protected int setPowerlineFreq(int i) { 201 | return 0; 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/externalvideocapture/VideoCaptureFactory.java: -------------------------------------------------------------------------------- 1 | package com.zego.externalvideocapture; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.util.Log; 7 | 8 | import com.zego.zegoavkit2.ZegoVideoCaptureDevice; 9 | import com.zego.zegoavkit2.ZegoVideoCaptureFactory; 10 | import com.zego.zegoliveroom.ZegoLiveRoom; 11 | import com.zego.zegoliveroomplugin.module.mediaplayer.ZegoMediaPlayerController; 12 | 13 | import static com.zego.zegoavkit2.ZegoVideoCaptureDevice.PIXEL_FORMAT_BGRA32; 14 | 15 | /** 16 | * 外部采集工厂, 需要通过ZegoLiveRoom.setVideoCaptureFactory()设置到sdk 17 | * ZGVideoCaptureForMediaPlayer外部采集的入口,定义了创建、销毁 ZegoVideoCaptureDevice 的接口, 18 | * 向 SDK 提供管理 ZegoVideoCaptureDevice 生命周期的能力。需要调用 19 | * 20 | * 外部采集工厂设置到Zego SDK的时机必须是在 {@link ZegoLiveRoom#initSDK(long, byte[], Context)} 之前。 21 | * 否则外部采集功能将不生效 22 | *

23 | * 24 | */ 25 | public class VideoCaptureFactory extends ZegoVideoCaptureFactory { 26 | 27 | private static final String TAG = "VideoCaptureFactory"; 28 | 29 | private MediaPlayerVideoCapture mDevice; 30 | private final Handler mUIHandler = new Handler(Looper.getMainLooper()); 31 | 32 | public VideoCaptureFactory() { 33 | mDevice = new MediaPlayerVideoCapture(); 34 | } 35 | 36 | @Override 37 | protected ZegoVideoCaptureDevice create(String s) { 38 | Log.i(TAG, "create: s = " + s); 39 | mUIHandler.post(new Runnable() { 40 | @Override 41 | public void run() { 42 | ZegoMediaPlayerController.getInstance(0).setVideoDataCallback(mDevice, PIXEL_FORMAT_BGRA32); 43 | } 44 | }); 45 | return mDevice; 46 | } 47 | 48 | @Override 49 | protected void destroy(ZegoVideoCaptureDevice zegoVideoCaptureDevice) { 50 | mUIHandler.post(new Runnable() { 51 | @Override 52 | public void run() { 53 | ZegoMediaPlayerController.getInstance(0).setVideoDataCallback(null, PIXEL_FORMAT_BGRA32); 54 | } 55 | }); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/flutter/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zego.flutter.example; 2 | 3 | import android.os.Bundle; 4 | 5 | import io.flutter.app.FlutterActivity; 6 | import io.flutter.plugins.GeneratedPluginRegistrant; 7 | 8 | // 使用外部滤镜:导入 ZegoLiveRoomPlugin 以及自己实现的外部滤镜工厂文件 9 | import com.zego.externalvideocapture.MediaPlayerVideoCapture; 10 | import com.zego.externalvideocapture.VideoCaptureFactory; 11 | import com.zego.zegoavkit2.ZegoVideoCaptureFactory; 12 | import com.zego.zegoliveroomplugin.ZegoLiveRoomPlugin; 13 | import com.zego.ExternalVideoFilter.VideoFilterFactoryDemo; 14 | import com.zego.zegoliveroomplugin.module.mediaplayer.ZegoMediaPlayerController; 15 | 16 | import static com.zego.zegoavkit2.ZegoVideoCaptureDevice.PIXEL_FORMAT_BGRA32; 17 | 18 | 19 | public class MainActivity extends FlutterActivity { 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | 24 | 25 | // 创建一个自己实现的外部视频滤镜工厂,此处为一个 Demo 工厂 26 | VideoFilterFactoryDemo factory = new VideoFilterFactoryDemo(); 27 | // 选择使用 FilterTypeMem(异步 BGRA32) 类型滤镜 28 | factory.filterType = VideoFilterFactoryDemo.FilterType.FilterTypeMem; 29 | // 设给 ZegoLiveRoomPlugin 暂存,当调用 dart 的接口 `enableExternalVideoFilterFactory` 时才真正调用 Native SDK 接口设入 30 | ZegoLiveRoomPlugin.setExternalVideoFilterFactory(factory); 31 | 32 | 33 | ZegoLiveRoomPlugin.setExternalVideoCaptureFactory(new VideoCaptureFactory()); 34 | 35 | GeneratedPluginRegistrant.registerWith(this); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/zego/flutter/example/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.zego.flutter.example; 2 | 3 | import com.tencent.bugly.crashreport.CrashReport; 4 | 5 | import io.flutter.app.FlutterApplication; 6 | 7 | public class MyApplication extends FlutterApplication { 8 | 9 | final static private String BUGLY_APP_KEY = "156048a981"; 10 | 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | 15 | setupBugly(); 16 | } 17 | 18 | private void setupBugly() { 19 | CrashReport.initCrashReport(this, BUGLY_APP_KEY, true); 20 | } 21 | } -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 4 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } 5 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } 6 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/gradle-plugin' } 7 | google() 8 | jcenter() 9 | 10 | } 11 | 12 | dependencies { 13 | classpath 'com.android.tools.build:gradle:4.2.1' 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 20 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' } 21 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } 22 | maven { url 'http://maven.aliyun.com/nexus/content/repositories/gradle-plugin' } 23 | google() 24 | jcenter() 25 | 26 | } 27 | } 28 | 29 | rootProject.buildDir = '../build' 30 | subprojects { 31 | project.buildDir = "${rootProject.buildDir}/${project.name}" 32 | } 33 | subprojects { 34 | project.evaluationDependsOn(':app') 35 | } 36 | 37 | task clean(type: Delete) { 38 | delete rootProject.buildDir 39 | } 40 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Nov 02 10:44:26 CST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Flutter.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: This podspec is NOT to be published. It is only used as a local source! 3 | # This is a generated file; do not edit or check into version control. 4 | # 5 | 6 | Pod::Spec.new do |s| 7 | s.name = 'Flutter' 8 | s.version = '1.0.0' 9 | s.summary = 'High-performance, high-fidelity mobile apps.' 10 | s.homepage = 'https://flutter.io' 11 | s.license = { :type => 'MIT' } 12 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } 13 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } 14 | s.ios.deployment_target = '9.0' 15 | # Framework linking is handled by Flutter tooling, not CocoaPods. 16 | # Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs. 17 | s.vendored_frameworks = 'path/to/nothing' 18 | end 19 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | post_install do |installer| 35 | installer.pods_project.targets.each do |target| 36 | flutter_additional_ios_build_settings(target) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | // 使用外部滤镜:导入 ZegoLiveRoomPlugin.h 以及自己实现的外部滤镜工厂文件 5 | #import 6 | #import "ZGVideoFilterFactoryDemo.h" 7 | 8 | // 使用外部采集 9 | // 这里是结合 MediaPlayer 来使用外部采集示例 10 | #import "ZGVideoCaptureForMediaPlayer.h" 11 | #import 12 | 13 | @implementation AppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application 16 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 17 | [GeneratedPluginRegistrant registerWithRegistry:self]; 18 | 19 | 20 | // 创建一个自己实现的外部视频滤镜工厂,此处为一个 Demo 工厂 21 | ZGVideoFilterFactoryDemo *factory = [[ZGVideoFilterFactoryDemo alloc] init]; 22 | // 使用异步(BGRA32)类型滤镜 23 | factory.bufferType = ZegoVideoBufferTypeAsyncPixelBuffer; 24 | // 设给 ZegoLiveRoomPlugin 暂存,当调用 dart 的接口 `enableExternalVideoFilterFactory` 时才真正调用 Native SDK 接口设入 25 | [ZegoLiveRoomPlugin setExternalVideoFilterFactory:factory]; 26 | 27 | // 创建一个自己实现的外部采集工厂,此处为一个配合 MediaPlayer 的工厂 28 | ZGVideoCaptureForMediaPlayer *mpCapture = [[ZGVideoCaptureForMediaPlayer alloc] init]; 29 | // 暂存外部采集工厂 30 | [ZegoLiveRoomPlugin setExternalVideoCaptureFactory:mpCapture]; 31 | 32 | // Override point for customization after application launch. 33 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoCapture/ZGExternalVideoCaptureFactory.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZGExternalVideoCaptureFactory.h 3 | // LiveRoomPlayGround 4 | // 5 | // Copyright © 2019 Zego. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** 14 | 示例 Demo 的外部视频采集 factory 15 | */ 16 | @interface ZGExternalVideoCaptureFactory : NSObject 17 | /** 18 | 初始化工厂 19 | 20 | @param device 抽象的采集设备 21 | */ 22 | - (instancetype)initWithDevice: (id)device; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | 28 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoCapture/ZGExternalVideoCaptureFactory.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZGExternalVideoCaptureFactory.m 3 | // LiveRoomPlayGround 4 | // 5 | // Copyright © 2019 Zego. All rights reserved. 6 | // 7 | 8 | #import "ZGExternalVideoCaptureFactory.h" 9 | 10 | @interface ZGExternalVideoCaptureFactory () 11 | 12 | @property (nonatomic, weak) id mDevice; 13 | 14 | @end 15 | 16 | @implementation ZGExternalVideoCaptureFactory 17 | 18 | 19 | - (instancetype)initWithDevice:(id)device { 20 | if (self = [super init]) { 21 | _mDevice = device; 22 | } 23 | return self; 24 | } 25 | 26 | #pragma mark - ZegoVideoCaptureFactory 27 | 28 | - (nonnull id)zego_create:(nonnull NSString*)deviceId { 29 | NSLog(@"%s.%@", __func__, self); 30 | return self.mDevice; 31 | } 32 | 33 | - (void)zego_destroy:(nonnull id)device { 34 | NSLog(@"%s. %@", __func__, self); 35 | self.mDevice = nil; 36 | } 37 | @end 38 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoCapture/ZGVideoCaptureForMediaPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoCaptureForMediaPlayer.h 3 | // LiveRoomPlayground 4 | // 5 | // Copyright © 2018年 Zego. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | #import 11 | #import 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface ZGVideoCaptureForMediaPlayer : NSObject 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoCapture/ZGVideoCaptureForMediaPlayer.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoCaptureForMediaPlayer.m 3 | // LiveRoomPlayground 4 | // 5 | // Copyright © 2018年 Zego. All rights reserved. 6 | // 7 | 8 | #import "ZGVideoCaptureForMediaPlayer.h" 9 | #import 10 | #import 11 | #import 12 | 13 | @interface ZGVideoCaptureForMediaPlayer () { 14 | id client_; 15 | BOOL capture_started_; 16 | std::mutex capture_lock_; 17 | 18 | CVPixelBufferPoolRef pool_; 19 | int video_width_; 20 | int video_height_; 21 | } 22 | @end 23 | 24 | @implementation ZGVideoCaptureForMediaPlayer 25 | 26 | #pragma mark - ZegoVideoCaptureFactory 27 | 28 | - (id)zego_create:(NSString *)deviceId { 29 | NSLog(@"%s", __func__); 30 | return self; 31 | } 32 | 33 | - (void)zego_destroy:(id)device { 34 | NSLog(@"%s", __func__); 35 | } 36 | 37 | #pragma mark - ZegoVideoCaptureDevice 38 | 39 | - (void)zego_allocateAndStart:(id)client { 40 | NSLog(@"%s", __func__); 41 | client_ = client; 42 | } 43 | 44 | - (void)zego_stopAndDeAllocate { 45 | NSLog(@"%s", __func__); 46 | [client_ destroy]; 47 | client_ = nil; 48 | } 49 | 50 | - (int)zego_startCapture { 51 | NSLog(@"%s", __func__); 52 | std::lock_guard lg(capture_lock_); 53 | capture_started_ = YES; 54 | return 0; 55 | } 56 | 57 | - (int)zego_stopCapture { 58 | NSLog(@"%s", __func__); 59 | std::lock_guard lg(capture_lock_); 60 | capture_started_ = NO; 61 | return 0; 62 | } 63 | 64 | - (ZegoVideoCaptureDeviceOutputBufferType)zego_supportBufferType { 65 | NSLog(@"%s", __func__); 66 | return ZegoVideoCaptureDeviceOutputBufferTypeCVPixelBuffer; 67 | } 68 | 69 | #pragma mark - ZegoMediaPlayerControllerVideoDataDelegate 70 | - (void)onPlayerVideoFrame:(CVPixelBufferRef)buffer timeStamp:(unsigned long long)timeStamp { 71 | [self handleFrame:buffer time:timeStamp]; 72 | } 73 | 74 | - (void)handleFrame:(CVPixelBufferRef)frame time:(unsigned long long)timeMS { 75 | CMTime pts = CMTimeMake(timeMS, 1000); 76 | std::lock_guard lg(capture_lock_); 77 | if (capture_started_) { 78 | [client_ onIncomingCapturedData:frame withPresentationTimeStamp:pts]; 79 | } 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoFilter/VideoFilter/ZGVideoFilterAsyncDemo.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoFilterAsyncDemo.h 3 | // LiveRoomPlayground-iOS 4 | // 5 | // Created by Paaatrick on 2019/7/30. 6 | // Copyright © 2019 Zego. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #if TARGET_OS_OSX 12 | #import 13 | #elif TARGET_OS_IOS 14 | #import 15 | #endif 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | /** 20 | 异步类型外部滤镜实现 21 | */ 22 | @interface ZGVideoFilterAsyncDemo : NSObject 23 | 24 | @end 25 | 26 | 27 | NS_ASSUME_NONNULL_END 28 | 29 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoFilter/VideoFilter/ZGVideoFilterAsyncDemo.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoFilterAsyncDemo.m 3 | // LiveRoomPlayground-iOS 4 | // 5 | // Created by Paaatrick on 2019/7/30. 6 | // Copyright © 2019 Zego. All rights reserved. 7 | // 8 | 9 | #import "ZGVideoFilterAsyncDemo.h" 10 | #import "ZGPixelBufferUtils.h" 11 | 12 | @interface ZGVideoFilterAsyncDemo () 13 | 14 | @property (atomic) int pendingCount; 15 | 16 | @end 17 | 18 | @implementation ZGVideoFilterAsyncDemo { 19 | id client_; // SDK 创建的外部滤镜客户端,用于传递数据 20 | id buffer_pool_; 21 | 22 | dispatch_queue_t queue_; 23 | int width_; 24 | int height_; 25 | int stride_; 26 | CVPixelBufferPoolRef pool_; 27 | int buffer_count_; 28 | } 29 | 30 | #pragma mark -- ZegoVideoFilter Delgate 31 | 32 | // 初始化外部滤镜使用的资源 33 | - (void)zego_allocateAndStart:(id) client { 34 | client_ = client; 35 | if ([client_ conformsToProtocol:@protocol(ZegoVideoBufferPool)]) { 36 | buffer_pool_ = (id)client; 37 | } 38 | 39 | width_ = 0; 40 | height_ = 0; 41 | stride_ = 0; 42 | pool_ = nil; 43 | buffer_count_ = 4; 44 | self.pendingCount = 0; 45 | 46 | queue_ = dispatch_queue_create("video.filter", nil); 47 | } 48 | 49 | // 停止并释放外部滤镜占用的资源 50 | - (void)zego_stopAndDeAllocate { 51 | if (queue_) { 52 | dispatch_sync(queue_, ^ { 53 | }); 54 | queue_ = nil; 55 | } 56 | 57 | if (pool_) { 58 | [ZGPixelBufferUtils destroyPixelBufferPool:&pool_]; 59 | pool_ = nil; 60 | } 61 | 62 | if (client_) { 63 | [client_ destroy]; 64 | client_ = nil; 65 | buffer_pool_ = nil; 66 | } 67 | } 68 | 69 | - (ZegoVideoBufferType)supportBufferType { 70 | // * 返回滤镜的类型:此滤镜为异步滤镜 71 | return ZegoVideoBufferTypeAsyncPixelBuffer; 72 | } 73 | 74 | #pragma mark -- ZegoVideoBufferPool Delegate 75 | 76 | // SDK 回调。从 App 获取 CVPixelBufferRef 对象,用于保存视频帧数据 77 | - (CVPixelBufferRef)dequeueInputBuffer:(int)width height:(int)height stride:(int)stride { 78 | // * 按需创建 CVPixelBufferPool 79 | if (width_ != width || height_ != height || stride_ != stride) { 80 | if (pool_) { 81 | [ZGPixelBufferUtils destroyPixelBufferPool:&pool_]; 82 | } 83 | 84 | if ([ZGPixelBufferUtils create32BGRAPixelBufferPool:&pool_ width:width height:height]) { 85 | width_ = width; 86 | height_ = height; 87 | stride_ = stride; 88 | } else { 89 | return nil; 90 | } 91 | } 92 | 93 | // * 如果处理不及时,未处理帧超过了 pool 的大小,则丢弃该帧 94 | if (self.pendingCount >= buffer_count_) { 95 | return nil; 96 | } 97 | 98 | CVPixelBufferRef pixel_buffer = nil; 99 | CVReturn ret = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool_, &pixel_buffer); 100 | 101 | if (ret != kCVReturnSuccess) { 102 | return nil; 103 | } else { 104 | self.pendingCount = self.pendingCount + 1; 105 | // * 返回一个可以用于存储采集到的图像的 CVPixelBuffer 实例 106 | return pixel_buffer; 107 | } 108 | } 109 | 110 | // SDK 回调。App 在此接口中获取 SDK 采集到的视频帧数据,并进行处理 111 | - (void)queueInputBuffer:(CVPixelBufferRef)pixel_buffer timestamp:(unsigned long long)timestamp_100n { 112 | // * 采集到的图像数据通过这个传进来,这个点需要异步处理 113 | dispatch_async(queue_, ^ { 114 | int imageWidth = (int)CVPixelBufferGetWidth(pixel_buffer); 115 | int imageHeight = (int)CVPixelBufferGetHeight(pixel_buffer); 116 | int imageStride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0); 117 | 118 | CVPixelBufferRef dst = [self->buffer_pool_ dequeueInputBuffer:imageWidth height:imageHeight stride:imageStride]; 119 | 120 | if (dst) { 121 | 122 | // 示例 1️⃣:此处示例使用 FaceUnity 作为外部滤镜 123 | // CVPixelBufferRef output = [[FUManager shareManager] renderItemsToPixelBuffer:pixel_buffer]; 124 | // BOOL result = [ZGPixelBufferUtils copyPixelBufferFrom:output to:dst]; 125 | 126 | 127 | // 示例 2️⃣:此处示例手动反转画面颜色 128 | CVPixelBufferLockBaseAddress(pixel_buffer, 0); 129 | unsigned char *bgra32 = (unsigned char *)CVPixelBufferGetBaseAddress(pixel_buffer); 130 | for (int i = 0; i < (imageStride * imageHeight); i += 4) { 131 | unsigned char b = bgra32[i]; 132 | unsigned char g = bgra32[i + 1]; 133 | unsigned char r = bgra32[i + 2]; 134 | bgra32[i] = 255 - b; 135 | bgra32[i + 1] = 255 - g; 136 | bgra32[i + 2] = 255 - r; 137 | } 138 | CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); 139 | BOOL result = [ZGPixelBufferUtils copyRGBBuffer:bgra32 to:dst strides:imageStride width:imageWidth height:imageHeight]; 140 | 141 | 142 | // 将处理完成的 Pixel Buffer 回传给 SDK 143 | if (result) { 144 | [self->buffer_pool_ queueInputBuffer:dst timestamp:timestamp_100n]; 145 | } 146 | } 147 | 148 | self.pendingCount = self.pendingCount - 1; 149 | CVPixelBufferRelease(pixel_buffer); 150 | }); 151 | } 152 | 153 | @end 154 | 155 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoFilter/VideoFilter/ZGVideoFilterSyncDemo.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoFilterSyncDemo.h 3 | // LiveRoomPlayground-iOS 4 | // 5 | // Created by Paaatrick on 2019/7/30. 6 | // Copyright © 2019 Zego. All rights reserved. 7 | // 8 | 9 | 10 | 11 | #import 12 | 13 | #if TARGET_OS_OSX 14 | #import 15 | #elif TARGET_OS_IOS 16 | #import 17 | #endif 18 | 19 | NS_ASSUME_NONNULL_BEGIN 20 | 21 | /** 22 | 同步类型外部滤镜实现 23 | */ 24 | @interface ZGVideoFilterSyncDemo : NSObject 25 | 26 | @end 27 | 28 | NS_ASSUME_NONNULL_END 29 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoFilter/VideoFilter/ZGVideoFilterSyncDemo.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoFilterSyncDemo.m 3 | // LiveRoomPlayground-iOS 4 | // 5 | // Created by Paaatrick on 2019/7/30. 6 | // Copyright © 2019 Zego. All rights reserved. 7 | // 8 | 9 | #import "ZGVideoFilterSyncDemo.h" 10 | #import "ZGPixelBufferUtils.h" 11 | 12 | @implementation ZGVideoFilterSyncDemo { 13 | id client_; 14 | id delegate_; 15 | } 16 | 17 | #pragma mark -- ZegoVideoFilter Delgate 18 | 19 | // 初始化外部滤镜使用的资源 20 | - (void)zego_allocateAndStart:(id) client { 21 | client_ = client; 22 | if ([client_ conformsToProtocol:@protocol(ZegoVideoFilterDelegate)]) { 23 | delegate_ = (id)client; 24 | } 25 | } 26 | 27 | // 停止并释放外部滤镜占用的资源 28 | - (void)zego_stopAndDeAllocate { 29 | [client_ destroy]; 30 | client_ = nil; 31 | delegate_ = nil; 32 | } 33 | 34 | - (ZegoVideoBufferType)supportBufferType { 35 | // * 返回滤镜的类型:此滤镜为同步滤镜 36 | return ZegoVideoBufferTypeSyncPixelBuffer; 37 | } 38 | 39 | #pragma mark -- ZegoVideoFilterDelegate Delegate 40 | 41 | - (void)onProcess:(CVPixelBufferRef)pixel_buffer withTimeStatmp:(unsigned long long)timestamp_100 { 42 | // * 采集到的图像数据通过这个传进来,同步处理完返回处理结果 43 | 44 | 45 | 46 | // 示例 1️⃣:此处示例使用 FaceUnity 作为外部滤镜(本工程未导入 FaceUnity 相关文件) 47 | // CVPixelBufferRef output = [[FUManager shareManager] renderItemsToPixelBuffer:pixel_buffer]; 48 | // [delegate_ onProcess:output withTimeStatmp:timestamp_100]; 49 | 50 | 51 | 52 | // 示例 2️⃣:此处示例手动反转画面颜色 53 | int imageHeight = (int)CVPixelBufferGetHeight(pixel_buffer); 54 | int imageStride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer, 0); 55 | CVPixelBufferLockBaseAddress(pixel_buffer, 0); 56 | unsigned char *bgra32 = (unsigned char *)CVPixelBufferGetBaseAddress(pixel_buffer); 57 | for (int i = 0; i < (imageStride * imageHeight); i += 4) { 58 | unsigned char b = bgra32[i]; 59 | unsigned char g = bgra32[i + 1]; 60 | unsigned char r = bgra32[i + 2]; 61 | bgra32[i] = 255 - b; 62 | bgra32[i + 1] = 255 - g; 63 | bgra32[i + 2] = 255 - r; 64 | } 65 | CVPixelBufferUnlockBaseAddress(pixel_buffer, 0); 66 | 67 | [delegate_ onProcess:pixel_buffer withTimeStatmp:timestamp_100]; 68 | } 69 | 70 | @end 71 | 72 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoFilter/ZGPixelBufferUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZGPixelBufferUtils.h 3 | // Runner 4 | // 5 | // Created by Patrick Fu on 2020/3/5. 6 | // Copyright © 2020 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZGPixelBufferUtils : NSObject 15 | 16 | /// 创建 CVPixelBuffer 17 | /// @param width 宽 18 | /// @param height 高 19 | /// @param format PixelBuffer 的格式 20 | /// @return 创建好的 PixelBuffer 21 | + (nullable CVPixelBufferRef)createPixelBufferWithWidth:(size_t)width height:(size_t)height format:(OSType)format; 22 | 23 | /// 创建 CVPixelBufferPool 24 | /// @param width 宽 25 | /// @param height 高 26 | /// @param format PixelBuffer 的格式 27 | /// @return 创建好的 Pool 28 | + (nullable CVPixelBufferPoolRef)createPixelBufferPoolWithWidth:(size_t)width height:(size_t)height format:(OSType)format; 29 | 30 | 31 | /// 拷贝 ARGB 类型(单平面模式, 不限排列顺序)的数据到对应数据类型的 PixelBuffer 中 32 | /// @param buffer 裸数据 33 | /// @param pixelbuffer 初始化好的 PixelBuffer 34 | /// @param stride 步长,此处取 stride[0] 35 | /// @param size 图像的宽高 36 | + (BOOL)copyRGBBuffer:(unsigned char * _Nonnull)buffer to:(CVPixelBufferRef _Nonnull )pixelBuffer strides:(int)strides width:(size_t)width height:(size_t)height; 37 | 38 | /// 拷贝 NV12(YUV420Semi-Planar, 双平面) 类型的数据到对应数据类型的 PixelBuffer 中 (NV21也可用这个方法) 39 | /// 40 | /// 内存布局 41 | /// plane 1: Y Y Y Y Y Y Y Y 42 | /// Y Y Y Y Y Y Y Y 43 | /// plane 2: U V U V U V U V (NV21颠倒UV顺序) 44 | /// 45 | /// @param buffer 裸数据 46 | /// @param pixelbuffer 初始化好的 PixelBuffer 47 | /// @param stride 步长,此处取 stride[0,1] 48 | /// @param size 图像的宽高 49 | + (BOOL)copyNV12Buffer:(unsigned char * _Nonnull * _Nonnull)buffer to:(CVPixelBufferRef _Nonnull )pixelBuffer strides:(int *_Nonnull)strides width:(size_t)width height:(size_t)height; 50 | 51 | /// 拷贝 I420(也叫 YU12, YUV420Planar, 三平面) 类型的数据到 PixelBuffer 中 (YV12也可用此方法) 52 | /// 53 | /// 内存布局 54 | /// plane 1: Y Y Y Y Y Y Y Y 55 | /// Y Y Y Y Y Y Y Y 56 | /// plane 2: U U U U 57 | /// plane 3: V V V V (YV12为先V后U) 58 | /// 59 | /// @param buffer 裸数据 60 | /// @param pixelbuffer 初始化好的 PixelBuffer 61 | /// @param stride 步长,此处取 stride[0,1,2] 62 | /// @param size 图像的宽高 63 | + (BOOL)copyI420Buffer:(unsigned char * _Nonnull * _Nonnull)buffer to:(CVPixelBufferRef _Nonnull )pixelBuffer strides:(int * _Nonnull)strides width:(size_t)width height:(size_t)height; 64 | 65 | /// 创建 BGRA32 类型的 PixelBufferPool 66 | /// @param pool CVPixelBufferPoolRef, The newly created pool will be placed here 67 | /// @param width Image Width 68 | /// @param height Image Height 69 | /// @return 是否成功创建 PixelBufferPool 70 | + (BOOL)create32BGRAPixelBufferPool:(CVPixelBufferPoolRef _Nonnull * _Nonnull)pool width:(int)width height:(int)height; 71 | 72 | /// 创建 I420 类型的 PixelBufferPool 73 | /// @param pool CVPixelBufferPoolRef, The newly created pool will be placed here 74 | /// @param width Image Width 75 | /// @param height Image Height 76 | /// @return 是否成功创建 PixelBufferPool 77 | + (BOOL)createI420PixelBufferPool:(CVPixelBufferPoolRef _Nonnull * _Nonnull)pool width:(int)width height:(int)height; 78 | 79 | /// 创建 NV12 类型的 PixelBufferPool 80 | /// @param pool CVPixelBufferPoolRef, The newly created pool will be placed here 81 | /// @param width Image Width 82 | /// @param height Image Height 83 | /// @return 是否成功创建 PixelBufferPool 84 | + (BOOL)createNV12PixelBufferPool:(CVPixelBufferPoolRef _Nonnull * _Nonnull)pool width:(int)width height:(int)height; 85 | 86 | /// 释放 CVPixelBufferPoolRef 87 | /// @param pool 待释放的 CVPixelBufferPoolRef 88 | + (void)destroyPixelBufferPool:(CVPixelBufferPoolRef _Nonnull * _Nonnull)pool; 89 | 90 | /// 拷贝 CVPixelBufferRef 91 | /// @param src Source CVPixelBufferRef 92 | /// @param dst Destination CVPixelBufferRef 93 | + (BOOL)copyPixelBufferFrom:(CVPixelBufferRef _Nonnull)src to:(CVPixelBufferRef _Nonnull)dst; 94 | 95 | @end 96 | 97 | NS_ASSUME_NONNULL_END 98 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoFilter/ZGVideoFilterFactoryDemo.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoFilterFactoryDemo.h 3 | // Runner 4 | // 5 | // Created by Patrick Fu on 2020/3/5. 6 | // Copyright © 2020 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZGVideoFilterFactoryDemo : NSObject 15 | 16 | // 此处的 bufferType 对应四种滤镜类型,以创建不同的外部滤镜实例 17 | @property (nonatomic, assign) ZegoVideoBufferType bufferType; 18 | // TODO: Demo 暂时仅实现了 ZegoVideoBufferTypeAsyncPixelBuffer(BGRA32) 与 ZegoVideoBufferTypeSyncPixelBuffer(BGRA32) 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /example/ios/Runner/ExternalVideoFilter/ZGVideoFilterFactoryDemo.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZGVideoFilterFactoryDemo.m 3 | // Runner 4 | // 5 | // Created by Patrick Fu on 2020/3/5. 6 | // Copyright © 2020 The Chromium Authors. All rights reserved. 7 | // 8 | 9 | #import "ZGVideoFilterFactoryDemo.h" 10 | #import "ZGVideoFilterAsyncDemo.h" 11 | #import "ZGVideoFilterSyncDemo.h" 12 | 13 | @implementation ZGVideoFilterFactoryDemo { 14 | id g_filter_; 15 | } 16 | 17 | #pragma mark - ZegoVideoFilterFactory Delegate 18 | 19 | // 创建外部滤镜实例 20 | - (id)zego_create { 21 | if (g_filter_ == nil) { 22 | // 此处的 bufferType 对应四种滤镜类型,以创建不同的外部滤镜实例 23 | switch (self.bufferType) { 24 | case ZegoVideoBufferTypeAsyncPixelBuffer: 25 | g_filter_ = [[ZGVideoFilterAsyncDemo alloc] init]; 26 | break; 27 | 28 | case ZegoVideoBufferTypeSyncPixelBuffer: 29 | g_filter_ = [[ZGVideoFilterSyncDemo alloc] init]; 30 | break; 31 | 32 | // TODO: NV12/I420 async video filter 33 | default: 34 | break; 35 | } 36 | } 37 | return g_filter_; 38 | } 39 | 40 | // 销毁外部滤镜实例 41 | - (void)zego_destroy:(id)filter { 42 | if (g_filter_ == filter) { 43 | g_filter_ = nil; 44 | } 45 | } 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ZegoLiveRoomExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | NSCameraUsageDescription 47 | Demo需要使用您的摄像头 48 | NSMicrophoneUsageDescription 49 | Demo需要使用您的麦克风 50 | UIBackgroundModes 51 | 52 | audio 53 | 54 | io.flutter.embedded_views_preview 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/config/zego_config.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | import 'dart:io'; 4 | import 'dart:math' show Random; 5 | 6 | class ZegoConfig { 7 | static ZegoConfig _instance = new ZegoConfig._internal(); 8 | 9 | static ZegoConfig getInstance() { 10 | return _instance; 11 | } 12 | 13 | factory ZegoConfig() { 14 | return _instance; 15 | } 16 | 17 | String userID; 18 | String userName; 19 | 20 | String appID; 21 | String appSign; 22 | 23 | // 是否使用测试环境 24 | bool isUseTestEnv; 25 | 26 | // 是否使用 Platform View 27 | bool enablePlatformView; 28 | 29 | // 是否开启外部视频滤镜 30 | bool enableExternalVideoFilter; 31 | 32 | String roomID; 33 | String streamID; 34 | 35 | bool isPreviewMirror; 36 | bool isPublishMirror; 37 | 38 | bool enableVirtualStereo; 39 | double virtualStereoAngle; 40 | bool enableReverb; 41 | int reverbMode; 42 | double voiceChangerValue; 43 | 44 | ZegoConfig._internal() { 45 | 46 | SharedPreferences.getInstance().then((config) { 47 | 48 | this.userID = config.getString('userID') ?? '${Platform.operatingSystem}-${new Random().nextInt(9999999).toString()}'; 49 | this.userName = config.getString('userName') ?? 'user-$userID'; 50 | this.appID ??= config.getString('appID') ?? ''; 51 | this.appSign ??= config.getString('appSign') ?? ''; 52 | this.isUseTestEnv = config.getBool('isUseTestEnv') ?? true; 53 | this.roomID = config.getString('roomID') ?? ''; 54 | this.streamID = config.getString('streamID') ?? ''; 55 | this.enablePlatformView = config.getBool('enablePlatformView') ?? false; 56 | this.enableExternalVideoFilter = config.getBool('enableExternalVideoFilter') ?? false; 57 | 58 | this.isPreviewMirror = true; 59 | this.isPublishMirror = false; 60 | 61 | this.enableVirtualStereo = false; 62 | this.virtualStereoAngle = 90.0; 63 | this.enableReverb = false; 64 | this.reverbMode = 0; 65 | this.voiceChangerValue = 0.0; 66 | }); 67 | } 68 | 69 | Future saveConfig() async { 70 | 71 | SharedPreferences config = await SharedPreferences.getInstance(); 72 | 73 | config.setString('userID', this.userID); 74 | config.setString('userName', this.userName); 75 | config.setString('appID', this.appID); 76 | config.setString('appSign', this.appSign); 77 | config.setBool('isUseTestEnv', this.isUseTestEnv); 78 | config.setString('roomID', this.roomID); 79 | config.setString('streamID', this.streamID); 80 | config.setBool('enablePlatformView', this.enablePlatformView); 81 | config.setBool('enableExternalVideoFilter', this.enableExternalVideoFilter); 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:zegoliveroom_plugin_example/pages/init_sdk_page.dart'; 4 | import 'package:zegoliveroom_plugin_example/config/zego_config.dart'; 5 | 6 | void main() => runApp(MyApp()); 7 | 8 | class MyApp extends StatelessWidget { 9 | // This widget is the root of your application. 10 | @override 11 | Widget build(BuildContext context) { 12 | return MaterialApp( 13 | title: 'ZegoLiveRoom Demo', 14 | theme: ThemeData( 15 | primarySwatch: Colors.blue, 16 | ), 17 | home: HomePage(title: 'ZegoLiveRoom Demo'), 18 | ); 19 | } 20 | } 21 | 22 | class HomePage extends StatelessWidget { 23 | HomePage({Key key, this.title}) : super(key: key); 24 | 25 | final String title; 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | print(ZegoConfig.getInstance()); // Load config instance 30 | 31 | return Scaffold( 32 | appBar: AppBar( 33 | title: Text(title), 34 | ), 35 | body: SafeArea( 36 | child: Center( 37 | child: Column( 38 | mainAxisAlignment: MainAxisAlignment.center, 39 | children: [ 40 | Padding( 41 | padding: const EdgeInsets.only(bottom: 10.0), 42 | ), 43 | CupertinoButton( 44 | color: Color(0xff0e88eb), 45 | child: Text('Publish Stream'), 46 | onPressed: () { 47 | Navigator.of(context).push( 48 | MaterialPageRoute(builder: (BuildContext context) { 49 | return InitPage(true); 50 | })); 51 | }), 52 | Padding( 53 | padding: const EdgeInsets.only(bottom: 10.0), 54 | ), 55 | CupertinoButton( 56 | color: Color(0xff0e88eb), 57 | child: Text(' Play Stream '), 58 | onPressed: () { 59 | Navigator.of(context).push( 60 | MaterialPageRoute(builder: (BuildContext context) { 61 | return InitPage(false); 62 | })); 63 | }), 64 | Padding( 65 | padding: const EdgeInsets.only(bottom: 10.0), 66 | ), 67 | CupertinoButton( 68 | color: Color(0xff0e88eb), 69 | child: Text(' mediaplayer '), 70 | onPressed: () { 71 | Navigator.of(context).push( 72 | MaterialPageRoute(builder: (BuildContext context) { 73 | return InitPage( 74 | false, 75 | isMediaplayer: true, 76 | ); 77 | })); 78 | }), 79 | ], 80 | ), 81 | ))); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /example/lib/ui/zego_ui_tool.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | 4 | class ZegoUITool { 5 | 6 | static showAlert(BuildContext context, String message) { 7 | showDialog(context: context, builder: (BuildContext context) { 8 | return AlertDialog( 9 | title: Text('提示'), 10 | content: Text(message), 11 | actions: [ 12 | FlatButton( 13 | child: Text('确认'), 14 | onPressed: () { 15 | Navigator.of(context).pop(); 16 | }, 17 | ) 18 | ], 19 | ); 20 | }); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: zegoliveroom_plugin_example 2 | description: Demonstrates how to use the zegoliveroom_plugin. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.0.0+1 15 | 16 | environment: 17 | sdk: ">=2.6.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | 23 | zegoliveroom_plugin: 24 | path: ../ 25 | 26 | shared_preferences: ^0.5.6 27 | 28 | zego_permission: 29 | git: 30 | url: git://github.com/zegoim/zego-flutter-permission.git 31 | flutter_seekbar: 32 | git: https://github.com/LiuC520/flutter_seekbar.git 33 | 34 | # The following adds the Cupertino Icons font to your application. 35 | # Use with the CupertinoIcons class for iOS style icons. 36 | cupertino_icons: ^0.1.2 37 | 38 | dev_dependencies: 39 | flutter_test: 40 | sdk: flutter 41 | 42 | 43 | # For information on the generic Dart part of this file, see the 44 | # following page: https://www.dartlang.org/tools/pub/pubspec 45 | 46 | # The following section is specific to Flutter. 47 | flutter: 48 | 49 | # The following line ensures that the Material Icons font is 50 | # included with your application, so that you can use the icons in 51 | # the material Icons class. 52 | uses-material-design: true 53 | 54 | assets: 55 | - resources/images/ 56 | - resources/images/2.0x/ 57 | - resources/images/3.0x/ 58 | 59 | # To add assets to your application, add an assets section, like this: 60 | # assets: 61 | # - images/a_dot_burr.jpeg 62 | # - images/a_dot_ham.jpeg 63 | 64 | # An image asset can refer to one or more resolution-specific "variants", see 65 | # https://flutter.dev/assets-and-images/#resolution-aware. 66 | 67 | # For details regarding adding assets from package dependencies, see 68 | # https://flutter.dev/assets-and-images/#from-packages 69 | 70 | # To add custom fonts to your application, add a fonts section here, 71 | # in this "flutter" section. Each entry in this list should have a 72 | # "family" key with the font family name, and a "fonts" key with a 73 | # list giving the asset and other descriptors for the font. For 74 | # example: 75 | # fonts: 76 | # - family: Schyler 77 | # fonts: 78 | # - asset: fonts/Schyler-Regular.ttf 79 | # - asset: fonts/Schyler-Italic.ttf 80 | # style: italic 81 | # - family: Trajan Pro 82 | # fonts: 83 | # - asset: fonts/TrajanPro.ttf 84 | # - asset: fonts/TrajanPro_Bold.ttf 85 | # weight: 700 86 | # 87 | # For details regarding fonts from package dependencies, 88 | # see https://flutter.dev/custom-fonts/#from-packages -------------------------------------------------------------------------------- /example/resources/images/2.0x/bottom_microphone_off_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/2.0x/bottom_microphone_off_icon.png -------------------------------------------------------------------------------- /example/resources/images/2.0x/bottom_microphone_on_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/2.0x/bottom_microphone_on_icon.png -------------------------------------------------------------------------------- /example/resources/images/2.0x/bottom_switchcamera_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/2.0x/bottom_switchcamera_icon.png -------------------------------------------------------------------------------- /example/resources/images/2.0x/settings_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/2.0x/settings_tips.png -------------------------------------------------------------------------------- /example/resources/images/3.0x/bottom_microphone_off_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/3.0x/bottom_microphone_off_icon.png -------------------------------------------------------------------------------- /example/resources/images/3.0x/bottom_microphone_on_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/3.0x/bottom_microphone_on_icon.png -------------------------------------------------------------------------------- /example/resources/images/3.0x/bottom_switchcamera_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/3.0x/bottom_switchcamera_icon.png -------------------------------------------------------------------------------- /example/resources/images/3.0x/settings_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/3.0x/settings_tips.png -------------------------------------------------------------------------------- /example/resources/images/bottom_microphone_off_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/bottom_microphone_off_icon.png -------------------------------------------------------------------------------- /example/resources/images/bottom_microphone_on_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/bottom_microphone_on_icon.png -------------------------------------------------------------------------------- /example/resources/images/bottom_switchcamera_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/bottom_switchcamera_icon.png -------------------------------------------------------------------------------- /example/resources/images/settings_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/example/resources/images/settings_tips.png -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /ios/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zegoim/zego-flutter-sdk/ffea55734a2dfb4be808ba858adf151a848449cf/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/ZegoAudioPlayerController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoAudioPlayerController.h 3 | // Pods 4 | // 5 | // Created by 李展鹏@ZEGO on 2019/12/12. 6 | // 7 | 8 | #ifndef ZegoAudioPlayerController_h 9 | #define ZegoAudioPlayerController_h 10 | 11 | #import 12 | #import 13 | #import 14 | 15 | @protocol ZegoAudioPlayerControllerDelegate 16 | - (void)onAudioPlayBegin:(unsigned int)soundID errorCode:(int)errorCode; 17 | 18 | - (void)onAudioLoad:(unsigned int)soundID errorCode:(int)errorCode; 19 | 20 | - (void)onAudioLoadComplete:(unsigned int)soundID; 21 | 22 | - (void)onAudioPlayEnd:(unsigned int)soundID; 23 | 24 | @end 25 | 26 | 27 | @interface ZegoAudioPlayerController : NSObject 28 | 29 | + (instancetype)instance; 30 | 31 | - (void)initObject; 32 | - (void)uninitObject; 33 | 34 | - (void)playAudioEffect:(NSDictionary *)args register:(NSObject*)reg result:(FlutterResult)result; 35 | - (void)stopAudioEffect:(NSDictionary *)args result:(FlutterResult)result; 36 | - (void)pauseAudioEffect:(NSDictionary *)args result:(FlutterResult)result; 37 | - (void)resumeAudioEffect:(NSDictionary *)args result:(FlutterResult)result; 38 | - (void)preloadAudioEffect:(NSDictionary *)args register:(NSObject*)reg result:(FlutterResult)result; 39 | - (void)unloadAudioEffect:(NSDictionary *)args result:(FlutterResult)result; 40 | - (void)setAudioEffectVolume:(NSDictionary *)args result:(FlutterResult)result; 41 | 42 | - (void)setAllEffectVolume:(NSDictionary *)args result:(FlutterResult)result; 43 | - (void)pauseAllEffect:(FlutterResult)result; 44 | - (void)stopAllEffect:(FlutterResult)result; 45 | - (void)resumeAllEffect:(FlutterResult)result; 46 | 47 | - (void)seekTo:(NSDictionary *)args result:(FlutterResult)result; 48 | - (void)getTotalDuration:(NSDictionary *)args result:(FlutterResult)result; 49 | - (void)getCurrentDuration:(NSDictionary *)args result:(FlutterResult)result; 50 | 51 | - (BOOL)isPlaying:(int)soundID; 52 | 53 | - (void)setAudioPlayerEventDelegate:(id)delegate; 54 | 55 | 56 | @end 57 | 58 | 59 | #endif /* ZegoAudioPlayerController_h */ 60 | -------------------------------------------------------------------------------- /ios/Classes/ZegoLiveRoomPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | #include 15 | #import "ZegoViewRenderer.h" 16 | 17 | @interface ZegoLiveRoomPlugin : NSObject 18 | 19 | /// 预存外部视频滤镜工厂 20 | /// @discussion 首先实现一个 ZegoVideoFilterFactory ,调用此接口将工厂预存,然后在 dart 层调用 `enableExternalVideoFilterFactory` 接口从而将此预存的工厂设置给 Native ZegoSDK 21 | /// @param factory 外部视频滤镜工厂 22 | + (void)setExternalVideoFilterFactory:(nullable id)factory; 23 | 24 | 25 | /// 预存外部视频采集工厂 26 | /// @discussion 首先实现一个 ZegoVideoCaptureFactory ,调用此接口将工厂预存,然后在 dart 层调用 `enableExternalVideoCaptureFactory` 接口从而将此预存的工厂设置给 Native ZegoSDK 27 | /// @param factory 外部视频采集工厂 28 | + (void)setExternalVideoCaptureFactory:(nullable id)factory; 29 | 30 | @end 31 | 32 | 33 | -------------------------------------------------------------------------------- /ios/Classes/ZegoLog.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoLog.h 3 | // 4 | // 5 | // Created by lizhanpeng@ZEGO on 2019/8/8. 6 | // 7 | 8 | #ifndef ZegoLog_h 9 | #define ZegoLog_h 10 | 11 | #import 12 | 13 | @interface ZegoLog : NSObject 14 | 15 | + (void)logNotice:(NSString *)content; 16 | 17 | @end 18 | 19 | #endif /* ZegoLog_h */ 20 | -------------------------------------------------------------------------------- /ios/Classes/ZegoLog.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoLog.m 3 | // 4 | // 5 | // Created by lizhanpeng@ZEGO on 2019/8/8. 6 | // 7 | 8 | #import "ZegoLog.h" 9 | #include "../../zego_defines.h" 10 | 11 | @implementation ZegoLog 12 | 13 | + (void)logNotice:(NSString *)content { 14 | NSLog(@"%@", content); 15 | zego_liveroom_custom_log(content.UTF8String, 0); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ios/Classes/ZegoMediaplayerController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoMediaplayerController.h 3 | // Pods-Runner 4 | // 5 | // Created by 李展鹏@ZEGO on 2020/4/30. 6 | // 7 | 8 | #ifndef ZegoMediaplayerController_h 9 | #define ZegoMediaplayerController_h 10 | 11 | #import 12 | #import 13 | #import 14 | 15 | #import "ZegoRendererController.h" 16 | 17 | @protocol ZegoMediaPlayerControllerVideoDataDelegate 18 | 19 | - (void)onPlayerVideoFrame: (CVPixelBufferRef)buffer timeStamp: (unsigned long long)timeStamp index:(ZegoMediaPlayerIndex)playerIndex; 20 | 21 | @end 22 | 23 | @protocol ZegoMediaPlayerControllerDelegate 24 | 25 | - (void)onPlayBegin:(ZegoMediaPlayerIndex)playerIndex; 26 | 27 | - (void)onPlayPause:(ZegoMediaPlayerIndex)playerIndex; 28 | 29 | - (void)onPlayResume:(ZegoMediaPlayerIndex)playerIndex; 30 | 31 | - (void)onPlayEnd:(ZegoMediaPlayerIndex)playerIndex; 32 | 33 | - (void)onPlayStop:(ZegoMediaPlayerIndex)playerIndex; 34 | 35 | - (void)onPlayError:(int)errorCode index:(ZegoMediaPlayerIndex)playerIndex; 36 | 37 | - (void)onBufferBegin:(ZegoMediaPlayerIndex)playerIndex; 38 | 39 | - (void)onBufferEnd:(ZegoMediaPlayerIndex)playerIndex; 40 | 41 | - (void)onAudioBegin:(ZegoMediaPlayerIndex)playerIndex; 42 | 43 | - (void)onVideoBegin:(ZegoMediaPlayerIndex)playerIndex; 44 | 45 | - (void)onProcessInterval:(long)timestamp index:(ZegoMediaPlayerIndex)playerIndex; 46 | 47 | - (void)onSeekComplete:(int)errorCode when:(long)millisecond index:(ZegoMediaPlayerIndex)playerIndex; 48 | 49 | @end 50 | 51 | @interface ZegoMediaPlayerController : NSObject 52 | 53 | //+ (instancetype)instance; 54 | 55 | //- (void)initPlayerWithType:(MediaPlayerType)type; 56 | 57 | //- (void)uninit; 58 | 59 | 60 | /// 播放器的 id 61 | @property (nonatomic, assign) ZegoMediaPlayerIndex zegoPlayIndex; 62 | 63 | - (instancetype)initObjectWithIndex:(ZegoMediaPlayerIndex)playerIndex; 64 | 65 | - (void)uninitObject; 66 | 67 | - (void)setDelegate:(id)delegate; 68 | 69 | - (void)setVideoDataDelegate:(id)delegate; 70 | 71 | - (void)setRenderController:(ZegoRendererController *)rndController; 72 | 73 | - (void)setPlatformView:(UIView *)view; 74 | 75 | - (void)start:(NSString *)path repeat:(BOOL)repeat asset:(BOOL)asset reg:(NSObject*)reg result:(FlutterResult)result; 76 | 77 | - (void)stop:(FlutterResult)result; 78 | 79 | - (void)pause:(FlutterResult)result; 80 | 81 | - (void)resume:(FlutterResult)result; 82 | 83 | - (void)seekTo:(long)millisecond result:(FlutterResult)result; 84 | 85 | - (long)getDuration; 86 | 87 | - (long)getCurrentDuration; 88 | 89 | - (void)muteLocal:(BOOL)mute; 90 | 91 | - (void)load:(NSString *)path asset:(BOOL)asset reg:(NSObject*)reg result:(FlutterResult)result; 92 | 93 | - (void)setVolume:(int)volume; 94 | 95 | - (void)setPlayerType:(MediaPlayerType)type; 96 | 97 | - (void)setOnlineResourceCacheDuration:(int)time andSize:(int)size; 98 | 99 | - (void)getOnlineResourceCacheStat:(int*)time andSize:(int*)size; 100 | 101 | - (void)setBufferThreshold:(int)threshold; 102 | 103 | - (void)setLoadResourceTimeout:(int)timeout; 104 | 105 | - (void)setPublishVolume:(int)volume; 106 | 107 | - (void)setPlayVolume:(int)volume; 108 | 109 | - (int)getPublishVolume; 110 | 111 | - (int)getPlayVolume; 112 | 113 | - (long)setAudioStream:(long)streamIndex; 114 | 115 | - (long)getAudioStreamCount; 116 | 117 | - (void)enableRepeatMode:(BOOL)enable; 118 | 119 | - (void)setProcessInterval:(long)interval; 120 | 121 | - (BOOL)isPlaying; 122 | 123 | @end 124 | 125 | #endif /* ZegoMediaplayerController_h */ 126 | -------------------------------------------------------------------------------- /ios/Classes/ZegoPlatformView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoPlatformView.h 3 | // Pods 4 | // 5 | // Created by 李展鹏@ZEGO on 2019/5/30. 6 | // 7 | 8 | #ifndef ZegoPlatformView_h 9 | #define ZegoPlatformView_h 10 | 11 | #import 12 | 13 | @interface ZegoPlatformView : NSObject 14 | 15 | - (instancetype)initWithRect:(CGRect)rect viewID:(int64_t) viewID; 16 | 17 | - (UIView *)getUIView; 18 | 19 | @end 20 | 21 | #endif /* ZegoPlatformView_h */ 22 | -------------------------------------------------------------------------------- /ios/Classes/ZegoPlatformView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoPlatformView.m 3 | // Pods-Runner 4 | // 5 | // Created by 李展鹏@ZEGO on 2019/5/30. 6 | // 7 | 8 | #import "ZegoPlatformView.h" 9 | 10 | @interface ZegoPlatformView() 11 | 12 | @property (nonatomic, strong) UIView *uiView; 13 | @property (nonatomic, assign) int64_t viewID; 14 | 15 | @end 16 | 17 | @implementation ZegoPlatformView 18 | 19 | - (instancetype)initWithRect:(CGRect)rect viewID:(int64_t) viewID { 20 | self = [super init]; 21 | if(self) { 22 | _uiView = [[UIView alloc] initWithFrame:rect]; 23 | _uiView.backgroundColor = [UIColor blackColor]; 24 | _viewID = viewID; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (UIView *)getUIView { 31 | return self.uiView; 32 | } 33 | 34 | # pragma mark - Flutter Platform View Delegate 35 | 36 | - (UIView *)view { 37 | return self.uiView; 38 | } 39 | 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ios/Classes/ZegoPlatformViewFactory.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoPlatformViewFactory.h 3 | // Pods 4 | // 5 | // Created by 李展鹏@ZEGO on 2019/5/30. 6 | // 7 | 8 | #ifndef ZegoPlatformViewFactory_h 9 | #define ZegoPlatformViewFactory_h 10 | 11 | #import 12 | #import "ZegoPlatformView.h" 13 | 14 | @interface ZegoPlatformViewFactory : NSObject 15 | 16 | + (instancetype) shareInstance; 17 | + (void) release; 18 | 19 | - (BOOL)addView:(ZegoPlatformView *)view viewID:(NSNumber *)viewID; 20 | - (BOOL)removeView:(NSNumber *)viewID; 21 | - (ZegoPlatformView *)getPlatformView:(NSNumber *) viewID; 22 | 23 | @end 24 | 25 | #endif /* ZegoPlatformViewFactory_h */ 26 | -------------------------------------------------------------------------------- /ios/Classes/ZegoPlatformViewFactory.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoPlatformViewFactory.m 3 | // Pods 4 | // 5 | // Created by 李展鹏@ZEGO on 2019/5/30. 6 | // 7 | 8 | #import "ZegoPlatformViewFactory.h" 9 | 10 | static ZegoPlatformViewFactory *g_factory = nil; 11 | 12 | @interface ZegoPlatformViewFactory() 13 | 14 | @property (nonatomic, strong) NSMutableDictionary *views; 15 | 16 | @end 17 | 18 | @implementation ZegoPlatformViewFactory 19 | 20 | - (instancetype) init { 21 | self = [super init]; 22 | if(self) { 23 | _views = [[NSMutableDictionary alloc] init]; 24 | 25 | } 26 | return self; 27 | } 28 | 29 | + (instancetype) shareInstance { 30 | static dispatch_once_t onceToken; 31 | dispatch_once(&onceToken, ^{ 32 | g_factory = [[ZegoPlatformViewFactory alloc] init]; 33 | }); 34 | 35 | return g_factory; 36 | } 37 | 38 | + (void)release { 39 | if(g_factory) { 40 | g_factory = nil; 41 | } 42 | } 43 | 44 | - (NSObject*)createWithFrame:(CGRect)frame 45 | viewIdentifier:(int64_t)viewId 46 | arguments:(id _Nullable)args { 47 | 48 | ZegoPlatformView *view = [[ZegoPlatformView alloc] initWithRect:frame viewID:viewId]; 49 | [self addView:view viewID:@(viewId)]; 50 | 51 | return view; 52 | } 53 | 54 | - (BOOL)addView:(ZegoPlatformView *)view viewID:(NSNumber *)viewID { 55 | if(!viewID || !view) 56 | return NO; 57 | 58 | [self.views setObject:view forKey:viewID]; 59 | 60 | return YES; 61 | } 62 | 63 | - (BOOL)removeView:(NSNumber *)viewID { 64 | if(!viewID) 65 | return NO; 66 | 67 | if(![[self.views allKeys] containsObject:viewID]) 68 | return NO; 69 | 70 | [self.views removeObjectForKey:viewID]; 71 | return YES; 72 | } 73 | 74 | - (ZegoPlatformView *)getPlatformView:(NSNumber *) viewID { 75 | if(!viewID) 76 | return nil; 77 | 78 | return [self.views objectForKey:viewID]; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /ios/Classes/ZegoRendererController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZegoRendererController.h 3 | // Pods 4 | // 5 | // Created by 李展鹏@ZEGO on 2018/11/13. 6 | // 7 | 8 | #ifndef ZegoRendererController_h 9 | #define ZegoRendererController_h 10 | 11 | #import 12 | #import "ZegoViewRenderer.h" 13 | 14 | @interface ZegoPixelBufferPool : NSObject 15 | { 16 | CVPixelBufferPoolRef _pool; 17 | int _width; 18 | int _height; 19 | } 20 | 21 | - (CVPixelBufferPoolRef)getBufferPool; 22 | - (int)getWidth; 23 | - (int)getHeight; 24 | 25 | @end 26 | 27 | @interface ZegoRendererController : NSObject 28 | 29 | @property (nonatomic, assign) BOOL isUseFrontCam; 30 | 31 | - (BOOL)addRenderer:(ZegoViewRenderer *)renderer ofKey:(NSString *)streamID; 32 | - (BOOL)removeRenderer:(NSString *)streamID; 33 | - (void)removeAllRenderer; 34 | - (ZegoViewRenderer *)getRenderer:(NSString *)streamID; 35 | - (int)getRenderCount; 36 | - (NSDictionary *)getRenderers; 37 | 38 | - (BOOL)createPixelBufferPool:(int)width height:(int)height streamID:(NSString* )streamID; 39 | - (BOOL)destroyPixelBufferPool:(NSString *)streamID; 40 | - (void)destroyAllPixelBufferPool; 41 | - (ZegoPixelBufferPool *)getPixelBufferPool:(NSString *)streamID; 42 | 43 | - (void)startRendering; 44 | - (void)stopRendering; 45 | - (BOOL)isRendering; 46 | 47 | @end 48 | 49 | #endif /* ZegoRendererController_h */ 50 | -------------------------------------------------------------------------------- /ios/Classes/ZegoViewRenderer.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #include 4 | #include 5 | 6 | typedef enum 7 | { 8 | ZegoRendererScaleAspectFit = 0, ///< 等比缩放,可能有黑边 9 | ZegoRendererScaleAspectFill = 1, ///< 等比缩放填充整View,可能有部分被裁减 10 | ZegoRendererScaleToFill = 2, ///< 填充整个View 11 | }ZegoRendererViewMode; 12 | 13 | @interface ZegoViewRenderer : NSObject 14 | 15 | @property (nonatomic, readonly) int64_t textureID; 16 | @property (nonatomic) int view_width; 17 | @property (nonatomic) int view_height; 18 | 19 | - (void)setSrcFrameBuffer:(CVPixelBufferRef)srcFrameBuffer processBuffer:(CVPixelBufferRef)processBuffer; 20 | - (void)setVideoMode:(ZegoRendererViewMode)mode; 21 | - (void)setUseMirrorEffect:(BOOL)isUse; 22 | 23 | - (BOOL)isNewFrameAvailable; 24 | - (void)notifyDrawNewFrame; 25 | 26 | - (CVPixelBufferRef)getPixelBuffer; 27 | - (void)updateRenderSize:(CGSize)size; 28 | - (instancetype)initWithTextureRegistry:(id)registry isPublisher:(BOOL)isPublisher viewWidth:(int)width viewHeight:(int)height; 29 | 30 | - (void)releaseRenderer:(void(^)(void))callback; 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ios/zegoliveroom_plugin.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'zegoliveroom_plugin' 6 | s.version = '1.0.0' 7 | s.summary = 'A flutter plugin which can use zego services.' 8 | s.description = <<-DESC 9 | A new flutter plugin project. 10 | DESC 11 | s.homepage = 'https://www.zego.im' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Zego' => 'lizhanpeng@zego.im' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | 17 | s.public_header_files = 'Classes/**/*.h' 18 | s.static_framework = true 19 | s.dependency 'Flutter' 20 | s.dependency 'ZegoLiveRoom', '6.16.2.25372' 21 | s.ios.deployment_target = '8.0' 22 | end 23 | -------------------------------------------------------------------------------- /lib/src/zego_liveroom_audio.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:zegoliveroom_plugin/zegoliveroom_plugin.dart'; 4 | 5 | class ZegoLiveRoomAudioPlugin { 6 | /* Method Channel */ 7 | static const MethodChannel _channel = 8 | const MethodChannel('plugins.zego.im/zegoliveroom_plugin'); 9 | 10 | ///耳机插入状态下是否使用回声消除 11 | /// 12 | ///@param enable true 使用,false 不使用。默认 true 13 | ///@discussion InitSDK 之后,在推流之前调用 14 | static Future enableAECWhenHeadsetDetected(bool enable) async { 15 | return await _channel.invokeMethod('enableAECWhenHeadsetDetected', { 16 | 'enable': enable 17 | }); 18 | } 19 | 20 | /// 开启耳返监听 21 | /// 22 | ///@param enable true 使用,false 不使用。默认 false 23 | ///@discussion InitSDK 之后,在推流之前调用 24 | static Future enableLoopback(bool enable) async { 25 | return await _channel.invokeMethod('enableLoopback', { 26 | 'enable': enable 27 | }); 28 | } 29 | 30 | /// 设置耳返音量 31 | /// 32 | ///@param volume 音量,取值为 [0, 100],默认为 80 33 | static Future setLoopbackVolume(int volume) async { 34 | return await _channel.invokeMethod('setLoopbackVolume', { 35 | 'volume': volume 36 | }); 37 | } 38 | 39 | ///设置虚拟立体声 40 | /// 41 | ///@param enable true 开启,false 关闭。默认 false 42 | ///@param angle 角度,范围 0 ~ 180,90 为正前方,0 和 180 分别对应最右边和最左边 43 | ///@discussion 必须在 InitSDK 之后调用,且需调用 [ZegoLiveRoomPublisherPlugin.setAudioChannelCount] 设置为双声道编码 44 | static Future enableVirtualStereo(bool enable, int angle) async { 45 | return await _channel.invokeMethod('enableVirtualStereo', { 46 | 'enable': enable, 47 | 'angle': angle 48 | }); 49 | } 50 | 51 | ///设置音频混响 52 | /// 53 | ///@param enable true 开启,false 关闭。默认为 false 54 | ///@param mode 混响模式,参考 [ZegoAudioReverbMode] 55 | ///@discussion 必须在 InitSDK 之后调用,且推流途中修改 mode 值均能动态生效 56 | static Future enableReverb(bool enable, int mode) async { 57 | return await _channel.invokeMethod('enableReverb', { 58 | 'enable': enable, 59 | 'mode': mode 60 | }); 61 | } 62 | 63 | ///设置音频混响参数值 64 | /// 65 | ///@param 混响参数,参考 [ZegoAudioReverbParam] 66 | ///@discussion 必须在 InitSDK 之后调用,且推流途中修改参数值均能动态生效 67 | static Future setReverbParam(ZegoAudioReverbParam param) async { 68 | return await _channel.invokeMethod('setReverbParam', { 69 | 'param': param.toMap() 70 | }); 71 | } 72 | 73 | ///设置变声器参数 74 | /// 75 | ///@param param 变声参数,取值范围为 [-8.0, 8.0] ,默认为 0 (不变声) 76 | ///@discussion 必须在 InitSDK 之后调用,且仅对采集的声音有效 77 | ///@note 几种典型的变声效果定义如下: 78 | ///@note 1. 女声变男生:-3.0 79 | ///@note 2. 男声变女声:4.0 80 | ///@note 3. 女声变童声:6.0 81 | ///@note 4. 男声变童声:8.0 82 | static Future setVoiceChangerParam(double param) async { 83 | return await _channel.invokeMethod('setVoiceChangerParam', { 84 | 'param': param 85 | }); 86 | } 87 | } -------------------------------------------------------------------------------- /lib/src/zego_liveroom_event_channel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | 4 | /// SDK 事件回调类型 5 | class ZegoEventType { 6 | static const int TYPE_ROOM_EVENT = 0; 7 | static const int TYPE_PUBLISH_EVENT = 1; 8 | static const int TYPE_PLAY_EVENT = 2; 9 | static const int TYPE_MEDIA_SIDE_INFO_EVENT = 3; 10 | static const int TYPE_SOUND_LEVEL_EVENT = 4; 11 | static const int TYPE_MEDIA_PLAYER_EVENT = 5; 12 | static const int TYPE_AUDIO_PLAYER_EVENT = 10; 13 | static const int TYPE_MEDIA_RECORD_EVENT = 11; 14 | } 15 | 16 | class ZegoLiveRoomEventChannel { 17 | /* Event Channel */ 18 | static const EventChannel _eventChannel = 19 | const EventChannel('plugins.zego.im/zegoliveroom_callback'); 20 | 21 | /* Event Stream */ 22 | static Stream _receivedEvents = _eventChannel.receiveBroadcastStream(); 23 | 24 | /// 用于接收native层事件流,开发者无需关注 25 | static Stream listenRoomEvent() { 26 | return _receivedEvents 27 | .map((dynamic event) => event) 28 | .where((Map event) => event['type'] == ZegoEventType.TYPE_ROOM_EVENT) 29 | .map((Map event) => event['method']); 30 | } 31 | 32 | /// 用于接收native层事件流,开发者无需关注 33 | static Stream listenPublishEvent() { 34 | return _receivedEvents 35 | .map((dynamic event) => event) 36 | .where((Map event) => event['type'] == ZegoEventType.TYPE_PUBLISH_EVENT) 37 | .map((Map event) => event['method']); 38 | } 39 | 40 | /// 用于接收native层事件流,开发者无需关注 41 | static Stream listenPlayEvent() { 42 | return _receivedEvents 43 | .map((dynamic event) => event) 44 | .where((Map event) => event['type'] == ZegoEventType.TYPE_PLAY_EVENT) 45 | .map((Map event) => event['method']); 46 | } 47 | 48 | /// 用于接收native层事件流,开发者无需关注 49 | static Stream listenMediaSideInfoEvent() { 50 | return _receivedEvents 51 | .map((dynamic event) => event) 52 | .where((Map event) => event['type'] == ZegoEventType.TYPE_MEDIA_SIDE_INFO_EVENT) 53 | .map((Map event) => event['method']); 54 | } 55 | 56 | /// 用于接收native层事件流,开发者无需关注 57 | static Stream listenSoundLevelEvent() { 58 | return _receivedEvents 59 | .map((dynamic event) => event) 60 | .where((Map event) => event['type'] == ZegoEventType.TYPE_SOUND_LEVEL_EVENT) 61 | .map((Map event) => event['method']); 62 | } 63 | 64 | /// 用于接收native层事件流,开发者无需关注 65 | static Stream listenAudioPlayerEvent() { 66 | return _receivedEvents 67 | .map((dynamic event) => event) 68 | .where((Map event) => event['type'] == ZegoEventType.TYPE_AUDIO_PLAYER_EVENT) 69 | .map((Map event) => event['method']); 70 | } 71 | 72 | /// 用于接收native层事件流,开发者无需关注 73 | static Stream listenMediaPlayerEvent() { 74 | return _receivedEvents 75 | .map((dynamic event) => event) 76 | .where((Map event) => event['type'] == ZegoEventType.TYPE_MEDIA_PLAYER_EVENT) 77 | .map((Map event) => event['method']); 78 | } 79 | 80 | /// 用于接收native层事件流,开发者无需关注 81 | static Stream listenMediaRecordEvent() { 82 | return _receivedEvents 83 | .map((dynamic event) => event) 84 | .where((Map event) => event['type'] == ZegoEventType.TYPE_MEDIA_RECORD_EVENT) 85 | .map((Map event) => event['method']); 86 | } 87 | } -------------------------------------------------------------------------------- /lib/src/zego_media_recorder.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | import 'zego_api_error_code.dart'; 4 | import 'zego_api_defines.dart'; 5 | import 'zego_liveroom_event_channel.dart'; 6 | 7 | 8 | class ZegoMediaRecorderPlugin { 9 | /* Method Channel */ 10 | static const MethodChannel _channel = 11 | const MethodChannel('plugins.zego.im/zegoliveroom_plugin'); 12 | 13 | /// 开始录制 14 | /// 15 | /// @param config 媒体录制配置,详见 [ZegoMediaRecordConfig] 16 | /// @param channelIndex 录制通道 17 | /// @discussion 必须在init sdk之后调用 18 | static Future startRecord(ZegoMediaRecordConfig config) async { 19 | return await _channel.invokeMethod('startRecord', { 20 | 'config': config.toMap() 21 | }); 22 | } 23 | 24 | /// 停止录制 25 | /// 26 | /// @param channelIndex 录制通道 27 | static Future stopRecord() async { 28 | return await _channel.invokeMethod('stopRecord'); 29 | } 30 | 31 | /// 媒体录制回调 32 | /// 33 | /// @param errorCode: 错误码,详见 [ZegoMediaRecordErrorCode] 定义 34 | /// @param channelIndex 录制通道 35 | /// @param storagePath 录制文件存储路径 36 | static void Function(int errorCode, String storagePath) _onMediaRecord; 37 | 38 | /// 录制信息更新回调 39 | /// 40 | /// @param storagePath 录制文件存储路径 41 | /// @param duration 录制时长,单位毫秒 42 | /// @param fileSize 文件大小,单位字节 43 | /// @param quality 录制质量 44 | static void Function(String storagePath, int duration, int fileSize, ZegoPublishStreamQuality quality) _onMediaRecordInfoUpdate; 45 | 46 | /// 用于接收native层事件流,开发者无需关注 47 | static StreamSubscription _streamSubscription; 48 | 49 | ///设置回调对象 50 | /// 51 | ///@discussion 开发者只有调用本 API 设置回调对象才能收到相关回调 52 | static void registerMediaRecordCallback({ 53 | Function(int errorCode, String storagePath) onMediaRecord, 54 | Function(String storagePath, int duration, int fileSize, ZegoPublishStreamQuality quality) onMediaRecordInfoUpdate 55 | }) { 56 | 57 | _onMediaRecord = onMediaRecord; 58 | _onMediaRecordInfoUpdate = onMediaRecordInfoUpdate; 59 | 60 | if (_streamSubscription == null) 61 | _streamSubscription = ZegoLiveRoomEventChannel.listenMediaRecordEvent() 62 | .listen(_eventListener); 63 | } 64 | 65 | ///销毁回调对象 66 | /// 67 | ///@discussion 当开发者不再需要接收回调时,必须显式调用本 API 销毁回调对象 68 | static void unregisterMediaRecordCallback() { 69 | 70 | _onMediaRecord = null; 71 | _onMediaRecordInfoUpdate = null; 72 | 73 | _streamSubscription?.cancel(); 74 | _streamSubscription = null; 75 | } 76 | 77 | /// 用于处理native层事件流,开发者无需关注 78 | static void _eventListener(dynamic data) { 79 | 80 | final Map args = data; 81 | switch (args['name']) { 82 | case 'onMediaRecord': 83 | if (_onMediaRecord != null) { 84 | int errorCode = args['errorCode']; 85 | int channelIndex = args['channelIndex']; 86 | String storagePath = args['storagePath']; 87 | _onMediaRecord(errorCode, storagePath); 88 | } 89 | break; 90 | 91 | case 'onMediaRecordInfoUpdate': 92 | if (_onMediaRecordInfoUpdate != null) { 93 | String storagePath = args['storagePath']; 94 | int duration = args['duration']; 95 | int fileSize = args['fileSize']; 96 | final Map quality = args['quality']; 97 | _onMediaRecordInfoUpdate(storagePath, duration, fileSize, 98 | ZegoPublishStreamQuality( 99 | quality['cfps'], 100 | quality['vencFps'], 101 | quality['fps'], 102 | quality['kbps'], 103 | quality['acapFps'], 104 | quality['afps'], 105 | quality['akbps'], 106 | quality['rtt'], 107 | quality['pktLostRate'] * 1.0 / 255.0, 108 | quality['quality'], 109 | quality['isHardwareVenc'], 110 | quality['videoCodecId'], 111 | quality['width'], 112 | quality['height'] 113 | ) 114 | ); 115 | } 116 | break; 117 | default: 118 | break; 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /lib/src/zego_media_side_info.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | import 'zego_liveroom_event_channel.dart'; 4 | 5 | class ZegoMediaSideInfo { 6 | /* Method Channel */ 7 | static const MethodChannel _channel = 8 | const MethodChannel('plugins.zego.im/zegoliveroom_plugin'); 9 | 10 | ///发送媒体次要信息开关 11 | /// 12 | ///@param bStart true 开启, false 关闭 13 | ///@param bOnlyAudioPublish true 纯音频直播,不传输视频数据, false 音视频直播,传输视频数据 14 | ///@return true 成功,false 失败 15 | ///@attention onlyAudioPublish 开关在 start 开关开启时才生效 16 | ///@attention 必须在InitSDK之后、推流前,设置 17 | static Future setMediaSideFlags(bool start, bool onlyAudioPublish) async { 18 | return await _channel.invokeMethod('setMediaSideFlags', { 19 | 'start' : start, 20 | 'onlyAudioPublish' : onlyAudioPublish 21 | }); 22 | } 23 | 24 | ///发送媒体次要信息 25 | /// 26 | ///@param inData 媒体次要信息数据 27 | ///@return true 成功,false 失败 28 | ///@attention 必须在推流成功后调用 29 | static Future sendMediaSideInfo(String data) async { 30 | return await _channel.invokeMethod('sendMediaSideInfo', { 31 | 'data' : data, 32 | }); 33 | } 34 | 35 | ///设置回调对象 36 | /// 37 | ///@param onRecvMediaSideInfo 设置接收 流媒体次要信息 回调,参考 [_onRecvMediaSideInfo] 定义 38 | ///@discussion 开发者只有调用本 API 设置回调对象才能收到相关回调 39 | static void registerMediaSideInfoCallback({ 40 | Function(String streamID, String data) onRecvMediaSideInfo 41 | }) { 42 | 43 | _onRecvMediaSideInfo = onRecvMediaSideInfo; 44 | 45 | if(_streamSubscription == null) { 46 | _streamSubscription = ZegoLiveRoomEventChannel.listenMediaSideInfoEvent().listen(_eventListener); 47 | } 48 | 49 | } 50 | 51 | ///销毁回调对象 52 | /// 53 | ///@discussion 当开发者不再需要接收回调时,必须显式调用本 API 销毁回调对象 54 | static void unregisterMediaSideInfoCallback() { 55 | 56 | _onRecvMediaSideInfo = null; 57 | 58 | _streamSubscription?.cancel(); 59 | _streamSubscription = null; 60 | 61 | } 62 | 63 | 64 | 65 | ///流媒体次要信息回调 66 | /// 67 | ///@param streamID 流ID,标记当前回调的信息属于哪条流 68 | ///@param data,数据缓冲区,存储流媒体次要信息 69 | static void Function(String streamID, String data) _onRecvMediaSideInfo; 70 | 71 | 72 | 73 | 74 | /// 用于接收native层事件流,开发者无需关注 75 | static StreamSubscription _streamSubscription; 76 | /// 用于处理native层事件流,开发者无需关注 77 | static void _eventListener(dynamic data) { 78 | 79 | final Map args = data; 80 | switch (args['name']) { 81 | case 'onRecvMediaSideInfo': 82 | if (_onRecvMediaSideInfo != null) { 83 | 84 | String streamID = args['streamID']; 85 | String data = args['data']; 86 | 87 | _onRecvMediaSideInfo(streamID, data); 88 | } 89 | break; 90 | default: 91 | break; 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /lib/src/zego_sound_level.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/services.dart'; 3 | import 'zego_liveroom_event_channel.dart'; 4 | 5 | class ZegoSoundLevelInfo { 6 | 7 | /// 流ID 8 | final String streamID; 9 | /// SoundLevel 数值 10 | final double soundLevel; 11 | 12 | const ZegoSoundLevelInfo(this.streamID, this.soundLevel); 13 | } 14 | 15 | class ZegoSoundLevel { 16 | /* Method Channel */ 17 | static const MethodChannel _channel = 18 | const MethodChannel('plugins.zego.im/zegoliveroom_plugin'); 19 | 20 | static Future setSoundLevelMonitorCycle(int ms) async { 21 | final success = await _channel.invokeMethod('setSoundLevelMonitorCycle', { 22 | 'ms': ms 23 | }); 24 | 25 | return success; 26 | } 27 | 28 | static Future startSoundLevelMonitor() async { 29 | final success = await _channel.invokeMethod('startSoundLevelMonitor'); 30 | return success; 31 | } 32 | 33 | static Future stopSoundLevelMonitor() async { 34 | final success = await _channel.invokeMethod('stopSoundLevelMonitor'); 35 | return success; 36 | } 37 | 38 | static Future registerSoundLevelCallback({ 39 | Function(ZegoSoundLevelInfo soundLevel) onCaptureSoundLevelUpdate, 40 | Function(List soundLevels) onSoundLevelUpdate 41 | }) async { 42 | 43 | await _channel.invokeMethod('registerSoundLevelCallback'); 44 | 45 | _onCaptureSoundLevelUpdate = onCaptureSoundLevelUpdate; 46 | _onSoundLevelUpdate = onSoundLevelUpdate; 47 | 48 | if(_streamSubscription == null) 49 | _streamSubscription = ZegoLiveRoomEventChannel.listenSoundLevelEvent().listen(_eventListener); 50 | } 51 | 52 | static Future unregisterSoundLevelCallback() async { 53 | 54 | await _channel.invokeMethod('unregisterSoundLevelCallback'); 55 | 56 | _onCaptureSoundLevelUpdate = null; 57 | _onSoundLevelUpdate = null; 58 | 59 | _streamSubscription?.cancel(); 60 | _streamSubscription = null; 61 | } 62 | 63 | 64 | static void Function(ZegoSoundLevelInfo soundLevel) _onCaptureSoundLevelUpdate; 65 | 66 | static void Function(List soundLevels) _onSoundLevelUpdate; 67 | 68 | /// 用于接收native层事件流,开发者无需关注 69 | static StreamSubscription _streamSubscription; 70 | /// 用于处理native层事件流,开发者无需关注 71 | static void _eventListener(dynamic data) { 72 | 73 | final Map args = data; 74 | switch (args['name']) { 75 | case 'onCaptureSoundLevelUpdate': 76 | if (_onCaptureSoundLevelUpdate != null) { 77 | 78 | String streamID = args['streamID']; 79 | double soundLevel = args['soundLevel']; 80 | 81 | ZegoSoundLevelInfo info = ZegoSoundLevelInfo(streamID, soundLevel); 82 | _onCaptureSoundLevelUpdate(info); 83 | } 84 | break; 85 | case 'onSoundLevelUpdate': 86 | if(_onSoundLevelUpdate != null) { 87 | 88 | List infos = []; 89 | List soundLevels = args['soundLevels']; 90 | for(Map soundLevelInfo in soundLevels) { 91 | String streamID = soundLevelInfo['streamID']; 92 | double soundLevel = soundLevelInfo['soundLevel']; 93 | 94 | ZegoSoundLevelInfo objInfo = ZegoSoundLevelInfo(streamID, soundLevel); 95 | infos.add(objInfo); 96 | } 97 | 98 | _onSoundLevelUpdate(infos); 99 | } 100 | break; 101 | default: 102 | break; 103 | } 104 | } 105 | 106 | 107 | } -------------------------------------------------------------------------------- /lib/zegoliveroom_plugin.dart: -------------------------------------------------------------------------------- 1 | library zegoliveroom_plugin; 2 | 3 | export 'src/zego_api_defines.dart'; 4 | export 'src/zego_api_error_code.dart'; 5 | export 'src/zego_liveroom_audio.dart'; 6 | export 'src/zego_liveroom.dart'; 7 | export 'src/zego_liveroom_publisher.dart'; 8 | export 'src/zego_liveroom_player.dart'; 9 | export 'src/zego_media_side_info.dart'; 10 | export 'src/zego_sound_level.dart'; 11 | export 'src/zego_audioplayer.dart'; 12 | export 'src/zego_mediaplayer.dart'; 13 | export 'src/zego_media_recorder.dart'; 14 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: zegoliveroom_plugin 2 | description: A flutter plugin that can provide real-time communication and live video broadcast. 3 | version: 1.7.0 4 | homepage: https://zego.im 5 | 6 | environment: 7 | sdk: ">=2.6.0 <3.0.0" 8 | flutter: ^1.10.0 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | 18 | # For information on the generic Dart part of this file, see the 19 | # following page: https://dart.dev/tools/pub/pubspec 20 | 21 | # The following section is specific to Flutter. 22 | flutter: 23 | # This section identifies this Flutter project as a plugin project. 24 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily 25 | # be modified. They are used by the tooling to maintain consistency when 26 | # adding or updating assets for this project. 27 | plugin: 28 | platforms: 29 | android: 30 | package: com.zego.zegoliveroomplugin 31 | pluginClass: ZegoLiveRoomPlugin 32 | ios: 33 | pluginClass: ZegoLiveRoomPlugin 34 | -------------------------------------------------------------------------------- /zego_defines.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define ZEGO_API __attribute__((visibility("default"))) 4 | 5 | 6 | extern ZEGO_API void zego_liveroom_custom_log(const char* content, int nLogType); 7 | 8 | extern ZEGO_API void ZegoExternalLogWithNotice(const char* content); 9 | //inline void log_string_notice(const char* content) { zego_liveroom_custom_log(content);} 10 | -------------------------------------------------------------------------------- /zegoliveroom_plugin.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /zegoliveroom_plugin_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | --------------------------------------------------------------------------------