Skip to content

Commit

Permalink
Merge pull request #8 from AgoraIO-Extensions/dev/m2.1.0_a4.3.0
Browse files Browse the repository at this point in the history
Dev/m2.1.0 a4.3.0
  • Loading branch information
icywind authored Apr 24, 2024
2 parents b7d0109 + 7fd38a7 commit b2a1a7d
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 72 deletions.
67 changes: 45 additions & 22 deletions AgoraEngine/ML2Support/Demo/AgoraMLDemo.unity
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.18064547, g: 0.22614636, b: 0.30711892, a: 1}
m_IndirectSpecularColor: {r: 0.18060996, g: 0.22608182, b: 0.30708373, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
Expand Down Expand Up @@ -437,12 +437,6 @@ GameObject:
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!82 &313531297 stripped
AudioSource:
m_CorrespondingSourceObject: {fileID: 2728559731536843762, guid: 7fe6e185edeea4434a1421a08226a74a,
type: 3}
m_PrefabInstance: {fileID: 8026431351379875335}
m_PrefabAsset: {fileID: 0}
--- !u!114 &313531299
MonoBehaviour:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -1254,6 +1248,11 @@ PrefabInstance:
propertyPath: m_AnchoredPosition.y
value: 0.00015258789
objectReference: {fileID: 0}
- target: {fileID: 9144045080929779760, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9144045080993300992, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_AnchorMax.y
Expand Down Expand Up @@ -1289,6 +1288,36 @@ PrefabInstance:
propertyPath: m_Text
value: This is simple Hello World example.
objectReference: {fileID: 0}
- target: {fileID: 9144045081349396370, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9144045081349396370, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9144045081349396370, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9144045081349396370, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9144045081349396370, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9144045081349396370, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9144045081354614237, guid: 6906f74934047d24e9a47bbdd1afb57a,
type: 3}
propertyPath: m_AnchorMax.y
Expand Down Expand Up @@ -1625,18 +1654,6 @@ RectTransform:
m_AnchoredPosition: {x: 207, y: -145}
m_SizeDelta: {x: 160, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2123939088 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 1512593271744470006, guid: 7fe6e185edeea4434a1421a08226a74a,
type: 3}
m_PrefabInstance: {fileID: 8026431351379875335}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ff2dfae1cb3824047a647bd2af2c78cf, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &8026431351379875335
PrefabInstance:
m_ObjectHideFlags: 0
Expand All @@ -1654,7 +1671,7 @@ PrefabInstance:
type: 3}
propertyPath: InputAudioSource
value:
objectReference: {fileID: 313531297}
objectReference: {fileID: 0}
- target: {fileID: 2277068096631128598, guid: 7fe6e185edeea4434a1421a08226a74a,
type: 3}
propertyPath: APP_ID
Expand Down Expand Up @@ -1775,6 +1792,11 @@ PrefabInstance:
propertyPath: m_audioClip
value:
objectReference: {fileID: 8300000, guid: ab0b3756ed665478ca7731aff7220062, type: 3}
- target: {fileID: 4639081902220624982, guid: 7fe6e185edeea4434a1421a08226a74a,
type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8615111217482490128, guid: 7fe6e185edeea4434a1421a08226a74a,
type: 3}
propertyPath: TOKEN
Expand Down Expand Up @@ -1824,15 +1846,16 @@ PrefabInstance:
type: 3}
propertyPath: CustomAudioCapture
value:
objectReference: {fileID: 2123939088}
objectReference: {fileID: 0}
- target: {fileID: 8615111217482490128, guid: 7fe6e185edeea4434a1421a08226a74a,
type: 3}
propertyPath: ReferenceTransform
value:
objectReference: {fileID: 1118466283}
m_RemovedComponents:
- {fileID: 2277068096631128598, guid: 7fe6e185edeea4434a1421a08226a74a, type: 3}
m_RemovedGameObjects: []
m_RemovedGameObjects:
- {fileID: 4639081902220624982, guid: 7fe6e185edeea4434a1421a08226a74a, type: 3}
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 7fe6e185edeea4434a1421a08226a74a, type: 3}
Expand Down
62 changes: 29 additions & 33 deletions AgoraEngine/ML2Support/Scripts/AgoraController.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using UnityEngine;
using UnityEngine.UI;
using Agora.Rtc;
using Agora.Util;
using Agora_RTC_Plugin.API_Example;
using Logger = Agora_RTC_Plugin.API_Example.Logger;
using Agora_RTC_Plugin.API_Example;

namespace Agora.Rtc.Extended
{
Expand Down Expand Up @@ -49,8 +48,8 @@ public class AgoraController : MonoBehaviour
[Header("Audio Control")]
[SerializeField]
IAudioRenderManager CustomAudioSink;
[SerializeField]
IAudioCaptureManager CustomAudioCapture;

internal uint AUDIO_TRACK_ID = 0;

internal Logger _logger;
private IRtcEngine _rtcEngine = null;
Expand All @@ -77,10 +76,18 @@ private void Start()
// Assume automatically joining the agora channel
if (appReady)
{
InitEngine(JoinChannel);
InitEngine();
PrepareJoinChannel(callback: JoinChannel);
}
}

