diff --git a/Plugin/VS/GStreamerUnityPlugin.vcxproj b/Plugin/VS/GStreamerUnityPlugin.vcxproj
index 095bc27e..71a3c63b 100644
--- a/Plugin/VS/GStreamerUnityPlugin.vcxproj
+++ b/Plugin/VS/GStreamerUnityPlugin.vcxproj
@@ -28,26 +28,26 @@
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
true
- v142
+ v143
MultiByte
DynamicLibrary
false
- v142
+ v143
true
Unicode
DynamicLibrary
false
- v142
+ v143
true
MultiByte
@@ -129,7 +129,7 @@
Level3
Disabled
- USE_UNITY_GRABBER;USE_UNITY_NETWORK;WIN32;_DEBUG;_WINDOWS;_USRDLL;GSTREAMERUNITYPLUGIN_EXPORTS;%(PreprocessorDefinitions)
+ USE_UNITY_GRABBER;WIN32;_DEBUG;_WINDOWS;_USRDLL;GSTREAMERUNITYPLUGIN_EXPORTS;%(PreprocessorDefinitions)
./;../includes;../includes/Win32;../sources;%(AdditionalIncludeDirectories)
@@ -163,7 +163,7 @@
MaxSpeed
- USE_UNITY_GRABBER;__USE_UNITY_NETWORK;WIN32;NDEBUG;_WINDOWS;_USRDLL;GSTREAMERUNITYPLUGIN_EXPORTS;%(PreprocessorDefinitions)
+ USE_UNITY_GRABBER;WIN32;NDEBUG;_WINDOWS;_USRDLL;GSTREAMERUNITYPLUGIN_EXPORTS;%(PreprocessorDefinitions)
./;../includes;../includes/Win32;../sources;%(AdditionalIncludeDirectories)
@@ -225,12 +225,27 @@
true
-
-
-
+
+ false
+ false
+
+
+ true
+ true
+
+
+ true
+ true
+
-
-
+
+ true
+ true
+
+
+ true
+ true
+
@@ -239,7 +254,10 @@
-
+
+ true
+ true
+
@@ -280,14 +298,29 @@
-
-
-
+
+ false
+ false
+
+
+ true
+ true
+
+
+ true
+ true
+
Disabled
-
-
+
+ true
+ true
+
+
+ true
+ true
+
Disabled
@@ -309,7 +342,10 @@
Disabled
-
+
+ true
+ true
+
diff --git a/Plugin/sources/GstCustomVideoStreamer.cpp b/Plugin/sources/GstCustomVideoStreamer.cpp
index 6f039846..8691ef1f 100644
--- a/Plugin/sources/GstCustomVideoStreamer.cpp
+++ b/Plugin/sources/GstCustomVideoStreamer.cpp
@@ -23,6 +23,8 @@ class GstCustomVideoStreamerImpl : public GstPipelineHandler,
std::string m_pipeLineString;
std::string m_srcPipeLineString;
+ ConnectionStatusCallback m_connectionStatusCallback = nullptr;
+
int m_fps;
Vector2d m_frameSize;
@@ -60,6 +62,11 @@ class GstCustomVideoStreamerImpl : public GstPipelineHandler,
m_fps = fps;
}
+ void SetConnectionStatusCallback(ConnectionStatusCallback cb)
+ {
+ m_connectionStatusCallback = cb;
+ }
+
std::string GetFormatStr(EPixelFormat fmt) {
std::string format = "RGB";
switch (fmt) {
@@ -313,6 +320,38 @@ class GstCustomVideoStreamerImpl : public GstPipelineHandler,
virtual void OnPipelineStopped(GstPipelineHandler* p) {
m_owner->__FIRE_OnStreamerStopped(m_owner);
}
+ virtual void OnPipelineError(GstPipelineHandler* p, const std::string& elementName)
+ {
+ if (m_connectionStatusCallback && elementName.find("rtspclientsink") != std::string::npos)
+ {
+ m_connectionStatusCallback(false);
+ }
+ }
+ virtual void OnPipelineProgress(GstPipelineHandler* p, int progressType, const std::string& code, const std::string& info) override
+ {
+ if(!m_connectionStatusCallback)
+ {
+ return;
+ }
+
+ switch (progressType)
+ {
+ case 2: // GST_PROGRESS_TYPE_COMPLETE
+ if (code.find("open") != std::string::npos)
+ {
+ m_connectionStatusCallback(true);
+ }
+ break;
+ case 4: // GST_PROGRESS_TYPE_ERROR
+ if (code.find("open") != std::string::npos)
+ {
+ m_connectionStatusCallback(false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
};
GstCustomVideoStreamer::GstCustomVideoStreamer() {
@@ -336,6 +375,11 @@ void GstCustomVideoStreamer::SetResolution(int width, int height, int fps) {
m_impl->SetResolution(width, height, fps);
}
+void GstCustomVideoStreamer::SetConnectionStatusCallback(ConnectionStatusCallback cb)
+{
+ m_impl->SetConnectionStatusCallback(cb);
+}
+
void GstCustomVideoStreamer::SetVideoGrabber(IVideoGrabber* grabber0) {
m_impl->SetVideoGrabber(grabber0);
}
diff --git a/Plugin/sources/GstCustomVideoStreamer.h b/Plugin/sources/GstCustomVideoStreamer.h
index a870cc0f..f8829679 100644
--- a/Plugin/sources/GstCustomVideoStreamer.h
+++ b/Plugin/sources/GstCustomVideoStreamer.h
@@ -20,6 +20,7 @@ author: MHD Yamen Saraiji
#define GstCustomVideoStreamer_h__
#include "IGStreamerStreamer.h"
+#include "Unity/IUnityInterface.h"
#include
namespace mray
@@ -30,6 +31,12 @@ namespace video
class GstCustomVideoStreamerImpl;
class IVideoGrabber;
+// Uggly fix to expose the ConnectionStatusCallback signature where relevant.
+extern "C"
+{
+ typedef void(UNITY_INTERFACE_API* ConnectionStatusCallback)(bool);
+}
+
class GstCustomVideoStreamer :public IGStreamerStreamer
{
protected:
@@ -50,7 +57,8 @@ class GstCustomVideoStreamer :public IGStreamerStreamer
virtual void Close();
void SetVideoGrabber(IVideoGrabber* grabber0);
- void SetResolution(int width, int height, int fps);
+ void SetResolution(int width, int height, int fps);
+ void SetConnectionStatusCallback(ConnectionStatusCallback cb);
virtual void SetPaused(bool paused);
virtual bool IsPaused();
diff --git a/Plugin/sources/GstPipelineHandler.cpp b/Plugin/sources/GstPipelineHandler.cpp
index 8125e711..527959a1 100644
--- a/Plugin/sources/GstPipelineHandler.cpp
+++ b/Plugin/sources/GstPipelineHandler.cpp
@@ -5,6 +5,7 @@
#include
#include
+#include
#include "GStreamerCore.h"
#include "IThreadManager.h"
@@ -368,9 +369,16 @@ long GstPipelineHandler::GetDuration() {
}
bool GstPipelineHandler::IsResettingEOS() { return m_data->_restartingEOS; }
void GstPipelineHandler::SetPaused(bool p) {
+ if (m_data->gstPipeline == NULL && m_data->busWatchID == 0)
+ {
+ m_data->paused = true;
+ m_data->Loaded = false;
+ m_data->playing = false;
+ return;
+ }
std::lock_guard lock(GetMutex());
m_data->paused = p;
- if (m_data->Loaded || true) {
+ if (m_data->Loaded) {
if (m_data->playing) {
GstState state;
if (m_data->paused) {
@@ -405,9 +413,18 @@ void GstPipelineHandler::SetPaused(bool p) {
}
}
void GstPipelineHandler::Stop() {
+ if (m_data->gstPipeline == NULL && m_data->busWatchID == 0)
+ {
+ m_data->paused = true;
+ m_data->Loaded = false;
+ m_data->playing = false;
+ return;
+ }
+
LogMessage(m_data->_name + ": GstPipelineHandler::Stop ", ELL_INFO);
if (!m_data->Loaded) return;
std::lock_guard lock(GetMutex());
+ if (m_data->paused == true && m_data->playing == false) return;
GstState state;
m_data->_seekPos = GST_CLOCK_TIME_NONE;
// gst_element_send_event(m_data->gstPipeline, gst_event_new_eos());
@@ -444,11 +461,16 @@ bool GstPipelineHandler::QueryLatency(bool &isLive, ulong &minLatency,
return ok;
}
void GstPipelineHandler::Close() {
+ if (m_data->gstPipeline == NULL && m_data->busWatchID == 0)
+ {
+ m_data->Loaded = false;
+ return;
+ }
LogMessage(m_data->_name + ": GstPipelineHandler::Close ", ELL_INFO);
std::lock_guard lock(GetMutex());
Stop();
- if (true || m_data->Loaded) {
+ if (m_data->Loaded) {
if (m_data->busWatchID != 0) g_source_remove(m_data->busWatchID);
m_data->busWatchID = 0;
@@ -607,27 +629,30 @@ bool GstPipelineHandler::HandleMessage(GstBus *bus, GstMessage *msg) {
case GST_MESSAGE_PROGRESS: {
GstProgressType type;
gchar *code, *text;
- bool in_progress = false;
gst_message_parse_progress(msg, &type, &code, &text);
switch (type) {
case GST_PROGRESS_TYPE_START:
case GST_PROGRESS_TYPE_CONTINUE:
- in_progress = TRUE;
- break;
case GST_PROGRESS_TYPE_COMPLETE:
case GST_PROGRESS_TYPE_CANCELED:
case GST_PROGRESS_TYPE_ERROR:
- in_progress = FALSE;
+ {
+ const std::string progressCode(code);
+ const std::string progressInfo(text);
+ FIRE_LISTENR_METHOD(OnPipelineProgress, (this, type, progressCode, progressInfo));
+ }
break;
default:
break;
}
- LogMessage("Progress: (" + std::string(code) + ") " + std::string(text),
- ELL_INFO);
+ LogMessage("Progress: (" + std::to_string(type) + ") ("
+ + std::string(code) + ") " + std::string(text),
+ ELL_INFO);
g_free(code);
g_free(text);
- } break;
+ }
+ break;
case GST_MESSAGE_WARNING: {
GError *err;
@@ -668,15 +693,16 @@ bool GstPipelineHandler::HandleMessage(GstBus *bus, GstMessage *msg) {
std::string(" - ") + debug,
ELL_WARNING);
+
+ const std::string gstElementName(name);
+ if (m_data) {
+ FIRE_LISTENR_METHOD(OnPipelineError, (this, gstElementName));
+ }
+
g_free(name);
g_error_free(err);
g_free(debug);
- if (m_data) {
- FIRE_LISTENR_METHOD(OnPipelineError, (this));
- // gst_element_set_state(GST_ELEMENT(m_data->gstPipeline),
- // GST_STATE_NULL);
- }
} break;
default:
diff --git a/Plugin/sources/GstPipelineHandler.h b/Plugin/sources/GstPipelineHandler.h
index cad5ff78..765e1fa8 100644
--- a/Plugin/sources/GstPipelineHandler.h
+++ b/Plugin/sources/GstPipelineHandler.h
@@ -25,7 +25,7 @@ class IPipelineListener {
virtual void OnPipelineStopped(GstPipelineHandler* p) {}
virtual void OnPipelineClosed(GstPipelineHandler* p) {}
virtual void OnPipelineWarning(GstPipelineHandler* p) {}
- virtual void OnPipelineError(GstPipelineHandler* p) {}
+ virtual void OnPipelineError(GstPipelineHandler* p, const std::string& elementName) {}
virtual void OnPipelineEOS(GstPipelineHandler* p) {}
virtual void OnPipelineBuffering(GstPipelineHandler* p, int percent) {}
@@ -34,6 +34,7 @@ class IPipelineListener {
virtual void OnPreSeek(GstPipelineHandler* p, long pos) {}
virtual void OnPostSeek(GstPipelineHandler* p) {}
+ virtual void OnPipelineProgress(GstPipelineHandler* p, int progressType, const std::string& code, const std::string& info) {}
};
class GstPipelineHandler : public ListenerContainer {
@@ -48,7 +49,7 @@ class GstPipelineHandler : public ListenerContainer {
DECLARE_FIRE_METHOD(OnPipelineStopped, (GstPipelineHandler * p), (p));
DECLARE_FIRE_METHOD(OnPipelineClosed, (GstPipelineHandler * p), (p));
DECLARE_FIRE_METHOD(OnPipelineWarning, (GstPipelineHandler * p), (p));
- DECLARE_FIRE_METHOD(OnPipelineError, (GstPipelineHandler * p), (p));
+ DECLARE_FIRE_METHOD(OnPipelineError, (GstPipelineHandler * p, const std::string& elementName), (p, elementName));
DECLARE_FIRE_METHOD(OnPipelineEOS, (GstPipelineHandler * p), (p));
DECLARE_FIRE_METHOD(OnPreSeek, (GstPipelineHandler * p, long pos), (p, pos));
DECLARE_FIRE_METHOD(OnPostSeek, (GstPipelineHandler * p), (p));
@@ -58,6 +59,7 @@ class GstPipelineHandler : public ListenerContainer {
(p, prevState, newState, pendState));
DECLARE_FIRE_METHOD(OnPipelineBuffering,
(GstPipelineHandler * p, int percent), (p, percent));
+ DECLARE_FIRE_METHOD(OnPipelineProgress, (GstPipelineHandler* p, int progressType, const std::string& code, const std::string& info), (p, progressType, code, info));
public:
GstPipelineHandler(const char* name = "");
diff --git a/Plugin/sources/StreamersAPI.cpp b/Plugin/sources/StreamersAPI.cpp
index ff6e264d..58da9207 100644
--- a/Plugin/sources/StreamersAPI.cpp
+++ b/Plugin/sources/StreamersAPI.cpp
@@ -149,6 +149,17 @@ extern "C" UNITY_INTERFACE_EXPORT void mray_gst_customImageStreamerSetResolution
}
}
+extern "C"
+{
+ UNITY_INTERFACE_EXPORT void mray_gst_customImageStreamerSetConnectionStatusCallback(GstCustomVideoStreamer* p, ConnectionStatusCallback cb)
+ {
+ if (p)
+ {
+ p->SetConnectionStatusCallback(cb);
+ }
+ }
+}
+
#ifdef USE_UNITY_NETWORK
extern "C" UNITY_INTERFACE_EXPORT void *mray_gst_createNetworkStreamer()
diff --git a/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstCustomVideoStreamer.cs b/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstCustomVideoStreamer.cs
index 1936ce50..cd634341 100644
--- a/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstCustomVideoStreamer.cs
+++ b/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstCustomVideoStreamer.cs
@@ -2,6 +2,8 @@
using System.Collections;
using System.Runtime.InteropServices;
+namespace GStreamerUnity{
+
public class GstCustomVideoStreamer:IGstStreamer {
@@ -17,6 +19,15 @@ public class GstCustomVideoStreamer:IGstStreamer {
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
extern static private int mray_gst_customImageStreamerSetResolution(System.IntPtr p,int width, int height, int fps);
+
+ public delegate void ConnectionStatusCallback(bool isConnected);
+
+ [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
+ extern static internal void
+ mray_gst_customImageStreamerSetConnectionStatusCallback(
+ System.IntPtr p,
+ [MarshalAs(UnmanagedType.FunctionPtr)] ConnectionStatusCallback callbackPointer);
+
GstUnityImageGrabber _grabber;
public GstCustomVideoStreamer()
@@ -44,4 +55,11 @@ public void SetResolution(int w,int h,int fps)
{
mray_gst_customImageStreamerSetResolution (m_Instance, w,h,fps);
}
+
+ public void SetCallback(ConnectionStatusCallback cb)
+ {
+ mray_gst_customImageStreamerSetConnectionStatusCallback(m_Instance, cb);
+ }
+}
+
}
diff --git a/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstUnityImageGrabber.cs b/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstUnityImageGrabber.cs
index 810f9874..2bfd4d31 100644
--- a/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstUnityImageGrabber.cs
+++ b/Unity/UnityTests/Assets/GStreamerUnity/Scripts/GstUnityImageGrabber.cs
@@ -3,6 +3,8 @@
using System.Runtime.InteropServices;
using System;
+namespace GStreamerUnity{
+
public class GstUnityImageGrabber {
enum EPixelFormat
@@ -141,3 +143,5 @@ public void Update()
mray_gst_UnityImageGrabberSetData (m_Instance, m_lastArrayPtr, m_width,m_height, (int)m_format);
}
}
+
+}
\ No newline at end of file
diff --git a/Unity/UnityTests/Assets/GStreamerUnity/Scripts/IGstStreamer.cs b/Unity/UnityTests/Assets/GStreamerUnity/Scripts/IGstStreamer.cs
index fb1cf6e5..6335448c 100644
--- a/Unity/UnityTests/Assets/GStreamerUnity/Scripts/IGstStreamer.cs
+++ b/Unity/UnityTests/Assets/GStreamerUnity/Scripts/IGstStreamer.cs
@@ -2,6 +2,9 @@
using System.Collections;
using System.Runtime.InteropServices;
+
+namespace GStreamerUnity{
+
public class IGstStreamer : MonoBehaviour {
internal const string DllName = "GStreamerUnityPlugin";
@@ -81,3 +84,5 @@ public void Close()
mray_gst_StreamerClose (m_Instance);
}
}
+
+}
\ No newline at end of file