Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Obbay2 committed May 20, 2019
2 parents 382fbe8 + 288fb5f commit a362de7
Show file tree
Hide file tree
Showing 36 changed files with 881 additions and 52 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ packages
.vs/
*.csproj.user
*.suo
*.pdb
*.pdb

*.o
18 changes: 12 additions & 6 deletions BaseStation/EntryPoint/EntryPoint.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
<HintPath>..\packages\HuskyRobotics.Scarlet.0.5.1\lib\BBBCSIO.dll</HintPath>
</Reference>
<Reference Include="PresentationFramework" />
<Reference Include="SharpDX.DirectInput, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>..\packages\SharpDX.DirectInput.4.2.0\lib\net45\SharpDX.DirectInput.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Half, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\HuskyRobotics.Scarlet.0.5.1\lib\System.Half.dll</HintPath>
Expand Down Expand Up @@ -117,12 +120,15 @@
<Content Include="huskyrobotics.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild"> <!-- Custom build tasks -->
<Target Name="AfterBuild">
<!-- Custom build tasks -->
<ItemGroup>
<IconFiles Include="$(SolutionDir)\UserInterface\Icons\*.*"/>
<LibraryBinaries Include="$(SolutionDir)\libraries\**\*.*"/>
</ItemGroup>
<Copy SkipUnchangedFiles="true" SourceFiles="@(IconFiles)" DestinationFolder="$(OutputPath)\Icons" /> <!-- Copy the map icons -->
<Copy SkipUnchangedFiles="true" SourceFiles="@(LibraryBinaries)" DestinationFolder="$(OutputPath)" /> <!-- Copy library binaries -->
<IconFiles Include="$(SolutionDir)\UserInterface\Icons\*.*" />
<LibraryBinaries Include="$(SolutionDir)\libraries\**\*.*" />
</ItemGroup>
<Copy SkipUnchangedFiles="true" SourceFiles="@(IconFiles)" DestinationFolder="$(OutputPath)\Icons" />
<!-- Copy the map icons -->
<Copy SkipUnchangedFiles="true" SourceFiles="@(LibraryBinaries)" DestinationFolder="$(OutputPath)" />
<!-- Copy library binaries -->
</Target>
</Project>
1 change: 1 addition & 0 deletions BaseStation/EntryPoint/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<packages>
<package id="HuskyRobotics.Scarlet" version="0.5.1" targetFramework="net47" />
<package id="SharpDX" version="4.2.0" targetFramework="net47" />
<package id="SharpDX.DirectInput" version="4.2.0" targetFramework="net47" />
<package id="SharpDX.XInput" version="4.2.0" targetFramework="net47" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net47" />
</packages>
16 changes: 8 additions & 8 deletions BaseStation/UserInterface/Elements/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ private void LaunchStream(object sender, RoutedEventArgs e)
private void ThreadStartingPoint(int Port, string Name, int BufferingMs)
{
VideoWindow tempWindow;
if (Name != "192.168.0.42" && Name != "127.0.0.1")
{
tempWindow = new RTPVideoWindow(Port, Name, Settings.RecordingPath, BufferingMs);
}
else
{
tempWindow = new RTSPVideoWindow(Port, Name, Settings.RecordingPath, BufferingMs);
}
//if (Name != "192.168.0.42" && Name != "127.0.0.1")
//{
// tempWindow = new RTPVideoWindow(Port, Name, Settings.RecordingPath, BufferingMs);
//}
//else
//{
tempWindow = new RTSPVideoWindow(Port, Name, Settings.RecordingPath, BufferingMs);
//}

VideoWindows.Add(tempWindow);

Expand Down
111 changes: 76 additions & 35 deletions BaseStation/UserInterface/VideoStreamer/RTSPVideoWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace HuskyRobotics.UI.VideoStreamer
{
Expand All @@ -26,12 +22,13 @@ namespace HuskyRobotics.UI.VideoStreamer
// gst-launch-1.0 rtspsrc -v location = rtsp://192.168.0.42 user-id=admin user-pw=1234 latency=0 ! rtpjpegdepay ! jpegdec ! d3dvideosink
public partial class RTSPVideoWindow : Window, VideoWindow
{
private Pipeline Pipeline;
public PipelineElements runningPipeline;
public PipelineElements pendingPipeline;

private Bin RTSP = (Bin) ElementFactory.Make("rtspsrc");
private Element Depay = ElementFactory.Make("rtpjpegdepay");
private Element Dec = ElementFactory.Make("jpegdec");
private Element VideoSink = ElementFactory.Make("d3dvideosink");
NetworkInterface networkInterface;

double bytesRecvSpeed = 0;
long lastBytesRecv;

private int Port;
private int BufferSizeMs;
Expand All @@ -48,6 +45,15 @@ public string StreamName
}
}

public struct PipelineElements
{
public Pipeline pipeline;
public VideoOverlayAdapter overlay;
public Bin RTSP;
public Element Depay;
public Element VideoSink;
}

public RTSPVideoWindow(int Port, string StreamName, string RecordingPath, int BufferSizeMs = 200)
{
DataContext = this;
Expand All @@ -56,38 +62,64 @@ public RTSPVideoWindow(int Port, string StreamName, string RecordingPath, int Bu
this.BufferSizeMs = BufferSizeMs;
this.RecordingPath = RecordingPath;

Pipeline = new Pipeline();
foreach (NetworkInterface currentNetworkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
Console.WriteLine(currentNetworkInterface.Description);
if (currentNetworkInterface.Description == "Realtek USB GbE Family Controller") {
networkInterface = currentNetworkInterface;
}
}

IPv4InterfaceStatistics interfaceStatistic = networkInterface.GetIPv4Statistics();
lastBytesRecv = interfaceStatistic.BytesReceived;
DispatcherTimer dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(GetNetworkInBackground);
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();

PipelineElements pipeline = CreatePipeline();
// Clean up running pipeline
runningPipeline = pipeline;
pendingPipeline = new PipelineElements();

Closing += OnCloseEvent;
InitializeComponent();
}

private PipelineElements CreatePipeline()
{
PipelineElements pipe = new PipelineElements();
pendingPipeline = pipe;

pipe.pipeline = new Pipeline();
pipe.RTSP = (Bin)ElementFactory.Make("rtspsrc");
pipe.Depay = ElementFactory.Make("rtpvrawdepay");
pipe.VideoSink = ElementFactory.Make("d3dvideosink");

Window window = GetWindow(this);
WindowInteropHelper wih = new WindowInteropHelper(this);
wih.EnsureHandle(); // Generate Window Handle if current HWND is NULL (always occurs because background window)
VideoOverlayAdapter overlay = new VideoOverlayAdapter(VideoSink.Handle);
overlay.WindowHandle = wih.Handle;

Pipeline["message-forward"] = true;
RTSP["location"] = "rtsp://" + StreamName;
RTSP["user-id"] = "admin";
RTSP["user-pw"] = "1234";
RTSP["latency"] = BufferSizeMs;

pipe.overlay = new VideoOverlayAdapter(pipe.VideoSink.Handle);
pipe.overlay.WindowHandle = wih.Handle;

Pipeline.Add(RTSP, Depay, Dec, VideoSink);
RTSP.Link(Depay);
RTSP.PadAdded += RTSPPadAdded;
Depay.Link(Dec);
Dec.Link(VideoSink);
pipe.pipeline["message-forward"] = true;
pipe.RTSP["location"] = "rtsp://" + StreamName;
pipe.RTSP["latency"] = BufferSizeMs;

pipe.pipeline.Add(pipe.RTSP, pipe.Depay, pipe.VideoSink);
pipe.RTSP.PadAdded += RTSPPadAdded;
pipe.RTSP.Link(pipe.Depay);
pipe.Depay.Link(pipe.VideoSink);

Pipeline.SetState(State.Null);
pipe.pipeline.SetState(State.Null);

Closing += OnCloseEvent;
InitializeComponent();
return pipe;
}

// Called after pipeline state is set to playing
private void RTSPPadAdded(object o, PadAddedArgs args)
{
Pad Sink = Depay.GetStaticPad("sink");
Pad Sink = runningPipeline.Depay.GetStaticPad("sink");
args.NewPad.Link(Sink);
}

Expand All @@ -96,7 +128,7 @@ private void RTSPPadAdded(object o, PadAddedArgs args)
/// </summary>
public void StartStream()
{
StateChangeReturn s = Pipeline.SetState(State.Playing);
StateChangeReturn s = runningPipeline.pipeline.SetState(State.Playing);
}

private string GetRecordingFilename()
Expand All @@ -110,12 +142,21 @@ private void OnCloseEvent(object sender, CancelEventArgs e)
// We have to wait for EOS to propogate through the pipeline
// Unclear how dependent delay is on machine's speed or other process usage
Console.WriteLine("Shutting down video");
Pipeline.SendEvent(Event.NewEos());
runningPipeline.pipeline.SendEvent(Event.NewEos());
Thread.Sleep(1000);

// Cleanup the unmanaged class objects
Pipeline.SetState(State.Null);
Pipeline.Unref();
runningPipeline.pipeline.SetState(State.Null);
runningPipeline.pipeline.Unref();
}

private void GetNetworkInBackground(object sender, EventArgs e)
{
IPv4InterfaceStatistics interfaceStatistic = networkInterface.GetIPv4Statistics();
long bytesRecv = interfaceStatistic.BytesReceived;
bytesRecvSpeed = (bytesRecv - lastBytesRecv) * 8 / Math.Pow(1024, 2);
Console.WriteLine("Receiving data at: " + string.Format("{0:0.00}", bytesRecvSpeed) + " Mbps" + " over " + networkInterface.Description);
lastBytesRecv = bytesRecv;
}
}
}
3 changes: 3 additions & 0 deletions Rover/GStreamer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
device-scanner
server
server-wrapper
30 changes: 30 additions & 0 deletions Rover/GStreamer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
CPP= g++
CFLAGS= -g -Wall -Wpedantic -std=c++14
GSFLAGS= `pkg-config --cflags --libs gstreamer-1.0` -lgstrtspserver-1.0
HEADERS=
DEV= device-scanner
SERVER= server-wrapper