// Update is called once per frame
private void Update()
{
PermissionHelper.RequestMicrophontPermission();
PermissionHelper.RequestCameraPermission();
}

// Simple check for APP ID input in case it is forgotten
bool CheckAppId()
{
Expand All @@ -94,43 +101,42 @@ bool CheckAppId()
}

// Initialize Agora Game Engine
void InitEngine(System.Action callback)
void InitEngine()
{

_rtcEngine = RtcEngine.CreateAgoraRtcEngine();
UserEventHandler handler = new UserEventHandler(this);
RtcEngineContext context = new RtcEngineContext(
appId: APP_ID,
context: 0,
channelProfile: CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING,
audioScenario: AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_DEFAULT,
areaCode: AREA_CODE.AREA_CODE_GLOB
);
RtcEngineContext context = new RtcEngineContext()
{
appId = APP_ID,
channelProfile = CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING,
audioScenario = AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_GAME_STREAMING,
areaCode = AREA_CODE.AREA_CODE_GLOB
};
var rc = _rtcEngine.Initialize(context);
Debug.Assert(rc == 0, "rtcEngine init failed");
rc = _rtcEngine.InitEventHandler(handler);
Debug.Assert(rc == 0, "rtcEngine init handler failed");

_rtcEngine.EnableAudio();
_rtcEngine.SetExternalAudioSource(true, CustomAudioCapturer.SAMPLE_RATE, CustomAudioCapturer.CHANNEL);

_rtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
_rtcEngine.SetAudioProfile(AUDIO_PROFILE_TYPE.AUDIO_PROFILE_DEFAULT, AUDIO_SCENARIO_TYPE.AUDIO_SCENARIO_GAME_STREAMING);

_rtcEngine.EnableVideo();

_rtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);

_rtcEngine.SetLogLevel(LogLevel);
_rtcEngine.SetLogFile(Application.persistentDataPath + "/log.txt");

CustomVideoCapture?.Init(_rtcEngine, RtcLock);
CustomAudioSink?.Init(_rtcEngine, RtcLock);
CustomAudioCapture?.Init(_rtcEngine, RtcLock);
}

// If AppID is certifcate enabled, use token.
void PrepareJoinChannel(System.Action callback)
{
// If AppID is certifcate enabled, use token.
if (UseTokenClient)
{
TokenClient.Instance.SetClient(
CLIENT_ROLE == CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER ? ClientType.publisher : ClientType.subscriber);
CLIENT_ROLE == CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER ? ClientType.publisher : ClientType.subscriber);

TokenClient.Instance.GetRtcToken(CHANNEL_NAME, _clientUID, (token) =>
{
Expand All @@ -143,8 +149,8 @@ void InitEngine(System.Action callback)
{
callback();
}
}

}

// Demo UI setup, using custom ToggleStateButton class
void InitUI()
{
Expand Down Expand Up @@ -175,9 +181,7 @@ void JoinChannel()
var option = new ChannelMediaOptions();
option.autoSubscribeVideo.SetValue(true);
option.autoSubscribeAudio.SetValue(true);
option.publishMicrophoneTrack.SetValue(false);
option.publishCameraTrack.SetValue(false);
option.publishCustomAudioTrack.SetValue(true);
option.publishCustomVideoTrack.SetValue(true);
option.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
option.channelProfile.SetValue(CHANNEL_PROFILE_TYPE.CHANNEL_PROFILE_LIVE_BROADCASTING);
Expand All @@ -186,12 +190,6 @@ void JoinChannel()
}


void OnVideoSizeChanged(uint uid, int width, int height, int rotation)
{
VideoRenderMgr.UpdateVideoView(uid, width, height, rotation);
}


private void OnDestroy()
{
Debug.Log("OnDestroy: Agora Clean up");
Expand Down Expand Up @@ -227,7 +225,6 @@ public override void OnJoinChannelSuccess(RtcConnection connection, int elapsed)
_app._rtcEngine.GetVersion(ref build)));
_app._logger.UpdateLog(string.Format("OnJoinChannelSuccess channelName: {0}, uid: {1}, elapsed: {2}",
connection.channelId, connection.localUid, elapsed));
_app.CustomAudioCapture?.StartAudioPush();
}

public override void OnRejoinChannelSuccess(RtcConnection connection, int elapsed)
Expand All @@ -238,7 +235,6 @@ public override void OnRejoinChannelSuccess(RtcConnection connection, int elapse
public override void OnLeaveChannel(RtcConnection connection, RtcStats stats)
{
_app._logger.UpdateLog("OnLeaveChannel");
_app.CustomAudioCapture?.StopAudioPush();
}

public override void OnClientRoleChanged(RtcConnection connection, CLIENT_ROLE_TYPE oldRole, CLIENT_ROLE_TYPE newRole, ClientRoleOptions newRoleOptions)
Expand Down
11 changes: 4 additions & 7 deletions AgoraEngine/ML2Support/Scripts/CustomAudioCapturer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections;
using UnityEngine;
using Agora.Rtc;
using RingBuffer;

#if ML2_ENABLE
Expand Down Expand Up @@ -80,7 +78,6 @@ public override void Init(Agora.Rtc.IRtcEngine engine, object rtclock)
RawBuffer = new byte[BufferLength],
renderTimeMs = 1000 / PUSH_FREQ_PER_SEC
};
AgoraLog.Log("BufferLength = " + BufferLength);
}

