B4J Question Media Player using many GBs of RAM

cirollo

Active Member
Licensed User
Longtime User
Hi guys!

I've made a desktop app that, using the media player library, executes in sequence some mp4 videos...
There's a tracklist on a txt file that is readed and inserted in a sql lite table, then the reproduction starts from the first video to the last reading from this sql table, then, after the last one, starts again...

The problem is that, even putting a pause of some milliseconds between the videos, the quantity of used ram is always increasing...until the app closed itself after some minutes (40-50) for using too much resources.

how can I reduce the resources usage to avoid forced close of the app???

this is my code

B4X:
#Region  Project Attributes
   #MainFormWidth: 600
   #MainFormHeight: 400
   #AdditionalJar: sqlite-jdbc-3.7.2
#End Region

Sub Process_Globals
  Private fx As JFX
  Private MainForm,splash As Form
  Dim mp As MediaPlayer
  Dim mv As MediaView
  Dim msgbox As Msgboxes
   Dim Sql1 As SQL
   Dim cartella As String
   Dim start,stop As String
   Dim pausa As Long
   Dim wratio, hradio As Int
   Dim videoattuale,videototali As Int
   Private t1,t2 As Timer
   Private robot As JavaObject
   Private ImageView1 As ImageView
End Sub

Sub AppStart (Form1 As Form, Args() As String)
     t1.Initialize("t1", 3000)
     t1.Enabled = True
   splash.Initialize("splash",-1,-1)
     splash.RootPane.LoadLayout("main")
   splash.SetFormStyle("UNDECORATED")'no win title
     splash.Show
   MainForm = Form1
   SetFormInCenter(MainForm, Form1)
'   Form1.   Width=MainForm.WindowWidth
'   Form1.height=MainForm.Windowheight
   Form1.BackColor = fx.Colors.Black   
   'creo prima la tabella sql
   
   Sql1.InitializeSQLite(File.DirApp, "video.db", True)
   Try
     Sql1.ExecNonQuery("drop table lista")
     Sql1.ExecNonQuery("create table lista (nomefile text, sequenza int)")
   Catch
     Log("tabella esistente")
   End Try
   'leggo dal file di configurazione quale e' il percorso dei files ed altri parametri
   Dim tr As TextReader
   tr.Initialize(File.OpenInput(File.DirApp,"parametri.txt"))
   Dim st As String = tr.ReadLine
   Do While st <> Null
     Log(st)
     'cartella dove si trova la playlist
       If (st.SubString2(0,4) = "path") Then
         cartella=st.SubString(5)
     End If
     'orario di inizio playback
     If (st.SubString2(0,5) = "start") Then
         start=st.SubString(6)
     End If
     'orario di fine playback
     If (st.SubString2(0,4) = "stop") Then
         stop=st.SubString(5)
     End If
     'width ratio
         If (st.SubString2(0,6) = "wratio") Then
         wratio=st.SubString(7)
     End If
     'height ratio
         If (st.SubString2(0,6) = "hradio") Then
         hradio=st.SubString(7)
     End If
     'pausa tra i video
     pausa=0
         If (st.SubString2(0,6) = "pausa") Then
         pausa=(st.SubString(7).Trim)
       Log(pausa)
     End If
     st = tr.ReadLine
   Loop
   Log(cartella)
   Dim jo As JavaObject
     jo.InitializeStatic("com.sun.glass.ui.Application")
   robot = jo.RunMethodJO("GetApplication",Null).RunMethodJO("createRobot",Null)
     MouseMove(0, 1000)
End Sub

Sub MouseMove(x As Int, y As Int)
     robot.RunMethod("mouseMove", Array As Object(x, y))
 '  robot.RunMethod("mousePress", Array As Object(1)) 'left button
  'Sleep(50)
 '  robot.RunMethod("mouseRelease", Array As Object(1)) 'left button
End Sub


Sub mv_onready
  Dim videowidth,videoheight As Double
  videowidth=mv.MediaInfo.width
  videoheight=mv.MediaInfo.height
   Log("mainform size:"&MainForm.WindowHeight&"-"&MainForm.WindowWidth)
  Log("media size:"&videoheight&"-"&videowidth)
   mv.FitWidth=MainForm.WindowWidth   'videowidth/wratio '1.6
  mv.FitHeight= MainForm.WindowHeight   'videoheight/hradio '1.6
  mp.Play
