Android Question Help needed for MJPEG


Active Member
Licensed User
Longtime User

I am trying to display a MJPEG stream on my Android phone using the MJPEG B4J example. I have adapted this example to B4A and my needs, just one stream. The stream displays perfectly in a web browser, but I don't get it running on my phone. The connection is made, but no image is shown.

My code at this moment is for Main :

#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private mj1 As MJPEG
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Private ImageView1 As ImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    mj1.Initialize(Me, "mj1")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub mj1_Frame(bmp As Bitmap)
End Sub

and for MJPEG:

Sub Class_Globals
    Private sock As Socket
    Private Astream As AsyncStreams
    Private mCallback As Object
    Private mEventName As String
    Private mHost As String
    Private mPath As String
    Private Data(1000000) As Byte
    Private index As Int
    Private bc As ByteConverter
    Private boundary As String
End Sub

Public Sub Initialize (Callback As Object, EventName As String)
    mCallback = Callback
    mEventName = EventName
End Sub

Public Sub Connect(url As String, Port As Int)
    If Astream.IsInitialized Then Astream.Close
    Dim i As Int = url.IndexOf("/")
    mPath = url.SubString(i)
    mHost = url.SubString2(0, i)
    sock.Connect(mHost, Port, 30000)
End Sub

Private Sub Sock_Connected (Successful As Boolean)
    If Successful Then
        boundary = ""
        Astream.Initialize(sock.InputStream, sock.OutputStream, "astream")
        Dim sTmp As String = $"GET ${mPath} HTTP/1.1
Host: ${mHost}
Connection: keep-alive

        Astream.Write(sTmp.Replace(Chr(10), CRLF).GetBytes("UTF8"))
    End If
End Sub

Private Sub AStream_NewData (Buffer() As Byte)
    bc.ArrayCopy(Buffer, 0, Data, index, Buffer.Length)
    index = index + Buffer.Length
    If boundary = "" Then
        Dim i1 As Int = IndexOfString("Content-Type", 0)
        If i1 > -1 Then
            Dim i2 As Int = IndexOfString(CRLF, i1 + 1)
            If i2 > -1 Then
                Dim ct As String = BytesToString(Data, i1, i2 - i1, "ASCII")
                Dim b As Int = ct.IndexOf("=")
                boundary = ct.SubString(b + 1)
            End If
        End If
        Dim b1 As Int = IndexOfString(boundary, 0)
        If b1 > -1 Then
            Dim b2 As Int = IndexOfString(boundary, b1 + 1)
            If b2 > -1 Then
                Dim startframe As Int = IndexOf(Array As Byte(0xff, 0xd8), b1)
                Dim endframe As Int = IndexOf(Array As Byte(0xff, 0xd9), b2 - 10)
                If startframe > -1 And endframe > -1 Then
                    Dim In As InputStream
                    In.InitializeFromBytesArray(Data, startframe, endframe - startframe + 2)
    #if B4J
                    Dim bmp As Image
                    Dim bmp As Bitmap
    #end if
                    CallSub2(mCallback, mEventName & "_frame", bmp)
                End If
            End If
        End If
    End If
End Sub

Private Sub TrimArray (i As Int)
    bc.ArrayCopy(Data, i, Data, 0, index - i)
    index = index - i
End Sub

Private Sub IndexOfString(s As String, Start As Int) As Int
    Return IndexOf(s.GetBytes("ASCII"), Start)
End Sub

Private Sub IndexOf(bs() As Byte, Start As Int) As Int
    For i = Start To index - 1 - bs.Length
        For b = 0 To bs.Length - 1
            If bs(b) <> Data(i + b) Then
            End If
        If b = bs.Length Then
             Return i
        End If   
    Return -1
End Sub

Private Sub AStream_Error
End Sub

Private Sub Astream_Terminated
End Sub

Does somebody have a complete example how to realize what I want or can point to errors are have made.


Active Member
Licensed User
Longtime User
Hi Erel,

No, it doesn't work either. At a certain moment the boundary value=text/htlm(???) . Then the program stops. I have been tracing FireFox, when I use it to display the image.
The answer on the GET request is:

<title>Raspberry Pi - Surveillance Camera</title>
<center><h1>Raspberry Pi - Surveillance Camera</h1></center>
<center><img src="stream.mjpg" width="640" height="480"></center>

The B4A app gets the same answer.

For FireFox this is enough to show the stream. I don't understand.

Upvote 0


Active Member
Licensed User
Longtime User
Hi Erel,
Sorry, my fault. The software I was running on the Raspberry zero did not generate JPEG frames, but MPJG. I was mislead by the documentation in which both termes were used. I loaded other software and now it works with tje MJPEG example.
Upvote 0