iOS Tutorial MJPEG / CCTV Server

This is a port of this example to B4i: https://www.b4x.com/android/forum/threads/mjpeg-cctv-server.73792/

The code is almost identical.

It turns the iOS device into a CCTV server. You can connect to the device from one or more browsers to see the captured video.

The frame rate is currently set to 6 frames per second. You can change it by modifying IntervalMS. Set it to 50 (1000 / 50 = 20 fps) and it will look much better.


SS-2016-12-04_15.35.36.jpg
 

Attachments

  • CCTV.zip
    3.9 KB · Views: 805
Last edited:
D

Deleted member 103

Guest
Fixed problem, so it works.
Main-Code:
B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page

    Private IP As String

    Private mj1 As MJPEG
    Private ImageView1 As ImageView
End Sub

Private Sub Application_Start (Nav As NavigationController)
    'SetDebugAutoFlushLogs(True) 'Uncomment if program crashes before all logs are printed.
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.Title = "Page 1"
    Page1.RootPanel.LoadLayout("1")
    Page1.RootPanel.Color = Colors.White
    NavControl.ShowPage(Page1)

    mj1.Initialize(Me, "mj1")
    IP = "192.168.178.22" '/mjpg/video.mjpg"
    mj1.Connect(IP, "51042")
End Sub

Private Sub Page1_Resize(Width As Int, Height As Int)

End Sub

Sub mj1_Frame(bmp As Bitmap)
    Log("mj1_Frame")
    ImageView1.Bitmap = bmp
End Sub

MJPEG-Code:
B4X:
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.Initialize("sock")
    sock.Connect(url, 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
'
'"$
    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
    Else
        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
    #else
                    Dim bmp As Bitmap
    #end if
                    bmp.Initialize2(In)
                    CallSub2(mCallback, mEventName & "_frame", bmp)
                End If
                TrimArray(b2)
                
            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 Exit
        Next
        If b = bs.Length Then Return i
    Next
    Return -1
End Sub

Private Sub AStream_Error
    Log("error")
End Sub

Private Sub Astream_Terminated
    Log("Terminated")
End Sub
 
Top