End Sub

Sub mp_Complete
 '  msgbox.Show("play completed!","Tips")
   If pausa = 1 Then
       t2.Initialize("t2", 1000)
     t2.Enabled = True
   End If
   If pausa = 2 Then
       t2.Initialize("t2", 2000)
     t2.Enabled = True
   End If
    If pausa = 3 Then
       t2.Initialize("t2", 3000)
     t2.Enabled = True
   End If
   If pausa = 4 Then
       t2.Initialize("t2", 4000)
     t2.Enabled = True
   End If
   If pausa = 5 Then
       t2.Initialize("t2", 5000)
     t2.Enabled = True
   End If
   If pausa = 6 Then
       t2.Initialize("t2", 6000)
     t2.Enabled = True
   End If
     mp.Stop 'new
   If videoattuale < videototali Then
     videoattuale=videoattuale+1
     Riproduci
   Else
     'dobbiamo rileggere il file per vedere se è cambiato qualcosa e rifare il ciclo
     videoattuale=1
     elenco_video   
   End If
End Sub

Sub Riproduci
   Dim RS As ResultSet = Sql1.ExecQuery("select nomefile from lista where sequenza='"&videoattuale&"'")
   Do While RS.NextRow
     Log(RS.GetString("nomefile"))
     Log(DateTime.Time(DateTime.Now).SubString2(0,2))
     mp.Initialize("mp",File.geturi(cartella,RS.GetString("nomefile")))
       mv.init("mv",MainForm.RootPane,mp)
     'scriviamo nel log il file e l'orario in cui viene riprodotto
     Dim tw As TextWriter
     tw.Initialize(File.OpenOutput(File.DirApp,"log.txt",True))
     tw.WriteLine(DateTime.Date(DateTime.Now)&" - "&DateTime.time(DateTime.Now)&" - "&RS.GetString("nomefile")&Chr(10)&Chr(13))
     tw.Close
   Loop
   RS.Close
End Sub

Sub elenco_video
   Try
     Sql1.ExecNonQuery("delete from lista")
   Catch
     Log("tabella vuota")
   End Try   
   Dim numerovideo As Int
   Dim tr As TextReader
   tr.Initialize(File.OpenInput(cartella,"elenco.txt"))
   Dim st As String = tr.ReadLine
   numerovideo=0
   Do While st <> Null
     Log(st)
       If (st.SubString2(0,4) = "nome") Then
       numerovideo=numerovideo+1
         Sql1.ExecNonQuery2("insert into lista values (?,?)",Array As String(st.SubString(5),numerovideo))
       videototali=numerovideo
     End If
         st = tr.ReadLine
   Loop
   Riproduci
End Sub

Sub t1_Tick
     t1.Enabled = False
     splash.Close
'   MainForm.RootPane.LoadLayout("main")
  MainForm.Title="Gemitex Video"
  MainForm.SetFormStyle("UNDECORATED")'no win title
  MainForm.WindowLeft=0
  MainForm.WindowTop=0
  MainForm.WindowHeight=fx.PrimaryScreen.MaxY
  MainForm.WindowWidth=fx.PrimaryScreen.MaxX
   MainForm.Show
   'leggo dal file presente nella cartella sincronizzata la sequenza dei video
   videoattuale=1
   elenco_video
End Sub

Sub t2_Tick
     t2.Enabled = False
End Sub

Sub MainForm_MouseClicked (EventData As MouseEvent)
     Log(EventData)
     If EventData.SecondaryButtonPressed Then
       ExitApplication
   End If
End Sub

Sub SetFormInCenter(Parent As Form, Form As Form)
  Form.WindowTop = Parent.WindowTop + (Parent.WindowHeight - Form.WindowHeight) / 2
  Form.WindowLeft = Parent.WindowLeft + (Parent.WindowWidth - Form.WindowWidth) / 2
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Use File.ReadList instead of TextReader.
2.
B4X:
  If pausa = 1 Then
       t2.Initialize("t2", 1000)
     t2.Enabled = True
   End If
   If pausa = 2 Then
       t2.Initialize("t2", 2000)
     t2.Enabled = True
   End If
    If pausa = 3 Then
       t2.Initialize("t2", 3000)
     t2.Enabled = True
   End If
   If pausa = 4 Then
       t2.Initialize("t2", 4000)
     t2.Enabled = True
   End If
   If pausa = 5 Then
       t2.Initialize("t2", 5000)
     t2.Enabled = True
   End If
   If pausa = 6 Then
       t2.Initialize("t2", 6000)
     t2.Enabled = True
   End If
