Skip to content

Commit

Permalink
Merge pull request #566 from 100mslive/develop
Browse files Browse the repository at this point in the history
Release 0.7.1: Develop to main
  • Loading branch information
ygit authored May 20, 2022
2 parents 90aa6ec + 2ab2cda commit 37a36b9
Show file tree
Hide file tree
Showing 109 changed files with 3,395 additions and 1,871 deletions.
5 changes: 2 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ group 'live.hms.hmssdk_flutter'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.5.0'
ext.kotlin_version = '+'
repositories {
google()
jcenter()
Expand Down Expand Up @@ -37,8 +37,7 @@ android {
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.github.100mslive.android-sdk:lib:2.3.4'
implementation 'com.github.100mslive.android-sdk:lib:2.3.9'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
implementation "org.jetbrains.kotlin:kotlin-script-runtime:1.5.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package live.hms.hmssdk_flutter

import android.util.Log
import live.hms.video.connection.stats.HMSLocalAudioStats
import live.hms.video.connection.stats.HMSLocalVideoStats
import live.hms.video.connection.stats.HMSRemoteAudioStats
import live.hms.video.connection.stats.HMSRemoteVideoStats
import live.hms.video.media.settings.HMSVideoResolution
import live.hms.video.media.tracks.*
import live.hms.video.sdk.models.HMSPeer

class HMSRtcStatsExtension {

companion object{

fun toDictionary(hmsRemoteVideoStats: HMSRemoteVideoStats, track : HMSTrack?, peer: HMSPeer?):HashMap<String,Any?>?{
val args=HashMap<String,Any?>()
if(peer==null || hmsRemoteVideoStats==null || track==null)return null
args.put("peer", HMSPeerExtension.toDictionary(peer)!!)
args.put("track",HMSTrackExtension.toDictionary(track)!!)

val hmsRemoteVideoStatsMap = HashMap<String,Any?>()
if(hmsRemoteVideoStats==null) return null
hmsRemoteVideoStatsMap["bytes_received"] = hmsRemoteVideoStats.bytesReceived
hmsRemoteVideoStatsMap["jitter"] = hmsRemoteVideoStats.jitter
hmsRemoteVideoStatsMap["bitrate"] = hmsRemoteVideoStats.bitrate
hmsRemoteVideoStatsMap["packets_lost"] = hmsRemoteVideoStats.packetsLost
hmsRemoteVideoStatsMap["packets_received"] = hmsRemoteVideoStats.packetsReceived
hmsRemoteVideoStatsMap["frame_rate"] = hmsRemoteVideoStats.frameRate
hmsRemoteVideoStatsMap["resolution"] = HMSVideoResolutionExtension.toDictionary(hmsRemoteVideoStats.resolution)

args.put("remote_video_stats",hmsRemoteVideoStatsMap)
return args;
}

fun toDictionary(hmsRemoteAudioStats: HMSRemoteAudioStats, track : HMSTrack?, peer: HMSPeer?):HashMap<String,Any?>?{
val args=HashMap<String,Any?>()
if(peer==null || hmsRemoteAudioStats==null || track==null)return null
args.put("peer", HMSPeerExtension.toDictionary(peer)!!)
args.put("track",HMSTrackExtension.toDictionary(track)!!)


val hmsRemoteAudioStatsMap = HashMap<String,Any?>()
if(hmsRemoteAudioStats==null) return null
hmsRemoteAudioStatsMap["bytes_received"] = hmsRemoteAudioStats.bytesReceived
hmsRemoteAudioStatsMap["jitter"] = hmsRemoteAudioStats.jitter
hmsRemoteAudioStatsMap["bitrate"] = hmsRemoteAudioStats.bitrate
hmsRemoteAudioStatsMap["packets_lost"] = hmsRemoteAudioStats.packetsLost
hmsRemoteAudioStatsMap["packets_received"] = hmsRemoteAudioStats.packetsReceived

args.put("remote_audio_stats",hmsRemoteAudioStatsMap)
return args;
}

fun toDictionary(hmsLocalAudioStats: HMSLocalAudioStats, track : HMSTrack?, peer: HMSPeer?):HashMap<String,Any?>?{
val args=HashMap<String,Any?>()
if(peer==null || hmsLocalAudioStats==null || track==null)return null
args.put("peer", HMSPeerExtension.toDictionary(peer)!!)
args.put("track",HMSTrackExtension.toDictionary(track)!!)


val hmsLocalAudioStatsMap = HashMap<String,Any?>()
if(hmsLocalAudioStats==null) return null
hmsLocalAudioStatsMap["bytes_received"] = hmsLocalAudioStats.bytesSent
hmsLocalAudioStatsMap["bitrate"] = hmsLocalAudioStats.bitrate
hmsLocalAudioStatsMap["round_trip_time"] = hmsLocalAudioStats.roundTripTime
args.put("local_audio_stats",hmsLocalAudioStatsMap)
return args;
}

fun toDictionary(hmsLocalVideoStats: HMSLocalVideoStats, track : HMSTrack?, peer: HMSPeer?):HashMap<String,Any?>?{
val args=HashMap<String,Any?>()
if(peer==null || hmsLocalVideoStats==null || track==null)return null
args.put("peer", HMSPeerExtension.toDictionary(peer)!!)
args.put("track",HMSTrackExtension.toDictionary(track)!!)


val hmsLocaVideoStatsMap = HashMap<String,Any?>()
if(hmsLocalVideoStats==null) return null
hmsLocaVideoStatsMap["bytes_received"] = hmsLocalVideoStats.bytesSent
hmsLocaVideoStatsMap["bitrate"] = hmsLocalVideoStats.bitrate
hmsLocaVideoStatsMap["round_trip_time"] = hmsLocalVideoStats.roundTripTime
hmsLocaVideoStatsMap["frame_rate"] = hmsLocalVideoStats.frameRate
hmsLocaVideoStatsMap["resolution"] = HMSVideoResolutionExtension.toDictionary(hmsLocalVideoStats.resolution)
args.put("local_video_stats",hmsLocaVideoStatsMap)
return args;
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package live.hms.hmssdk_flutter

import live.hms.video.media.settings.HMSVideoResolution

class HMSVideoResolutionExtension {

companion object{

fun toDictionary(hmsVideoResolution: HMSVideoResolution?):HashMap<String,Any?>?{

val args=HashMap<String,Any?>()
if(hmsVideoResolution == null) return null
args["height"] = hmsVideoResolution.height/1.0
args["width"] = hmsVideoResolution.width/1.0

return args;
}
}
}
157 changes: 150 additions & 7 deletions android/src/main/kotlin/live/hms/hmssdk_flutter/HmssdkFlutterPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.content.Intent
import android.media.projection.MediaProjectionManager
import android.os.Build
import androidx.annotation.NonNull
import io.flutter.Log

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
Expand All @@ -23,8 +22,7 @@ import kotlinx.coroutines.launch
import live.hms.hmssdk_flutter.hms_role_components.AudioParamsExtension
import live.hms.hmssdk_flutter.hms_role_components.VideoParamsExtension
import live.hms.hmssdk_flutter.views.HMSVideoViewFactory
import live.hms.video.connection.stats.quality.HMSNetworkObserver
import live.hms.video.connection.stats.quality.HMSNetworkQuality
import live.hms.video.connection.stats.*
import live.hms.video.error.HMSException
import live.hms.video.media.codec.HMSAudioCodec
import live.hms.video.media.codec.HMSVideoCodec
Expand All @@ -40,7 +38,6 @@ import live.hms.video.sdk.models.enums.HMSTrackUpdate
import live.hms.video.sdk.models.role.HMSRole
import live.hms.video.sdk.models.trackchangerequest.HMSChangeTrackStateRequest
import live.hms.video.utils.HMSLogger
import java.lang.Exception


/** HmssdkFlutterPlugin */
Expand All @@ -52,13 +49,16 @@ class HmssdkFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
private lateinit var meetingEventChannel: EventChannel
private lateinit var previewChannel: EventChannel
private lateinit var logsEventChannel: EventChannel
private lateinit var rtcStatsChannel: EventChannel
private var eventSink: EventChannel.EventSink? = null
private var previewSink: EventChannel.EventSink? = null
private var logsSink: EventChannel.EventSink? = null
private var rtcSink: EventChannel.EventSink? = null
private lateinit var activity: Activity
lateinit var hmssdk: HMSSDK
private lateinit var hmsVideoFactory: HMSVideoViewFactory
private var requestChange: HMSRoleChangeRequest? = null
private var isStatsActive: Boolean = false

companion object {
var hmssdkFlutterPlugin: HmssdkFlutterPlugin? = null
Expand All @@ -74,13 +74,14 @@ class HmssdkFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
this.logsEventChannel =
EventChannel(flutterPluginBinding.binaryMessenger, "logs_event_channel")

this.rtcStatsChannel = EventChannel(flutterPluginBinding.binaryMessenger, "rtc_event_channel")


this.meetingEventChannel.setStreamHandler(this)
this.channel.setMethodCallHandler(this)
this.previewChannel.setStreamHandler(this)
this.logsEventChannel.setStreamHandler(this)

this.rtcStatsChannel.setStreamHandler(this)
this.hmsVideoFactory = HMSVideoViewFactory(this)

flutterPluginBinding.platformViewRegistry.registerViewFactory(
Expand Down Expand Up @@ -162,6 +163,9 @@ class HmssdkFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
"get_all_tracks" -> {
getAllTracks(call, result)
}
"start_stats_listener", "remove_stats_listener" -> {
statsListenerAction(call, result)
}
else -> {
result.notImplemented()
}
Expand Down Expand Up @@ -271,11 +275,34 @@ class HmssdkFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
}
}

private var isRTCStatsListenerInit = false

private fun statsListenerAction(call: MethodCall, result: Result){
when (call.method) {
"start_stats_listener" -> {
if (!isRTCStatsListenerInit) {
hmssdk.addRtcStatsObserver(this.hmsStatsListener)
isRTCStatsListenerInit = true
}
isStatsActive = true
}

"remove_stats_listener" -> {
isStatsActive = false
}

else -> {
result.notImplemented()
}
}
}

override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
meetingEventChannel.setStreamHandler(null)
previewChannel.setStreamHandler(null)
logsEventChannel.setStreamHandler(null)
rtcStatsChannel.setStreamHandler(null)
hmssdkFlutterPlugin = null
}

Expand Down Expand Up @@ -368,6 +395,8 @@ class HmssdkFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
this.previewSink = events
} else if (nameOfEventSink == "logs") {
this.logsSink = events
} else if (nameOfEventSink == "rtc_stats") {
this.rtcSink = events
}
}

Expand Down Expand Up @@ -548,7 +577,7 @@ class HmssdkFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
)
}

