Salve a tutti, ho fatto un programma che registra in continuazione da una sorgente audio, comprime l'audio e ne fa pezzetti da un'ora per 90 giorni (poi cancello i file piu' vecchi).
Normalmente funziona per diverse settimane con un errore di "troppi file aperti".
Cercando su internet con gstreamer AND "too many files open" e' venuto fuori questo thread:
http://gstreamer-devel.966125.n4.nabble.com/Too-many-files-open-issue-td4687242.htmlche mi sembra attinente.
Sembrerebbe che la semplice interruzione della pipeline, la sua distruzione e la sua riapertura NON siano sufficienti a FERMARE la registrazione.
Si deve inviare un EOS alla pipeline ed il codice C proposto e' questo:
void worker(GstElement *pipeline) {
gst_element_send_event(pipeline, gst_event_new_eos());
}
void stopListening() {
boost::thread *th = new boost::thread(worker,pipeline);
}
nel mio programma, che trovate qui':
https://sourceforge.net/projects/prsose/files/tools/PRS_recorder-0.0.10.tar.gz/il codice che si occupa di chiudere la pipeline e generare un nuovo file e' questo:
Public Sub PipeLine(command As String)
Dim Destinazione As New String[]
Dim Risultato As String
Dim clienti As String[]
Dim I As Integer
Select Case command
Case "start"
InitCaptureSystem
InitSink
muxer.LinkTo(sink)
Try pl.Play
If Error Then
Message.Warning("Error starting gstreamer graph. Is Jack Audio server runnig?", "ok")
ToggleButton_RecStop.Value = False
Endif
'riconnette al volo le sorgenti (se la cosa va gestita dall'applicazione e non dal sistema
If AutoReconnectSource = True Then
'non so perche' ma i client mi cambiano nome in modo progressivo .. quindi devo trovare quelli al momento validi per il mio programma
'quindi scansiono i clienti di jack attivi (ho dato il play alla pipeline quindi c'e' anche il recorder) e mi trovo quelli con il nome
'simile a quello che ho settato io in init_capture_system .... ovver "client_name" qualcosa
Shell "jack_lsp" To Risultato
clienti = Split(Risultato, gb.CrLf)
For i = 0 To clienti.Count - 1
If clienti[i] Like ("*" & clientname & "*") Then
Destinazione.Add(clienti[i], Destinazione.Count)
Endif
Next
'a questo punto dovrei avere uno o piu' sink del mio programma che ricevono l'audio dalla sorgente che ho indicato
Shell "jack_connect " & Replace(FirstJackSource, " ", "\\ ") & " " & Destinazione[0]
If StereoSource = True Then
Shell "jack_connect " & GetNextOf(FirstJackSource) & " " & Destinazione[1]
Endif
Endif
Timer_RecordClock.Start
Case "stop"
Try pl.stop
Try Copy User.home & "/" & ClientName & ".ogg" To RealName
Try pl.Close
CheckForFilesToDelete
Timer_RecordClock.Stop
End Select
End
mentre l'inizializzazione della pipeline si fa cosi' (nel mio programma):
Public Sub InitCaptureSystem()
Try pl.Stop
Try pl.close
Try Recorder_Client.close
Try audioformat.close
Try audio_converter.close
Try lev.close
Try muxer.close
Try que1.close
Try que2.close
Try que3.close
'in teoria dovrebbe funzionare:
'gst-launch-1.0 jackaudiosrc connect=0 client-name="test" ! audioconvert ! avenc_aac ! mp4mux ! filesink location=aac_audio.mp4
pl = New MediaPipeline As "PipeLine"
'dico a gstreamer che la sorgente audio e' una sorgente di jack-server
Recorder_Client = New MediaControl(pl, "jackaudiosrc")
Recorder_Client["client-name"] = ClientName
Recorder_Client["connect"] = 0
audioformat = New MediaFilter(pl, "audio/x-raw,channels=2")
audio_converter = New MediaControl(pl, "audioconvert")
'qui decidiamo il tipo di encoder
Select Case encType
Case "vorbis"
encoder = New MediaControl(pl, "vorbisenc")
encoder["name"] = "enc"
encoder["quality"] = -0.1
Case "opus"
encoder = New MediaControl(pl, "opusenc") 'opusenc name=enc bitrate=24000 bitrate-type="vbr"
encoder["name"] = "enc"
encoder["bitrate"] = 24000
encoder["bitrate-type"] = 2 '0=cbr 1=vbr 2=CONSTRAINED_VBR .. che penso sia vbr entro un certo bitrate
Case "mp3"
encoder = New MediaControl(pl, "lamemp3enc") 'opusenc name=enc bitrate=24000 bitrate-type="vbr"
encoder["name"] = "enc"
encoder["bitrate"] = 32
encoder["cbr"] = False 'esempi lamemp3enc target=bitrate cbr=true bitrate=192 | lamemp3enc target=quality quality=0
End Select
lev = New MediaControl(pl, "level")
lev["message"] = True
muxer = New MediaControl(pl, "oggmux")
que1 = New MediaControl(pl, "queue")
que2 = New MediaControl(pl, "queue")
que3 = New MediaControl(pl, "queue")
' Parte audio SENZA LIVELLI AUDIO:
Recorder_Client.LinkTo(audioformat)
audioformat.LinkTo(audio_converter)
'audio_converter.LinkTo(encoder)
'per cercare di estrarre i livelli dell'audio in ingresso invece:
audio_converter.LinkTo(lev)
lev.LinkTo(encoder)
'
encoder.LinkTo(muxer)
End
Public Sub InitSink()
'Dim sink As MediaControl
Try sink.close
'se si vuole registrare su file;
sink = New MediaControl(pl, "filesink")
'sarebbe da rendere parametrica la path
sink["location"] = User.Home & "/" & ClientName & ".ogg"
RealName = RecordingRoot & "/" & ClientName & "_" & Format(Now, "yyyy-mm-dd_hh-nn-ss") & ".ogg"
End
Da super scarsone di C, come faccio a mandare questo fatidico messaggio di EOS alla pipeline?
PS: in allegato l'ultima versione con qualche piccola modifica.