Skip to content

Commit

Permalink
Merge pull request IntelRealSense#2810 from BlueprintReality/multicam…
Browse files Browse the repository at this point in the history
…_thread_safe_fix

Multicam in Unity lead to crash with post-processing filters (100% repro)
  • Loading branch information
matkatz authored Dec 9, 2018
2 parents 2164493 + 04dc15f commit 8a2a690
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 34 deletions.
5 changes: 4 additions & 1 deletion wrappers/csharp/Intel.RealSense/FrameSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,10 @@ public FrameSet Get(IntPtr ptr)

public void Release(FrameSet t)
{
stack.Push(t);
lock (locker)
{
stack.Push(t);
}
}
}

Expand Down
24 changes: 18 additions & 6 deletions wrappers/csharp/Intel.RealSense/Processing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,15 @@ public CustomProcessingBlock(FrameProcessorCallback cb)

static void ProcessingBlockCallback(IntPtr f, IntPtr src, IntPtr u)
{
var callback = GCHandle.FromIntPtr(u).Target as FrameProcessorCallback;
using (var frame = Frame.CreateFrame(f))
callback(frame, new FrameSource(new HandleRef(frame, src)));
try
{
var callback = GCHandle.FromIntPtr(u).Target as FrameProcessorCallback;
using (var frame = Frame.CreateFrame(f))
callback(frame, new FrameSource(new HandleRef(frame, src)));
}
// ArgumentException: GCHandle value belongs to a different domain
// Happens when Unity Editor stop the scene with multiple devices streaming with multiple post-processing filters.
catch (ArgumentException) { }
}

public void ProcessFrame(Frame f)
Expand Down Expand Up @@ -447,9 +453,15 @@ public void Start(FrameCallback cb)
readonly frame_callback m_frameCallback = new frame_callback(ProcessingBlockFrameCallback);
static void ProcessingBlockFrameCallback(IntPtr f, IntPtr u)
{
var callback = GCHandle.FromIntPtr(u).Target as FrameCallback;
using (var frame = Frame.CreateFrame(f))
callback(frame);
try
{
var callback = GCHandle.FromIntPtr(u).Target as FrameCallback;
using (var frame = Frame.CreateFrame(f))
callback(frame);
}
// ArgumentException: GCHandle value belongs to a different domain
// Happens when Unity Editor stop the scene with multiple devices streaming with multiple post-processing filters.
catch (ArgumentException) { }
}

private GCHandle frameCallbackHandle;
Expand Down
73 changes: 46 additions & 27 deletions wrappers/unity/Assets/RealSenseSDK2.0/Scripts/RsProcessingPipe.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Intel.RealSense;
using Intel.RealSense;
using System;
using System.Collections;
using System.Collections.Generic;
Expand All @@ -17,7 +17,6 @@ public ProcessingBlockDataAttribute(Type blockClass)
{
this.blockClass = blockClass;
}

}


Expand All @@ -30,6 +29,7 @@ public class RsProcessingPipe : RsFrameProvider
public override event Action OnStop;
public override event Action<Frame> OnNewSample;
private CustomProcessingBlock _block;
private object _locker = new object();

void Awake()
{
Expand All @@ -52,12 +52,17 @@ private void OnSourceStart(PipelineProfile activeProfile)

private void OnSourceStop()
{
if (_block != null)
Source.OnNewSample -= _block.ProcessFrame;
Streaming = false;
var h = OnStop;
if (h != null)
h();
lock (_locker)
{
if (!Streaming)
return;
if (_block != null)
Source.OnNewSample -= _block.ProcessFrame;
Streaming = false;
var h = OnStop;
if (h != null)
h();
}
}

private void OnFrame(Frame f)
Expand All @@ -69,41 +74,55 @@ private void OnFrame(Frame f)

private void OnDestroy()
{
if (_block != null)
lock (_locker)
{
_block.Dispose();
_block = null;
OnSourceStop();
if (_block != null)
{
_block.Dispose();
_block = null;
}
}
}

internal void ProcessFrame(Frame frame, FrameSource src)
{
try
{
Frame f = frame;

if (profile != null)
lock (_locker)
{
var filters = profile.ToArray();
// foreach (var pb in profile)
foreach (var pb in filters)
if (!Streaming)
return;

Frame f = frame;

if (profile != null)
{
if (pb == null || !pb.Enabled)
continue;
var filters = profile.ToArray();

var r = pb.Process(f, src);
if (r != f)
foreach (var pb in filters)
{
f.Dispose();
f = r;
if (pb == null || !pb.Enabled)
continue;

var r = pb.Process(f, src);
if (r != f)
{
// Prevent from disposing the original frame during post-processing
if (f != frame)
{
f.Dispose();
}
f = r;
}
}
}
}

src.FrameReady(f);
src.FrameReady(f);

if (f != frame)
f.Dispose();
if (f != frame)
f.Dispose();
}
}
catch (Exception e)
{
Expand Down

0 comments on commit 8a2a690

Please sign in to comment.