all: $(DEV) $(SERVER)
rm *.o

debug: $(DEV)_debug $(SERVER)_debug
rm *.o

server: $(HEADERS) server.cpp
$(CPP) -O3 -c server.cpp $(GSFLAGS) $(CFLAGS)

server-wrapper: $(HEADERS) $(SERVER).cpp server
$(CPP) -O3 $(SERVER).cpp -o $(SERVER) server.o $(GSFLAGS) $(CFLAGS)

device-scanner: $(HEADERS) $(DEV).cpp
$(CPP) -O3 $(DEV).cpp -o $(DEV) $(GSFLAGS) $(CFLAGS)

server-wrapper_debug: $(HEADERS) $(SERVER).cpp server
$(CPP) -ggdb -D DEBUG $(SERVER).cpp -o $(SERVER) $(GSFLAGS) $(CFLAGS)

device-scanner_debug: $(HEADERS) $(DEV).cpp
$(CPP) -ggdb -D DEBUG $(DEV).cpp -o $(DEV) $(GSFLAGS) $(CFLAGS)

clean:
rm $(DEV) $(SERVER)
2 changes: 2 additions & 0 deletions Rover/GStreamer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Expects gstreamer and appropriate plugins to be installed based on pipeline.
Expects gst-rtsp-server to be installed.
90 changes: 90 additions & 0 deletions Rover/GStreamer/device-scanner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <gst/gst.h>
#include <unistd.h>
#include <cstring>

#ifdef DEBUG
void structure_fields(const GstStructure *device)
{
gint n_fields = gst_structure_n_fields(device);
for (int i = 0; i < n_fields; i++)
{
const gchar *name;
name = gst_structure_nth_field_name(device, i);
g_print("%s:\n%s\n", name, gst_structure_get_string(device, name));
}
}
#endif

GstDeviceMonitor *device_monitor(void)
{
GstDeviceMonitor *monitor;
GstBus *bus;
GstCaps *caps;

// starts the monitor for the devices
monitor = gst_device_monitor_new ();

// starts the bus for the monitor
bus = gst_device_monitor_get_bus (monitor);
gst_object_unref (bus);

// adds a filter to scan for only video devices
caps = gst_caps_new_empty_simple ("video/x-raw");
gst_device_monitor_add_filter (monitor, "Video/Source", caps);
gst_caps_unref (caps);

gst_device_monitor_start (monitor);

return monitor;
}

int main(int argc, char *argv[])
{
GstDeviceMonitor *monitor;
GList *dev;
GMainLoop *loop;
gst_init(&argc, &argv);

// create the monitor
monitor = device_monitor();
dev = gst_device_monitor_get_devices(monitor);

// loop for the lists
GList *cur = g_list_first(dev);
while(cur != NULL)
{
GstDevice * devi = (GstDevice *) cur->data;
GstStructure * type = gst_device_get_properties(devi);

#ifdef DEBUG
structure_fields(type);
#endif
const char * name = gst_device_get_display_name(devi);
const char * path = gst_structure_get_string(type, "device.path");
g_print("Device-Scanner > Starting process for %s camera at %s\n", name, path);
int mypid = fork();
if(mypid == 0)
{
int ret;
if (strcmp(name, "ZED") == 0)
{
ret = execl("../zed_depth/zed_depth", argv[0]);
}
else
{
ret = execl("./server-wrapper", argv[0], name, path, NULL);
}
return ret; // Shouldn't reach this line
}
cur = g_list_next(cur);
}

loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);

return 0;
}
7 changes: 7 additions & 0 deletions Rover/GStreamer/server-wrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "server.h"

int
main (int argc, char *argv[])
{
return start_server(argc, argv);
}
Loading

0 comments on commit a362de7

Please sign in to comment.