Mobile Server Video Push Questions

Hello,

Following the SDK instructions regarding Mobile Server Video Push I have successfully requested and received response for ‘Connect’, ‘Login’ and ‘RequestStream’ commands as mentioned in the SDK. I see examples in the SDK regarding pulling video, but not a lot regarding the exact parameters or the video url when doing a Push. I’m currently just testing with a HTML5

I have some questions and I apologize they will be in no particular order, but I’m going to lay on the table everything I’ve came across and anyone who can enlighten me; just know it would be greatly appreciated.

1. Can anyone elaborate on how the sequenceID is triggered. Is it just an increment for every response or request?

2. The below parameters are what I have sent to the RequestStream.

//'Fps'             :   '15',

'StreamType'      :   'Transcoded',

'MethodType'      :   'Push',

'SrcWidth'        :   '160',

'SrcHeight'       :   '120',    

//'CameraId'        :   'a7537081-be53-4477-8631-d8cf3326a0e5',

'CameraId'        :   '00000000-0000-0000-0000-000000000000', 

'SignalType'      :   'Upload',

'ExportAvi'       :   'Yes',

'ExportDatabase'  :   'Yes',

'ExportJpeg'      :   'Yes' 

As you can see above I have toyed with them as I’m not sure which are needed and which are not. When I watch the logs after manually using Milestone Mobile App and doing a successful video push I see that it uses an id of 00000000-0000-0000-0000-000000000000 as opposed to the camera guid. I’ve tried with and without and still having issues so if anyone could inform me of why the Milestone Mobile App uses this bogus id I would appreciate. Additionally which params are ‘required’ for what I am trying to achieve?

3. When the RequestStream response is returned in the OutputParams I see protocol, port, address and information needed for the videoChannelURL. However if I just make a request to the videoChannelURL + videoID then I get a failed request. What is the proper videoChannelURL that way I know I’m on the right path. I believe it is:

http://127.0.0.1:8081/XProtectMobile/Video/a7537081-be53-4477-8631-d8cf3326a0e5

For example..

4. When I look in the Mobile Server log file DeviceHandling.log I see:

2017-03-11 03:59:28.947-05:00 [ 56] WARNING - a7537081-be53-4477-8631-d8cf3326a0e5 Video Push Driver (127.0.0.1) - Camera 1 Device communication error (NoDataException). Error: GetMediaDataBlock returned no data.

I assume this is because the JPEG frames that I am sending are not getting through? Does this mean I used the right parameters and url.. but the data was blank? If it means the data was blank could this be a CORS issue? Using Internet Explorer with cross domain security disabled I am able to make the request without any errors in the Developer Console of the browser. However when I use Google Chrome I see a SecurityError and some CORS messages which is what I’m working to resolve at the time of writing this.

5. In the code snippet from the SDK below.. there seems to be an issue. This loop never gets called and ‘as is’ the page errors because of the uuid.replace is undefined. I apologize if I’m missing something, but does the uuid not exist in some cases or is this just deprecated? I know this was probably a dumb question, but I needed to ask it so thank you.

        // convert the uuid string representation to Array of bytes

        var videoIDBytes = (function(str) {

              var result = \[\];

              for(var i=0; i<str.length; i=i+2)

                result.push(parseInt(str.substring(i,i+2),16));

              return result;

            } (this.uuid.replace(/-/g,'')) );

        // put UUID bytes in server expected order

        if(videoIDBytes) {

          for(var bytePosition=0; bytePosition < videoIDBytes.length; bytePosition++ ) 

             headerData.setUint8( bytePosition , 

                     videoIDBytes\[

                         \[3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15\]\[bytePosition\]

                     \]

          );

        }

6. I would assume that this JPEG extraction snippet in the SDK would need to go in a event that does something like:

    videoContext.drawImage($this, 0, 0);

    setTimeout(loop, 1000 / 15); 

    // perform JPEG operation and send via XMLHTTPRequest

    ... videoCanvas.toDataURL ... etc etc

