Italy
Asked — Edited

Camera Stop Doesn'T Work In C# Sdk

Hi

I'm having some problems stopping the webcam using the C# SDK. StopCamera() method doesn't work and camera is still active. I need to kill the iis express process to make it stop.

My current code that is not working is this: Camera.StopCamera(); Camera.OnNewFrame -= Camera_OnNewFrame; Camera.Dispose(); Camera = null; Ezb.Disconnect();


ARC Pro

Upgrade to ARC Pro

Elevate your robot's capabilities to the next level with Synthiam ARC Pro, unlocking a world of possibilities in robot programming.

PRO
Synthiam
#1  

The camera works - if you're running this in iis express, then i suspect you're re-creating the camera object each time. You will need to assign the camera object to either a static variable or as an application variable.

#2  

Thank you Dj. I'm using Signalr to provide movements from phone accelerometer and receive frames from webcam.

The initialization is done when connection is established and camera is initialized once and placed in a global static variable. I'm disposing it when the connection is closed but doesn't work.

 
 public static EZB Ezb { get; set; }
public static Camera Camera { get; set; }

        public override Task OnConnected()
        {
            Ezb = new EZB();
            Ezb.OnConnectionChange += Ezb_OnConnectionChange;
            var availablePort = EZB.GetAvailableCommunicationPorts(false).LastOrDefault();
            if (availablePort != null)
            {
                Ezb.Connect(availablePort);
                if (Camera == null)
                {
                    Camera = new Camera(Ezb);
                    Camera.OnNewFrame += Camera_OnNewFrame;
                    var devices = Camera.GetVideoCaptureDevices();
                    if (devices.Any())
                        Camera.StartCamera(devices.Last(), 640, 480);
                }
            }
            return base.OnConnected();
        }
PRO
Synthiam
#3  

OnConnected() is the ezb event? If so, creating a new instance of Ezb will lose the instance which called the function to begin with. Then connecting a second time with the ezb to get the last port? Sorry, but that code really screwy :)

can you post your project and i'll take a look? Zip it and attach it here with the Upload File button

#4  

Sure here's my code: http://pastebin.com/YiDEfCDC

If you want I can send you the entire project but you will need to deploy it on a local IIS server in order to connect with a device that has accelerometer and html5 capability.

the 2 tasks OnConnected and OnDisconnect run with the websocket connection.

PRO
Synthiam
#5  

There's no need to dispose or null the camera or ezb object. They can live for ever since they are static - it's just harder on the CLR and it may also get confused if there's a bunch of executions of the events at the same time. In the change i made, simply initiate the objects once and let them live for ever.

Also, i'm not quite sure of the logic - but i feel it's correct with my edits. You want the camera to STOP when the EZB is disconnected. And you want the EZB to disconnect when the websocket disconnects. I added an async and await to properly use the Task declaration of the OnDisconnected() override. This is becuase the Thread.Sleep is far too dangerous to use in this instance. Specifically because the Disconnect may be overriden by another Connect while it's sleeping. I don't know if the async and await will fix that without testing, but it's better than what was there.

Also, ensure that you're not running multiple web server instance (i.e. server farm) because the static objects will only exist within their unique space. To share the object amongst other web server iis instances, store the object in an Application Variable. Set the Web.Config to use State Session Manager and start the State Session Manager service in windows. So, ensure you have only 1 web pool!

Anyway, try this...


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using EZ_B;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;

namespace ArscolorVr.Hubs {

  public class VrHub : Hub {

    public static EZB Ezb {
      get;
      set;
    }

    public static Camera Camera {
      get;
      set;
    }

    public override Task OnConnected() {

      if (Ezb == null) {

        Ezb = new EZB();
        Ezb.OnConnectionChange += Ezb_OnConnectionChange;
      }

      if (!Ezb.IsConnected)
        Ezb.Connect("192.168.1.1:23");

      if (Camera == null) {

        Camera = new Camera(Ezb);
        Camera.OnNewFrame += Camera_OnNewFrame;
      }

      if (!Camera.IsActive)
        Camera.StartCamera(new ValuePair("192.168.1.1:24", "192.168.1.1:24"), 640, 480);

      return base.OnConnected();
    }

    public override async Task OnDisconnected(bool stopCalled) {

      if (Ezb != null) {

        Ezb.Servo.SetServoPosition(Servo.ServoPortEnum.D2, 50);
        Ezb.Servo.SetServoPosition(Servo.ServoPortEnum.D1, 50);

        await Task.Delay(1000);

        Ezb.Servo.ReleaseAllServos();

        Ezb.Disconnect();
      }

      return base.OnDisconnected(stopCalled);
    }

    public void ChangePosition(int x, int y) {

      if (Ezb == null || !Ezb.IsConnected)
        return;

      x = 180 - x;
      x = x + 30;
      y = y + 30;
      x = MyRound(x * 80 / 180);
      y = MyRound(y * 80 / 180);

      if (x > 10 && x < 90)
        Ezb.Servo.SetServoPosition(Servo.ServoPortEnum.D2, x);

      if (y > 10 && y < 90)
        Ezb.Servo.SetServoPosition(Servo.ServoPortEnum.D1, y);
    }

    private void Ezb_OnConnectionChange(bool isConnected) {

      if (isConnected) {

        Ezb.Servo.SetServoPosition(Servo.ServoPortEnum.D2, 50);
        Ezb.Servo.SetServoPosition(Servo.ServoPortEnum.D1, 50);
      } else {

        if (Camera != null && Camera.IsActive) 
          Camera.StopCamera();
      }
    }

    private void Camera_OnNewFrame() {

      if (Camera == null || !Camera.IsActive)
        return;

      var base64Image = ImageToBase64(Camera.GetCurrentBitmap, ImageFormat.Jpeg);

      Clients.All.getImage(base64Image);
    }

    private static int MyRound(double d) {

      return (int)(d + 0.5);
    }

    private string ImageToBase64(Image image, ImageFormat format) {

      using (var ms = new MemoryStream()) {

        image.Save(ms, format);

        var imageBytes = ms.ToArray();

        var base64String = Convert.ToBase64String(imageBytes);

        return base64String;
      }
    }
  }
}

#6  

Hi Dj

just letting you know that your code worked and this is the final result: https://www.facebook.com/alex33x/videos/10207409777592949/

Basically it's a .net webserver that receives the orientation data from any browser compatible with the javascript orientation api. The data is sent to the webserver via websocket. Then the server moves the servos and get the image from the connected webcam and sends it back to the browser

PRO
Synthiam
#7  

That's fantastic! What a brilliant idea