private void Update()
Expand Down Expand Up @@ -208,10 +205,10 @@ private void HandleAudioBuffer(float[] data)
}

_count += 1;
//if (_count % 100 == 0)
//{
// Debug.Log($"AGORA: HandleAudioBuffer count:{_count}");
//}
if (_count % 100 == 0)
{
Debug.Log($"AGORA: HandleAudioBuffer count:{_count}");
}
}

// This method receives data from the audio source by the Unity engine
Expand Down
13 changes: 10 additions & 3 deletions AgoraEngine/ML2Support/Scripts/CustomAudioSinkPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,16 @@ private void PullAudioFrameThread()
double startMillisecond = GetTimestamp();
long tick = 0;

AudioFrame audioFrame = new AudioFrame(
type, samples, BYTES_PER_SAMPLE.TWO_BYTES_PER_SAMPLE, channels, samplesPerSec, buffer, 0, avsync_type, 0);
AudioFrame audioFrame = new AudioFrame
{
type = type,
samplesPerChannel = samples,
bytesPerSample = BYTES_PER_SAMPLE.TWO_BYTES_PER_SAMPLE,
channels = channels,
samplesPerSec = samplesPerSec,
avsync_type = avsync_type,
};

BufferPtr = Marshal.AllocHGlobal(samples * bytesPerSample * channels);
audioFrame.buffer = BufferPtr;

Expand Down Expand Up @@ -205,7 +213,6 @@ private void PullAudioFrameThread()
Thread.Sleep(sleepMillisecond);
}
}

}

if (BufferPtr != IntPtr.Zero)
Expand Down
2 changes: 0 additions & 2 deletions AgoraEngine/ML2Support/Scripts/IAudioRenderManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Agora.Rtc.Extended
{
Expand Down
2 changes: 0 additions & 2 deletions AgoraEngine/ML2Support/Scripts/IVideoCaptureManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Agora.Rtc.Extended
{
Expand Down
2 changes: 1 addition & 1 deletion AgoraEngine/Prefabs/TokenClient
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Please see Agora_MagicLeap2_Plugin/AgoraEngine/ML2Support/ML2Demo. Simply drag
### Reusable Components
For the MagicLeap2, Application that uses Agora for native RTC support must use **custom video and audio** capturing and rendering techniques respectively. The scripts under the *agora_sample* namespace are refactored components that enable low-code solution:

- **CustomAudioCapturer**: this script captures the local user's audio via Unity's Microphone interface and push the raw audio into Agora SD-RTN. This is required if the ML2 user is a broadcaster.
- **CustomAudioCapturer**: this script captures the local user's audio via Unity's Microphone interface and push the raw audio into Agora SD-RTN. This is only required if the ML2 user is a broadcaster and the MagicLeap SDK is v2.0.0 or lower.
- **CustomAudioSinkPlayer**: this script receives the remote users' audio data and play the stream on a AudioSource component. This is required.
- **CustomVideoCapturer**: this script captures the local user's camera view and send it into the Agora SD-RTN. The code utilized ML2's MLCamera capabilities to capture the raw video data from the camera. There are options to be set in the Inspector to accommodate different capturing parameters, such as resolution and XR/Camera modes. This component can be replaced with other capturing methods. Use the *ShareScreen* method in the script as an example to push raw data that is capture using other means.
- **VideoRenderManager**: this script provides basic 2D rendering for the remote users' video stream. Developer should override the virtual methods *MakeVideoView()* and *UpdateVideoView()* to accommodate different UI design.
Expand Down Expand Up @@ -49,7 +49,7 @@ The following tables explains the fields that should be filed in the Inspector.
|Mute Remote Button|A Button that enables/disables remote user's audio|No
|Custom Video Capture |The Video Capture component, see **CustomVideoCapturer.cs**|Yes
|Custom Audio Sink|The audio sink component, see **CustomAudioSinkPlayer.cs**| Yes
|Custom Audio Capture|The audio capture component, see **CustomAudioCapturer.cs**|Yes
|Custom Audio Capture|The audio capture component, see **CustomAudioCapturer.cs**|not needed after MLSDK v2.1.0

Lastly, there is a **VideoRenderManager** class that implements the view placement of user video streams. It is recommended to implement the IVideoRenderManager interface for your own applications design.

Expand All @@ -73,3 +73,4 @@ As an example a chosen endpoint is "https://agoraml2test.herokuapp.com/". Copy
## License

MIT license.

0 comments on commit b2a1a7d

Please sign in to comment.