private fun isAllowedToEndMeeting(): Boolean {
private fun isAllowedToEndMeeting(): Boolean? {
return hmssdk.getLocalPeer()!!.hmsRole.permission?.endRoom
}

Expand Down Expand Up @@ -973,4 +1002,118 @@ class HmssdkFlutterPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
val peer: HMSPeer? = getPeerById(peerId!!)
result.success(HMSTrackExtension.toDictionary(peer?.getTrackById(trackId!!)))
}
}



private val hmsStatsListener = object : HMSStatsObserver {

override fun onRemoteVideoStats(
videoStats: HMSRemoteVideoStats,
hmsTrack: HMSTrack?,
hmsPeer: HMSPeer?
) {
if(isStatsActive) {
val args = HashMap<String, Any?>()
args["event_name"] = "on_remote_video_stats"
args["data"] = HMSRtcStatsExtension.toDictionary(
hmsRemoteVideoStats = videoStats,
peer = hmsPeer,
track = hmsTrack
)

if (args["data"] != null)
CoroutineScope(Dispatchers.Main).launch {
rtcSink?.success(args)
}
}
}

override fun onRemoteAudioStats(
audioStats: HMSRemoteAudioStats,
hmsTrack: HMSTrack?,
hmsPeer: HMSPeer?
) {
if(isStatsActive) {
val args = HashMap<String, Any?>()
args["event_name"] = "on_remote_audio_stats"
args["data"] = HMSRtcStatsExtension.toDictionary(
hmsRemoteAudioStats = audioStats,
peer = hmsPeer,
track = hmsTrack
)


if (args["data"] != null)
CoroutineScope(Dispatchers.Main).launch {
rtcSink?.success(args)
}
}
}

override fun onLocalVideoStats(
videoStats: HMSLocalVideoStats,
hmsTrack: HMSTrack?,
hmsPeer: HMSPeer?
) {
if(isStatsActive) {
val args = HashMap<String, Any?>()
args["event_name"] = "on_local_video_stats"
args["data"] = HMSRtcStatsExtension.toDictionary(
hmsLocalVideoStats = videoStats,
peer = getLocalPeer(),
track = hmsTrack
)


if (args["data"] != null)
CoroutineScope(Dispatchers.Main).launch {
rtcSink?.success(args)
}
}
}

override fun onLocalAudioStats(
audioStats: HMSLocalAudioStats,
hmsTrack: HMSTrack?,
hmsPeer: HMSPeer?
) {
if(isStatsActive) {
val args = HashMap<String, Any?>()
args["event_name"] = "on_local_audio_stats"
args["data"] = HMSRtcStatsExtension.toDictionary(
hmsLocalAudioStats = audioStats,
peer = getLocalPeer(),
track = hmsTrack
)

if (args["data"] != null)
CoroutineScope(Dispatchers.Main).launch {
rtcSink?.success(args)
}
}
}

override fun onRTCStats(rtcStats: HMSRTCStatsReport) {
if(isStatsActive) {
val args = HashMap<String, Any?>()
args["event_name"] = "on_rtc_stats"
val dict = HashMap<String, Any?>()
dict["bytes_sent"] = rtcStats.combined.bytesSent
dict["bytes_received"] = rtcStats.combined.bitrateReceived
dict["bitrate_sent"] = rtcStats.combined.bitrateSent
dict["packets_received"] = rtcStats.combined.packetsReceived
dict["packets_lost"] = rtcStats.combined.packetsLost
dict["bitrate_received"] = rtcStats.combined.bitrateReceived
dict["round_trip_time"] = rtcStats.combined.roundTripTime

args["data"] = dict
if (args["data"] != null)
CoroutineScope(Dispatchers.Main).launch {
rtcSink?.success(args)
}
}
}

}

}
Loading

0 comments on commit 37a36b9

Please sign in to comment.