Explorar o código

接入大牛安卓实现

Melon hai 1 ano
pai
achega
fcc188200a

+ 1 - 0
.flutter-plugins

@@ -1,4 +1,5 @@
 # This is a generated file; do not edit or check into version control.
+daniulive=C:\\Users\\18651\\AppData\\Local\\Pub\\Cache\\git\\fis_plugin_daniu-d2d5718dad770607567acc8825e77b65b29fa4cb\\
 image_crop_plus=C:\\Users\\18651\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\image_crop_plus-0.6.1\\
 path_provider=C:\\Users\\18651\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider-2.0.2\\
 path_provider_linux=C:\\Users\\18651\\AppData\\Local\\Pub\\Cache\\hosted\\pub.flutter-io.cn\\path_provider_linux-2.1.8\\

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
.flutter-plugins-dependencies


+ 2 - 0
android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java

@@ -4,6 +4,7 @@ import io.flutter.plugin.common.PluginRegistry;
 import eu.wroblewscy.marcin.imagecrop.ImageCropPlugin;
 import io.flutter.plugins.pathprovider.PathProviderPlugin;
 import com.tencent.trtcplugin.TRTCCloudPlugin;
+import com.vinno.plugins.daniulive.DaniulivePlugin;
 
 /**
  * Generated file. Do not edit.
@@ -16,6 +17,7 @@ public final class GeneratedPluginRegistrant {
     ImageCropPlugin.registerWith(registry.registrarFor("eu.wroblewscy.marcin.imagecrop.ImageCropPlugin"));
     PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
     TRTCCloudPlugin.registerWith(registry.registrarFor("com.tencent.trtcplugin.TRTCCloudPlugin"));
+    DaniulivePlugin.registerWith(registry.registrarFor("com.vinno.plugins.daniulive.DaniulivePlugin"))
   }
 
   private static boolean alreadyRegisteredWith(PluginRegistry registry) {

+ 9 - 0
example/pubspec.lock

@@ -85,6 +85,15 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.0.5"
+  daniulive:
+    dependency: transitive
+    description:
+      path: "."
+      ref: "^0.0.1"
+      resolved-ref: d2d5718dad770607567acc8825e77b65b29fa4cb
+      url: "http://git.ius.plus:88/melon.yin/fis_plugin_daniu"
+    source: git
+    version: "0.0.1"
   dio:
     dependency: transitive
     description:

+ 59 - 10
lib/implementations/nt_rtmp/channel/channel_io.dart

@@ -1,3 +1,12 @@
+import 'package:daniulive/controllers/interfaces/play_controller.dart';
+import 'package:daniulive/controllers/merge_play_controller.dart';
+import 'package:daniulive/controllers/play_controller.dart';
+import 'package:daniulive/controllers/publish_controller.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/members.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/models.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/values.dart';
+import 'package:flutter/foundation.dart';
+
 import '../native_share.dart';
 import 'base.dart';
 
@@ -8,22 +17,27 @@ class NTPublishChannel extends NTBasePublishChannel {
 
   @override
   void setAudioMute(bool isMute) async {
-    // await NTNativeShare.ins.setLocalMuteAudio(isMute);
+    await NTNativeShare.publishController?.muteAudio(isMute);
     super.setAudioMute(isMute);
   }
 
   @override
   void setVideoMute(bool isMute) async {
-    // await NTNativeShare.ins.setLocalMuteVideo(isMute);
+    await NTNativeShare.publishController?.muteVideo(isMute);
     super.setVideoMute(isMute);
   }
 
   @override
   void setVolume(int volume) async {
-    // await NTNativeShare.ins.setLocalVolume(volume);
+    await NTNativeShare.publishController?.setVolume(volume);
     _volume = volume;
   }
 
+  @override
+  void onViewIdChanged() {
+    updateReadyState(viewId > 0);
+  }
+
   @override
   int get volume => _volume;
 }
@@ -31,43 +45,78 @@ class NTPublishChannel extends NTBasePublishChannel {
 class NTPlayChannel extends NTBasePlayChannel {
   int _volume = 100;
 
-  NTPlayChannel({required super.member});
+  NTPlayChannel({required super.member}) {
+    _initMobile();
+  }
 
   @override
   int get volume => _volume;
 
+  IPlayController? get playController =>
+      NTNativeShare.playControllers.get(member.userId!);
+
   @override
   void setAudioMute(bool isMute) async {
-    // await NTNativeShare.ins.setRemoteMuteAudio(member.userId!, isMute);
+    await playController?.muteAudio(isMute);
     super.setAudioMute(isMute);
   }
 
   @override
   void setVideoMute(bool isMute) async {
-    // await NTNativeShare.ins.setRemoteMuteVideo(member.userId!, isMute);
+    await playController?.muteVideo(isMute);
     super.setVideoMute(isMute);
   }
 
   @override
   Future<void> play() async {
-    // await NTNativeShare.ins.startRemote(member.userId!);
+    await playController?.play();
     return super.play();
   }
 
   @override
   Future<void> stop() async {
-    // await NTNativeShare.ins.stopRemote(member.userId!);
+    await playController?.stop();
     return super.stop();
   }
 
   @override
   void setVolume(int volume) async {
-    // await NTNativeShare.ins.setRemoteVolume(member.userId!, volume);
+    await playController?.setVolume(volume);
     _volume = volume;
   }
 
   @override
   void onViewIdChanged() {
-    // TODO: implement onViewIdChanged
+    updateReadyState(viewId > 0);
+  }
+
+  void _initMobile() {
+    final userId = member.userId!;
+    if (isDevice) {
+      _loadMobileDevice(userId);
+    } else {
+      final controller = PlayController(liveInfo.rtmpUrl, userId: userId);
+      NTNativeShare.playControllers.put(userId, controller);
+    }
+  }
+
+  void _loadMobileDevice(String userId) {
+    DeviceRtmpLiveInfo info = liveInfo as DeviceRtmpLiveInfo;
+    if (info.isMerge) {
+      final subCount = (member as RtmpMemberInfo).deviceInfoList!.length - 1;
+      if (isDeviceMain) {
+        final controller = MergePlayController(
+          liveInfo.rtmpUrl,
+          userId: MERGE_DEVICE_NATIVE_SIGN,
+          mergeWidth: info.mergeWidth,
+          mergeHeight: info.mergeHeight,
+          subViewCount: subCount,
+        );
+        NTNativeShare.playControllers.put(MERGE_DEVICE_NATIVE_SIGN, controller);
+      }
+    } else {
+      final controller = PlayController(liveInfo.rtmpUrl, userId: userId);
+      NTNativeShare.playControllers.put(userId, controller);
+    }
   }
 }

+ 25 - 9
lib/implementations/nt_rtmp/native_share.dart

@@ -1,9 +1,25 @@
-// import 'package:daniulive/daniulive.dart';
-
-// class NTNativeShare {
-//   static Daniulive? _ins;
-//   static Daniulive get ins {
-//     _ins ??= Daniulive();
-//     return _ins!;
-//   }
-// }
+import 'package:daniulive/controllers/interfaces/play_controller.dart';
+import 'package:daniulive/controllers/interfaces/publish_controller.dart';
+import 'package:daniulive/platform_interface.dart';
+
+class NTNativeShare {
+  static DaniulivePlatform get instance => DaniulivePlatform.instance;
+
+  static IPublishController? publishController;
+
+  static final playControllers = _PlayControllerMap();
+}
+
+class _PlayControllerMap {
+  final Map<String, IPlayController> _map = {};
+  IPlayController? get(String userId) {
+    if (_map.containsKey(userId)) {
+      return _map[userId];
+    }
+    return null;
+  }
+
+  void put(String userId, IPlayController controller) {
+    _map[userId] = controller;
+  }
+}

+ 35 - 16
lib/implementations/nt_rtmp/publisher.dart

@@ -1,5 +1,7 @@
 import 'dart:collection';
 
+import 'package:daniulive/controllers/publish_controller.dart';
+import 'package:daniulive/entities/publish_profile.dart';
 import 'package:fis_common/env/env.dart';
 import 'package:fis_lib_media_rt/base/index.dart';
 import 'package:fis_lib_media_rt/implementations/nt_rtmp/members.dart';
@@ -9,6 +11,7 @@ import 'package:fis_lib_media_rt/interface/channel.dart';
 import 'package:flutter/foundation.dart';
 
 import 'channel/channel.dart';
+import 'native_share.dart';
 import 'room.dart';
 
 class NTPublisher extends BasePublisher {
@@ -33,17 +36,20 @@ class NTPublisher extends BasePublisher {
     _profile = profile;
     await _init();
 
-    if (kIsWeb) {
-      //TODO:
-      (channels.first as NTPublishChannel).viewId = 10010;
-    }
+    //TODO: make local channel ready
+    (channels.first as NTPublishChannel).viewId = 10010;
   }
 
   @override
   Future<void> startLocal() async {
     await _init();
-    if (!FPlatform.isPureWeb) {
-      await ShellApi.startRtmpPublish();
+
+    if (kIsWeb) {
+      if (!FPlatform.isPureWeb) {
+        await ShellApi.startRtmpPublish();
+      }
+    } else {
+      await NTNativeShare.instance.startLocal();
     }
     _channel!.isPreviewing = true;
   }
@@ -51,8 +57,13 @@ class NTPublisher extends BasePublisher {
   @override
   Future<void> stopLocal() async {
     if (!_hasInit) return;
-    if (!FPlatform.isPureWeb) {
-      await ShellApi.stopRtmpPublish();
+
+    if (kIsWeb) {
+      if (!FPlatform.isPureWeb) {
+        await ShellApi.stopRtmpPublish();
+      }
+    } else {
+      await NTNativeShare.instance.stopLocal();
     }
     _channel!.isPreviewing = false;
     _hasInit = false;
@@ -66,13 +77,19 @@ class NTPublisher extends BasePublisher {
   }
 
   Future<void> _init() async {
-    if (!_hasInit) {
-      final member = _rtmpRoom.localMember as NTLocalMember;
-      final pushUrl = member.memberInfo.liveInfo?.pushUrl;
+    if (_hasInit) return;
 
-      if (pushUrl == null || pushUrl.isEmpty) return;
+    final member = _rtmpRoom.localMember as NTLocalMember;
+    final pushUrl = member.memberInfo.liveInfo?.pushUrl;
 
-      if (!FPlatform.isPureWeb) {
+    if (pushUrl == null || pushUrl.isEmpty) {
+      throw ArgumentError.notNull("Publish url of Local member");
+    }
+
+    if (kIsWeb) {
+      if (FPlatform.isPureWeb) {
+        await Future.delayed(const Duration(milliseconds: 100));
+      } else {
         await ShellApi.initRtmpPublisher(
           RtmpPublishProfile(
             url: pushUrl,
@@ -81,10 +98,12 @@ class NTPublisher extends BasePublisher {
             microphoneName: _profile!.idealMicrophoneName,
           ),
         );
-      } else {
-        await Future.delayed(const Duration(milliseconds: 100));
       }
-      _hasInit = true;
+    } else {
+      await NTNativeShare.instance.initLocal(PublishProfile(url: pushUrl));
+      NTNativeShare.publishController = PublishController(pushUrl);
     }
+
+    _hasInit = true;
   }
 }

+ 14 - 6
lib/implementations/nt_rtmp/room.dart

@@ -6,7 +6,9 @@ import 'package:fis_lib_media_rt/interface/member.dart';
 import 'package:fis_lib_media_rt/interface/publisher.dart';
 
 import 'package:fis_lib_media_rt/interface/player.dart';
+import 'package:flutter/foundation.dart';
 
+import 'native_share.dart';
 import 'player.dart';
 import 'publisher.dart';
 import 'rtc_adapter.dart';
@@ -26,9 +28,12 @@ class NTRtmpRoom extends BaseRoom {
     try {
       NTRtmp2RtcAdapter.adapter.room = this;
 
-      Future.delayed(const Duration(milliseconds: 100), () {
-        entered.emit(this, null);
-      });
+      if (kIsWeb) {
+        await Future.delayed(const Duration(milliseconds: 100));
+      } else {
+        await NTNativeShare.instance.enterRoom();
+      }
+      entered.emit(this, null);
     } catch (e) {
       logger.e("$TAG - Enter room error", e);
     }
@@ -40,9 +45,12 @@ class NTRtmpRoom extends BaseRoom {
       NTRtmp2RtcAdapter.adapter.room = null;
       NTRtmp2RtcAdapter.adapter.localMemberInfo = null;
 
-      Future.delayed(const Duration(milliseconds: 100), () {
-        exited.emit(this, null);
-      });
+      if (kIsWeb) {
+        await Future.delayed(const Duration(milliseconds: 100));
+      } else {
+        await NTNativeShare.instance.exitRoom();
+      }
+      exited.emit(this, null);
     } catch (e) {
       logger.e("$TAG - Exit room error", e);
     }

+ 3 - 0
lib/implementations/nt_rtmp/values.dart

@@ -5,3 +5,6 @@ const TAG = "NT_RTMP";
 
 /// iframe id 前缀
 const IFRAME_ID_PREFIX = "fis_media_rt_iframe_";
+
+/// 合图设备native端通用标识
+const MERGE_DEVICE_NATIVE_SIGN = "MergeDevice";

+ 3 - 2
lib/implementations/nt_rtmp/widgets/preview_view/inner_view_io.dart

@@ -1,4 +1,6 @@
+import 'package:daniulive/views/publish_view.dart';
 import 'package:fis_lib_media_rt/implementations/nt_rtmp/channel/channel.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/native_share.dart';
 import 'package:flutter/material.dart';
 
 class InnerView extends StatefulWidget {
@@ -12,7 +14,6 @@ class InnerView extends StatefulWidget {
 class _InnerViewState extends State<InnerView> {
   @override
   Widget build(BuildContext context) {
-    // TODO: implement build
-    throw UnimplementedError();
+    return PublishView(controller: NTNativeShare.publishController!);
   }
 }

+ 54 - 2
lib/implementations/nt_rtmp/widgets/remote_view/inner_view_io.dart

@@ -1,4 +1,11 @@
+import 'package:daniulive/controllers/interfaces/play_controller.dart';
+import 'package:daniulive/controllers/merge_play_controller.dart';
+import 'package:daniulive/views/merge_play_view/main_view.dart';
+import 'package:daniulive/views/play_view.dart';
 import 'package:fis_lib_media_rt/implementations/nt_rtmp/channel/channel.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/models.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/native_share.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/values.dart';
 import 'package:flutter/material.dart';
 
 class InnerView extends StatefulWidget {
@@ -10,9 +17,54 @@ class InnerView extends StatefulWidget {
 }
 
 class _InnerViewState extends State<InnerView> {
+  bool _hasInit = false;
+  bool _isMerge = false;
+
+  late final IPlayController controller;
+
+  @override
+  void initState() {
+    controller = _loadController();
+    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+      controller.init().then((_) {
+        setState(() {
+          _hasInit = true;
+        });
+      });
+    });
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    controller.dispose();
+    super.dispose();
+  }
+
   @override
   Widget build(BuildContext context) {
-    // TODO: implement build
-    throw UnimplementedError();
+    if (!_hasInit) {
+      return const SizedBox();
+    } else {
+      if (_isMerge) {
+        return MergePlayMainView(
+          width: widget.channel.liveInfo.width,
+          height: widget.channel.liveInfo.height,
+          controller: controller as MergePlayController,
+        );
+      } else {
+        return PlayView(controller: controller);
+      }
+    }
+  }
+
+  IPlayController _loadController() {
+    if (widget.channel.isDeviceMain) {
+      _isMerge = (widget.channel.liveInfo as DeviceRtmpLiveInfo).isMerge;
+      if (_isMerge) {
+        return NTNativeShare.playControllers.get(MERGE_DEVICE_NATIVE_SIGN)!;
+      }
+    }
+    return NTNativeShare.playControllers.get(widget.channel.member.userId!)!;
   }
 }

+ 17 - 2
lib/implementations/nt_rtmp/widgets/sub_view/inner_view_io.dart

@@ -1,4 +1,8 @@
+import 'package:daniulive/controllers/merge_play_controller.dart';
+import 'package:daniulive/views/merge_play_view/sub_view.dart';
 import 'package:fis_lib_media_rt/implementations/nt_rtmp/channel/channel.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/native_share.dart';
+import 'package:fis_lib_media_rt/implementations/nt_rtmp/values.dart';
 import 'package:flutter/material.dart';
 
 class InnerView extends StatefulWidget {
@@ -10,9 +14,20 @@ class InnerView extends StatefulWidget {
 }
 
 class _InnerViewState extends State<InnerView> {
+  late final MergePlayController controller;
+
+  @override
+  void initState() {
+    controller = NTNativeShare.playControllers.get(MERGE_DEVICE_NATIVE_SIGN)!
+        as MergePlayController;
+    super.initState();
+  }
+
   @override
   Widget build(BuildContext context) {
-    // TODO: implement build
-    throw UnimplementedError();
+    return MergePlaySubView(
+      index: 1,
+      controller: controller,
+    );
   }
 }

+ 5 - 2
pubspec.yaml

@@ -28,8 +28,11 @@ dependencies:
       ref: ed3bf90
   image_crop_plus: ^0.6.1
   js: ^0.6.4
-  # daniulive:
-  #   path: D:\flutter\daniu\daniulive
+  daniulive:
+    git:
+      url: http://git.ius.plus:88/melon.yin/fis_plugin_daniu
+      ref: ^0.0.1
+    # path: ../../fis_packages/fis_plugin_daniu
 
 dev_dependencies:
   flutter_test:

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio