Android Question MJPEG Decoder artitecture

goldmagnet

Member
Licensed User
Longtime User
Hello

I am trying to write a MJPEG stream receiver/decoder with B4A.

I have code that connects to the cameras, logs in, and recives the stream of data chunks, I am current displaying the data in a label.

The next part "Should" be simple and something I have coded on different platforms before. BUT I can not process the data in B4A. Normally I would use a string (the decoding is all string operations) and in the socket data received event:

Sub TcpStreams_NewData (buffer() As Byte)

BufferString = BufferString & BytesToString(buffer, 0, buffer.Length, "UTF8")

But this generates a huge memory leak, thats because the strings in B4A are imputable so a new string is used each time.

Next I tried using string builder and the append method, which generates the same memory issue, and now I am at a loss as to which structure I should use. This process is going to be run at least 25 times per second (thats how fast the label updates with the data), and perhaps 100 times per second depending on how the data is "chunked". Using a massive byte array, while maintaining a pointer might work but the string conversions would be too slow.

Can anyone help me out with some advice, I am new to B4A ?

Thanks

Huw
 

goldmagnet

Member
Licensed User
Longtime User
Erel

This works when written in Java.

The memory issue occurs over time, and has nothing to do with the the size of the data stored in the string builder, i.e. Initalize or .remove has no effect on memory use. It is also fine unit you use the SBT.stringto, the length of SBT never exceeds 40K (very worst case). The data is 7 bit ACSII.
 
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
Yes, our commercial iCatcher products use a Java receiver using the same method.

The same method generates the memory issue when implemented in B4A.

I have tried everything I can think of in B4A, and cant get away from the memory issue. I have stripped out the rest of the code so I can simplify the example. I need to parse the data from the stream, I can receive it, but the minute I put it in a string the memory issue appears.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I'm not familiar with the whole project. However you are creating many large strings. NewData event can be raised many many times. Android processes are limited in memory. It is possible that the GC hasn't yet released the previous strings and then the process runs out of memory.

There isn't any memory leak in the code you posted (might be somewhere else).

You should change your parsing method to work with parts of the string instead of the whole string. B4A StringBuilder is just a wrapper over the Java StringBuilder. If you are missing any method then you can easily add it with reflection.
 
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
OK Erel, I will give up with this project now.

I am working on parts of strings, I simply parse the data until I find the end of frame marker and throw away the rest of the data. In reality the string never gets bigger than 20k. It just seems there is no way to do it in B4A (I think that the GC might be the explanation but I cant think why it works OK in native Java), I think we will wrap the Java receiver we have, can you recommend a tutorial to creating a b4a library from eclipse ?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
No the Java app is in an application on Google play called iCatcher Go, I was rewriting it in B4A. It works fine on the andriod same device I am testing the B4A version, so it id something to do with the B4A implementation.
 
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
Erel

I have just rewritten the receiver using a list and I get the same thing, no string involved. It must be something I am doing wrong or a limitation when running in the debugger, I will simply the code and post it again for your comments, can you confirm that B4A is suitable for receiving a MJPEG stream and parsing the byte data in real time ? As far as I know native java is being run so I cant think why not ?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
As I wrote to you many times in this thread, Basic4android StringBuilder or Strings operations are identical to the same Java objects. If it can be done with Java on Android then it can be done with Basic4android.
I recommend you to shift your focus from "can Basic4android do that?" or "is this a bug in Basic4android?" to the actual problem you are trying to solve.

You can use AsyncStreams to handle huge chunks of data. However you need to do it correctly.
 
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
Erel

Please be less defensive, I would not be trying this if I did not think that B4A could help us with a RAD alternative. I understand what B4A is and hence I am dedicating time to this development. The title of this thread requests help with the architecture of the application, and it my last post I do say it could be my mistake. I am not wildly pointing the finger at B4A, but at the same time "it should work" does not help me much, all I can do is carry on trying. This forum has posts from 3 other customers trying to achieve the same thing, and no one has achieved it, so cracking this would help others too.

Though trial and error I belive the issue is caused by holding up servicing of the newdata event, so I am thinking if I put the stream receiver in a service and use a shared memory structure to parse the data outside the receiving service, the event can be serviced correctly. What do you think ?

My internal data structures never grow greater that 50K and yet I get an out of memory error. If I dont clear the data structure it grows to over 2.2 meg before I get an out of memory error, yet with the simple code examples I get out of memory errors at less than 10% of this figure. Could it be that as all my code is in the activity an internal buffer to TCPStreams is reaching a limit. If I do not process the data all works well and the receiver runs for days, if I run other intensive routines in the activity then I get out of memory.

Erel, I understand you are very busy with the beta etc, and appreciate you taking time to help a customer use B4A.
 
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
IT WORKS !!

I now have a fully working MJPEG receiver, running at 25 FPS, coded in B4A with no custom Java library.

I have written several stream receivers in Java, but the only way to do it in B4A seems to be to have the data receiver in a service, with the parsing code in an activity/class. I don't know why this happens, but unless you do this you get lots of non specific memory errors, as the title of my post suggests it was all down to the code architecture. The memory errors only surface if your data receiver is running continuously for more than a minute or so (same code as earlier in this thread), put the same code in a service and no issues at all.

Here's it running (test app)


This means we can go ahead and release our Android CCTV client to replace the old one.

A very relived

Huw
 
Upvote 0

ciprian

Active Member
Licensed User
Longtime User
Briliant. Can we hope that you are goint to release a library, class, example (free or not)?
There are many users into this forum willing to use it.
 
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
Hi Ciprian

Yes I have seen a number of people on the forum asking for this.

I am way behind on my launch as I have been trying to figure out these memory oddities, I dont understand why it must be done this way and no one here could really help, but it works in this structure. So I will tidy everything up/optimize, finish the app, launch, then and release the receiver code. We have a XML file with over 1000 cameras defined so I will include that to make it simple to connect to a particular model.

Huw
 
Upvote 0

ciprian

Active Member
Licensed User
Longtime User
That's great news....
If you need testers... i'm in. :)
I'm not an experienced programer, so i think can not help you a lot.
But i can try to offer a new point of view if needed.
 
Last edited:
Upvote 0

goldmagnet

Member
Licensed User
Longtime User
Hi

I am just investigating an issue, it works great on a wireless connection, but there is image corruption sometimes when using 3G. I think the issue is in my code and its triggered by lots of small data packets confusing my parsing code.

I will update when this is finalised.

Huw
 
Upvote 0
Top