The reason I mentioned this is it seems to me that the example in the SDK is only to show you how to send one frame which of course is not what we are looking for in the real world. So would I loop like shown above and send each frame in a XMLHTTPRequest?

I’ll leave it at this for now. Thank you everyone for your time!

Update:

When I try videoChannelURL:

http://127.0.0.1:8081/XProtectMobile/Video/a7537081-be53-4477-8631-d8cf3326a0e5

I get:

{readyState: 4, responseText: “”, status: 410, statusText: “Gone”}

Do I need to keep this stream alive? I am immediately sending a request and would imagine a timeout would be at minimum in seconds.

I have consulted with a developer colleague, and this is what we have..

It is left for the client to define logic for change of the sequenceId.

The easiest implementation is to be used incremental logic.

Server doesn’t use it. It is left only if the client wants to sync request with responses.

If I remember well you can keep one and the same Integer value for all the request and it should work.

(My recommendation however is to be used Integer increment, starting from zero).

The only mandatory parameter for the RequestStream (in case of VideoPush) is “SignalType” with value of “Upload”.

If the method succeeds, in the OutputParams of the response will be returned “VideoId” and/or “ChannelId”.

Milestone Mobile App is using this “bogus” camera id because this was the easiest implementation for the developers.

Mobile server will discard all other parameters, except “SignalType” in case of “Upload”.

That’s the proper address.

You should use it in order to upload JPEG video frames on the already opened Video Push channel.

You have correctly constructed the address: http://127.0.0.1:8081/XProtectMobile/Video/<video_id_returned_on_RequestStream_response>.

Please bear in mind the video_id is dynamic and changed on every RequestStream command (should extract it from the response – in the same way as it is done for the live video channels).

Of course address will be valid only if RequestStream returned without an error.

I cannot really guess.

I would assume that data has reached to the server and if it is empty, probably you could have such log message.

If CORS issue occurs, data won’t be received in the Server at all.

Hmm. We will do a little researching..

Usually you have to make a loop and call/make http requests.

I do not think however that XMLHTTPRequest is the best choice.

Probably it is not clear in the documentation, but the JPEG frames are send trough the Video channel, which have binary structure, not XML one as the Communication one (sending commands).

In short you have to send videoHeder followed by video data in every HttpRequest.

Update.

This generally means that you make request on not existing address.

There are two possibilities: Either video channel was expired and listener on this address was closed, or listener was never created on this address.

I’ll second that VIdeoId is dynamic and is different between every two RequestStreams.

So if you try to use one and the same fixed VideoId (resp. address/alias) to push video frames – this won’t work at all.

Very helpful. Thank you for taking time out of your day to write this detailed response. I will give your suggestions a go and see what happens.

I would like to direct your attention to this new Milestone initiative. Milestone is inviting to a workshop where the objective is to form a future Milestone Mobile (Apps) SDK. Read about it here.

https://www.milestonesys.com/newsletters/2017/Developer-Community-Update/Mobile-SDK/

The workshop is also an entry to a beta program on the new Mobile SDK.

Great. I will look into this thank you again.

Bo,

I’ve verified everything was as you said above and I’m still getting a Bad Request when I attempt to send a frame through to Milestone. Additionally in this first image I wanted to show that uuid.replace() error from the code snippet in the SDK that I said was failing above and you stated you would look into. As you can see below everything seems to be working as intended until I send a frame through. I see the JPEG binary coming through in Fiddler so I know data is going out, but I am missing something obviously. Do you have any suggestions? I was hoping to use the Milestone Mobile app to intercept and debug with.. to monitor its traffic and simulate what is being performed there, however it appears the Milestone Mobile app does not follow the same instruction and instead uses SOAP requests. My plan is to understand what is going on with the uuid code and recreate it in hopes to figuring out why it is failing, but even without that section of code I am still getting a Bad Request and correct me if I’m wrong, but I would expect to get a valid response if data went through, but the data was incorrectly delivered.

mobileserverlogfirewall

Additionally.. the successful log you see in DeviceHandling.log is when I utilized the Milestone Mobile App. My attempts are the GetMediaDataBlock returned no data errors.