Equivalent to:
B4X:
t2.Initialize("t2", pause * 1000)
t2.Enabled = True

3. What is this code supposed to do:
B4X:
Do While RS.NextRow
     Log(RS.GetString("nomefile"))
     Log(DateTime.Time(DateTime.Now).SubString2(0,2))
     mp.Initialize("mp",File.geturi(cartella,RS.GetString("nomefile")))
       mv.init("mv",MainForm.RootPane,mp)
     'scriviamo nel log il file e l'orario in cui viene riprodotto
     Dim tw As TextWriter
     tw.Initialize(File.OpenOutput(File.DirApp,"log.txt",True))
     tw.WriteLine(DateTime.Date(DateTime.Now)&" - "&DateTime.time(DateTime.Now)&" - "&RS.GetString("nomefile")&Chr(10)&Chr(13))
     tw.Close
   Loop
Why are you initializing mp multiple times?
 
Upvote 0

cirollo

Active Member
Licensed User
Longtime User
1. Use File.ReadList instead of TextReader.
2.

Equivalent to:
B4X:
t2.Initialize("t2", pause * 1000)
t2.Enabled = True

Hi Erel! of course tried also this, but I get an error regarding that the number should be >0 so I switched to a case statement....

3. What is this code supposed to do:
B4X:
Do While RS.NextRow
     Log(RS.GetString("nomefile"))
     Log(DateTime.Time(DateTime.Now).SubString2(0,2))
     mp.Initialize("mp",File.geturi(cartella,RS.GetString("nomefile")))
       mv.init("mv",MainForm.RootPane,mp)
     'scriviamo nel log il file e l'orario in cui viene riprodotto
     Dim tw As TextWriter
     tw.Initialize(File.OpenOutput(File.DirApp,"log.txt",True))
     tw.WriteLine(DateTime.Date(DateTime.Now)&" - "&DateTime.time(DateTime.Now)&" - "&RS.GetString("nomefile")&Chr(10)&Chr(13))
     tw.Close
   Loop
Why are you initializing mp multiple times?

maybe is this the problem, I'll check....I use this code to read from the sqlite table the next movie to play (sequenza is the playing order....1,2,.....)

But with the initialize I can pass the movie url, without initializing it, how can I do?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
of course tried also this, but I get an error regarding that the number should be >0 so I switched to a case statement....
This means that pausa value is 0 or negative. Check for this case.

But with the initialize I can pass the movie url, without initializing it, how can I do?
Why are you initializing it inside the loop? I assume that the ResultSet only has one value so it is fine.

Add this line and see whether it solves this issue:
B4X:
Dim jo As JavaObject = mp
jo.RunMethod("dispose", null)
 
Upvote 0

cirollo

Active Member
Licensed User
Longtime User
This means that pausa value is 0 or negative. Check for this case.


Why are you initializing it inside the loop? I assume that the ResultSet only has one value so it is fine.

Add this line and see whether it solves this issue:
B4X:
Dim jo As JavaObject = mp
jo.RunMethod("dispose", null)

I do it because in the initialize method of mp I can pass the mediauri as string....
I should add your code after the playback of the video, after mp.stop, right?
 
Upvote 0

cirollo

Active Member
Licensed User
Longtime User
So, I reopened this thread because after an intensive test of my application I found the following issue:

- the GPU utilize always around 90% of video ram, causing (after some hours) the freeze of the app

I can also specify this:

- this app should run on PC-Stick (INTEL Compute Stick 32GB Windows 10 Atom Quad-Core Processor Z3735F 2GB memory 32GB storage wifi…)

- using the same playlist on player like VLC (for example) with same hardware takes around 40%-50% of GPU video ram, avoiding the freeze of the app even after some hours.

So, the question is, how can I optimize the resource consumption to avoid app freezing???

thanks! cirollo
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
While non-ui apps can run for as long as needed (months / years) without any interruptions or memory leaks this is not the case for UI apps and video playing UI apps specifically.

I think that you will need to kill the process after a few hours and start it again. You should do it automatically. You can create a small non-ui app that starts the other app with jShell and kills it after a few hours.
 
Upvote 0
Top