It appears the Mobile Server protocol in the SDK is hit or miss as far as completeness. For example in the Mobile Server protocol - Decoding Frames section var uuid = dataView.getUUID(); is defined, however that is the only place uuid seems to appear.. so you create a var that is not used? This is for Decoding Frames and what I’m hoping to do is Encode them and Video Push so this is irrelevant to me, however the section in the SDK that does pertain to what I’m trying to accomplish also seems to be missing code.

In the Mobile Server protocol - Video Push section headerData is created, but never used? videoChannelURL is referenced, but never defined.. in Mobile Server protocol - Decoding Frames once again I see httpRequest.open(‘POST’,‘http://mobileserver.name:8081/Video/f3cad68b-8692-4068-a79b-fdfd58665699’); which seems to be deprecated and it appears Milestone now uses /XProtect/Video path instead of /Video. Back to Mobile Server protocol - Video Push I see videoIDBytes is a variable function and a for loop which states it: // put UUID bytes in server expected order … however it never shows what str you should pass to videoIDBytes and if the loop is immediately after the variable function is defined then of course it will be undefined seeming the loop does not appear to pass str.. instead it only accesses elements inside an array that does not yet exist (videoIDBytes)..

I’m sorry to ask so much, but I think a lot of instruction is missing or half composed. I’m not as familiar as the Milestone team with streaming video so it makes it time consuming to try to figure out what needs to happen which is why I am reaching out more than I would normally. We have a deadline to demo our product coming up and this Video Push is the biggest hurdle standing in our way. I know that’s not your problem, but the reason I mention is if there is a way for you to reach out and see what is going on here then I would of course appreciate it greatly.

Thank you.

I was able to resolve my Bad Request problems and successfully push video into Milestone through the Milestone driver. As I mentioned before this line of code:

(this.uuid.replace(/-/g,‘’)) was failing due to uuid being undefined. I looked at it and realized that its replacing a hypen so the uuid it was looking for could possibly be a videoID or streamID or in reality any similar identifier that I specify just so the server gets the bytes in expected server order and has that uuid padding its looking for.. so I used streamID from the OutputParam and viola video push working as expected coming through the live preview in Milestone :slight_smile: ..

For anyone else trying to resolve this in the future.. In the RequestStream command response there is an OutputParam object that Milestone responds with that has a StreamID located in the object tree as shown below.. so I basically did this (you will have to replace response with your XMLHTTPRequest response object) ..

var streamID = response.Communication.Command.OutputParams.Param[1][“@attributes”].Value;

(streamID.replace(/-/g,‘’))

Based on your questions here Milestone Development realized that the documentation was not accurate. Without going into details I would like to give you the result of this realization.

Milestone has managed to integrate the Video Push into the Demo app.

The DemoApp code is uploaded here: http://download.milestonesys.com/MIPSDK/Beta/MIPSDK2017R2_Mobile/DemoApp.zip

In order for this sample to work you need to:

  1. Have a setup with a Video Push camera configured.

  2. Upload the Demo app in the same folder were the sources of WebClient are located (default location [C:\Program](file:C:/Program) Files\Milestone\Milestone Mobile Server\Web ).

  3. Open Mobile Server configuration file VideoOS.MobileServer.Service.exe.config (default location [C:\Program](file:C:/Program) Files\Milestone\Milestone Mobile Server) and change the Content Security Rule (we did that by default and will be released with next release):

From:

To:

  1. Restart Mobile server

  2. Run Demo app (default location: http://localhost:8081/DemoApp/index.html )

At the same the documentation has been updated, and the documentation is uploaded here: http://download.milestonesys.com/MIPSDK/Beta/MIPSDK2017R2_Mobile/Doc.zip

Milestone hope this will lead you to a succesful implementation.

PS.

The sample is tested in Firefox, Chrome and Edge browsers.

The video push will send in the video from the camera on the PC, so you must test using a PC with a camera.

Bo,

Impressive response from both you and Milestone. I really appreciate the time you have spent answering my questions. Thank you very much for that and thanks to your contacts at Milestone for going the extra mile.