Differenze tra le versioni di "Gestione dei dati media con GStreamer"
(21 versioni intermedie di uno stesso utente non sono mostrate) | |||
Riga 3: | Riga 3: | ||
==Impostare un ''Elemento'' per la gestione del flusso dei dati== | ==Impostare un ''Elemento'' per la gestione del flusso dei dati== | ||
− | Un ''Elemento'' è la Classe di oggetti più importante in ''GStreamer''. Esso svolge una determinata funzione, ed è utilizzato per gestire il flusso di dati, come ad esempio lettura, decodifica ed invio dei medesimi alla scheda audio. | + | Un ''Elemento'' è la Classe di oggetti più importante in ''GStreamer''. Esso svolge una determinata funzione, ed è utilizzato per gestire il flusso di dati, come ad esempio lettura, decodifica ed invio dei medesimi alla scheda audio. Di solito si crea una catena di Elementi collegati insieme (''Pipeline'') e si lascia che i dati passino attraverso questa catena di Elementi. In tal modo è possibile sfruttare le loro funzionalità ed ottenere gli obiettivi multimediali desiderati (come ad esempio la riproduzione audio). |
Il modo più semplice per creare un ''Elemento'' è utilizzare la funzione: | Il modo più semplice per creare un ''Elemento'' è utilizzare la funzione: | ||
Riga 96: | Riga 96: | ||
<BR>La funzione ritorna un valore booleano ''True'' se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata. | <BR>La funzione ritorna un valore booleano ''True'' se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata. | ||
In Gambas questa funzione sarà così dichiarata: | In Gambas questa funzione sarà così dichiarata: | ||
− | Private Extern gst_element_query_duration( | + | Private Extern gst_element_query_duration(gselement As Pointer, formatI As Integer, duration As Pointer) As Boolean |
e sarà richiamata in routine ad esempio così: | e sarà richiamata in routine ad esempio così: | ||
Dim Dim GST_FORMAT_TIME As Integer = 3 | Dim Dim GST_FORMAT_TIME As Integer = 3 | ||
Riga 120: | Riga 120: | ||
<BR>La funzione ritorna un valore booleano ''True'' se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata. | <BR>La funzione ritorna un valore booleano ''True'' se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata. | ||
In Gambas questa funzione sarà così dichiarata: | In Gambas questa funzione sarà così dichiarata: | ||
− | Private Extern gst_element_query_position( | + | Private Extern gst_element_query_position(gselement As Pointer, formatI As Integer, cur As Pointer) As Boolean |
e sarà richiamata in routine ad esempio così: | e sarà richiamata in routine ad esempio così: | ||
Dim GST_FORMAT_TIME As Integer = 3 | Dim GST_FORMAT_TIME As Integer = 3 | ||
Riga 146: | Riga 146: | ||
Dim timeout As Long | Dim timeout As Long | ||
− | state = Alloc(4) | + | state = Alloc(SizeOf(gb.Byte), 4) |
− | pending = Alloc(4) | + | pending = Alloc(SizeOf(gb.Byte), 4) |
gst_element_get_state(player, state, pending, timeout) | gst_element_get_state(player, state, pending, timeout) | ||
Print Int@(state) | Print Int@(state) | ||
− | |||
Riga 162: | Riga 161: | ||
anche questa precedentementre vista, alla quale in Gambas attribuiremo il secondo parametro a ''Null'': | anche questa precedentementre vista, alla quale in Gambas attribuiremo il secondo parametro a ''Null'': | ||
gst_element_set_state(elem, GST_STATE_NULL) | gst_element_set_state(elem, GST_STATE_NULL) | ||
− | |||
Riga 168: | Riga 166: | ||
In conclusione possiamo dire che bastano solo poche funzioni esterne del API di ''GStreamer'' per effettuare la riproduzione di un file audio. | In conclusione possiamo dire che bastano solo poche funzioni esterne del API di ''GStreamer'' per effettuare la riproduzione di un file audio. | ||
− | Riportiamo un esempio pratico funzionante | + | Riportiamo alcuni esempi con applicazioni in ambiente grafico ed applicazione ''a riga di comando''. |
− | Private | + | |
+ | |||
+ | ===Esempio con applicazione in ambiente grafico usando la Classe ''Timer''=== | ||
+ | Mostriamo di seguito un esempio pratico e funzionante di un'applicazione in ambiente grafico che fa uso della la Classe ''Timer'' per consentire l'estrazione della durata totale e del tempo trascorso di esecuzione del file mediale: | ||
+ | Private elem As Pointer | ||
+ | Private tempus As Timer | ||
+ | |||
− | Library "libgstreamer-1.0" | + | Library "libgstreamer-1.0:0.2403.0" |
− | Private | + | Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING |
− | Private | + | Private GST_FORMAT_TIME As Integer = 3 |
<FONT color=gray>' ''gst_init (int *argc, char **argv[])'' | <FONT color=gray>' ''gst_init (int *argc, char **argv[])'' | ||
Riga 194: | Riga 198: | ||
<FONT color=gray>' ''GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)'' | <FONT color=gray>' ''GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)'' | ||
' ''Sets the state of the element.''</font> | ' ''Sets the state of the element.''</font> | ||
− | Private Extern gst_element_set_state( | + | Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer |
+ | |||
+ | <FONT color=gray>' ''gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)'' | ||
+ | ' ''Queries an element for the total stream duration in nanoseconds.''</font> | ||
+ | Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean | ||
+ | |||
+ | <FONT color=gray>' ''gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)'' | ||
+ | ' ''Queries an element for the stream position in nanoseconds.''</font> | ||
+ | Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean | ||
<FONT color=gray>' ''void gst_object_unref(gpointer object)'' | <FONT color=gray>' ''void gst_object_unref(gpointer object)'' | ||
Riga 201: | Riga 213: | ||
− | + | Public Sub Form_Open() | |
− | + | gst_init(0, 0) | |
+ | |||
+ | With tempus = New Timer As "Tempus" | ||
+ | .Delay = 70 | ||
+ | End With | ||
+ | |||
+ | End | ||
− | |||
− | + | Public Sub Button1_Click() <FONT color=gray>' ''Avvia la riproduzione del file mediale''</font> | |
− | + | Dim fileaudio as string | |
− | + | elem = gst_element_factory_make("playbin", "Riproduzione") | |
+ | fileaudio = "<FONT color=darkgreen>''/percorso/del/file/audio''</font>" | ||
+ | |||
+ | g_object_set(elem, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) | ||
+ | |||
<FONT color=gray>' ''Avviamo la riproduzione audio:''</font> | <FONT color=gray>' ''Avviamo la riproduzione audio:''</font> | ||
− | + | gst_element_set_state(elem, GST_STATE_PLAYING) | |
+ | |||
+ | tempus.Start | ||
− | + | End | |
− | + | Public Sub Button2_Click() <FONT color=gray>' ''Arresta la riproduzione del file mediale''</font> | |
− | + | tempus.Stop | |
− | + | ||
− | + | gst_element_set_state(elem, GST_STATE_NULL) | |
− | |||
− | + | gst_object_unref(elem) | |
− | + | End | |
− | + | Public Sub ToggleButton1_Click() <FONT color=gray>' ''Pone in pausa e riprende la riproduzione del file mediale''</font> | |
− | + | If ToggleButton1.Value Then | |
+ | tempus.Stop | ||
+ | gst_element_set_state(elem, GST_STATE_PAUSED) | ||
+ | Else | ||
+ | gst_element_set_state(elem, GST_STATE_PLAYING) | ||
+ | tempus.Start | ||
+ | Endif | ||
+ | |||
+ | End | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Public Sub Tempus_Timer() | |
+ | |||
+ | Dim positio, durata As Long | ||
+ | |||
+ | gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) | ||
+ | |||
+ | gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(positio)) | ||
+ | |||
+ | Write #File.Out, "\rDurata: " & Time(0, 0, 0, durata / 1000000) & " - Posizione: " & Time(0, 0, 0, positio / 1000000) | ||
+ | |||
+ | If (positio > 0) And (durata = positio) Then | ||
+ | tempus.Stop | ||
+ | gst_element_set_state(elem, GST_STATE_NULL) | ||
+ | gst_object_unref(elem) | ||
+ | Endif | ||
− | + | End | |
− | + | ===Esempio con applicazione in ambiente grafico usando la funzione ''Wait''=== | |
− | + | Mostriamo di seguito un esempio pratico e funzionante di un'applicazione in ambiente grafico che fa uso della funzione ''Wait'' per consentire l'estrazione della durata totale e del tempo trascorso di esecuzione del file mediale: | |
− | Library "libgstreamer-1.0" | + | Private elem As Pointer |
+ | Private v As Boolean | ||
+ | |||
+ | |||
+ | Library "libgstreamer-1.0:0.2403.0" | ||
− | Private | + | Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING |
− | Private | + | Private GST_FORMAT_TIME As Integer = 3 |
− | |||
<FONT color=gray>' ''gst_init (int *argc, char **argv[])'' | <FONT color=gray>' ''gst_init (int *argc, char **argv[])'' | ||
Riga 276: | Riga 318: | ||
<FONT color=gray>' ''gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)'' | <FONT color=gray>' ''gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)'' | ||
' ''Queries an element for the total stream duration in nanoseconds.''</font> | ' ''Queries an element for the total stream duration in nanoseconds.''</font> | ||
− | Private Extern gst_element_query_duration(gstelement As Pointer, | + | Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean |
<FONT color=gray>' ''gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)'' | <FONT color=gray>' ''gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)'' | ||
' ''Queries an element for the stream position in nanoseconds.''</font> | ' ''Queries an element for the stream position in nanoseconds.''</font> | ||
− | Private Extern gst_element_query_position(gstelement As Pointer, | + | Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean |
<FONT color=gray>' ''void gst_object_unref(gpointer object)'' | <FONT color=gray>' ''void gst_object_unref(gpointer object)'' | ||
Riga 287: | Riga 329: | ||
− | ''' | + | Public Sub Form_Open() |
+ | |||
+ | gst_init(0, 0) | ||
+ | |||
+ | End | ||
+ | |||
+ | |||
+ | Public Sub Button1_Click() <FONT color=gray>' ''Avvia la riproduzione del file mediale''</font> | ||
− | |||
Dim fileaudio as string | Dim fileaudio as string | ||
− | Dim | + | Dim durata As Long = 1 |
+ | Dim positio As Long | ||
+ | |||
+ | elem = gst_element_factory_make("playbin", "Riproduzione") | ||
+ | |||
+ | fileaudio = "<FONT color=darkgreen>''/percorso/del/file/audio''</font>" | ||
+ | |||
+ | g_object_set(elem, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) | ||
+ | |||
+ | <FONT color=gray>' ''Avviamo la riproduzione audio:''</font> | ||
+ | gst_element_set_state(elem, GST_STATE_PLAYING) | ||
+ | |||
+ | v = False | ||
+ | |||
+ | While (positio < durata) And (v = False) | ||
+ | Wait 0.01 | ||
+ | gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) | ||
+ | gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(positio)) | ||
+ | Write #File.Out, "\rDurata: " & Time(0, 0, 0, durata / 1000000) & " - Posizione: " & Time(0, 0, 0, positio / 1000000) | ||
+ | Wend | ||
+ | |||
+ | gst_element_set_state(elem, GST_STATE_NULL) | ||
+ | |||
+ | gst_object_unref(elem) | ||
+ | |||
+ | End | ||
+ | |||
+ | |||
+ | Public Sub Button2_Click() <FONT color=gray>' ''Arresta la riproduzione del file mediale''</font> | ||
+ | |||
+ | v = True | ||
+ | |||
+ | End | ||
+ | |||
+ | |||
+ | Public Sub ToggleButton1_Click() <FONT color=gray>' ''Pone in pausa e riprende la riproduzione del file mediale''</font> | ||
+ | |||
+ | If ToggleButton1.Value Then | ||
+ | gst_element_set_state(elem, GST_STATE_PAUSED) | ||
+ | Else | ||
+ | gst_element_set_state(elem, GST_STATE_PLAYING) | ||
+ | Endif | ||
+ | |||
+ | End | ||
+ | |||
+ | |||
+ | ===Esempio con applicazione ''a riga di comando''=== | ||
+ | Mostriamo di seguito un esempio pratico e funzionante di un'applicazione ''a riga di comando'': | ||
+ | Library "libgstreamer-1.0:0.2403.0" | ||
− | + | Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING | |
+ | Private Const GST_FORMAT_TIME As Integer = 3 | ||
− | + | <FONT color=gray>' ''gst_init (int *argc, char **argv[])'' | |
+ | ' ''Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins.''</font> | ||
+ | Private Extern gst_init(argc As Pointer, argv As Pointer) | ||
− | + | <FONT color=gray>' ''GstElement * gst_element_factory_make(const gchar *factoryname, Const gchar * name)'' | |
+ | ' ''Create a new element of the type defined by the given element factory.''</font> | ||
+ | Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer | ||
− | + | <FONT color=gray>' ''gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)'' | |
+ | ' ''Converts an absolute filename to an escaped ASCII-encoded URI.''</font> | ||
+ | Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String | ||
− | <FONT color=gray>' '' | + | <FONT color=gray>' ''void g_object_set(gpointer object, const gchar *first_property_name, ...)'' |
− | + | ' ''Sets properties on an object.''</font> | |
+ | Private Extern g_object_set(gobject As Pointer, key As String, value As String, tertium As String) | ||
+ | |||
+ | <FONT color=gray>' ''void g_object_set(gpointer object, const gchar *first_property_name, ...)'' | ||
+ | ' ''Sets properties on an object.''</font> | ||
+ | Private Extern g_object_set_Volume(gobject As Pointer, key As String, value As Float, tertium As String) Exec "g_object_set" | ||
+ | |||
+ | <FONT color=gray>' ''GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)'' | ||
+ | ' ''Sets the state of the element.''</font> | ||
+ | Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer | ||
+ | |||
+ | <FONT color=gray>' ''gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)'' | ||
+ | ' ''Queries an element for the total stream duration in nanoseconds.''</font> | ||
+ | Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean | ||
+ | |||
+ | <FONT color=gray>' ''gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)'' | ||
+ | ' ''Queries an element for the total stream position in nanoseconds.''</font> | ||
+ | Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean | ||
+ | |||
+ | <FONT color=gray>' ''void gst_object_unref(gpointer object)'' | ||
+ | ' ''Decrements the reference count on object .''</font> | ||
+ | Private Extern gst_object_unref(gobject As Pointer) | ||
+ | |||
+ | |||
+ | Public Sub Main() | ||
+ | |||
+ | Dim elem As Pointer | ||
+ | Dim fileaudio as string | ||
+ | Dim durata, pos As Long | ||
+ | Dim volume As Float | ||
+ | |||
+ | gst_init(0, 0) | ||
+ | |||
+ | elem = gst_element_factory_make("playbin", "riproduzione") | ||
+ | |||
+ | fileaudio = "<FONT color=darkgreen>''/percorso/del/file/audio''</font>" | ||
+ | |||
+ | g_object_set(elem, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) | ||
+ | |||
+ | <FONT color=gray>' ''Imposta il valore del volume (da 0.0 a 1.0) di esecuzione:''</font> | ||
+ | volume = 0.7 | ||
+ | g_object_set_Volume(elem, "volume", volume, Null) | ||
+ | |||
+ | <FONT color=gray>' ''Avvia la riproduzione audio:''</font> | ||
+ | gst_element_set_state(elem, GST_STATE_PLAYING) | ||
− | + | Repeat | |
− | + | gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) | |
− | + | Wait 0.01 | |
− | + | Until durata > -1 | |
− | + | ||
+ | Repeat | ||
+ | gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(pos)) | ||
+ | Write "\r\e[0mDurata: " & Time(0, 0, 0, durata / 1000000) & " Pos. \e[31m" & Time(0, 0, 0, pos / 1000000) | ||
+ | Wait 0.001 | ||
+ | Until pos >= durata | ||
− | + | gst_object_unref(elem) | |
+ | Print "\nEsecuzione terminata." | ||
− | ''' | + | End |
+ | |||
+ | |||
+ | =La gestione dei dati audio con GStreamer mediante una ''Pipeline'' di elementi= | ||
+ | Gstreamer fornisce una potente struttura per consentire agli utenti esperti di gestire flussi audio e video in modi estremamente flessibili. | ||
+ | |||
+ | Gstreamer con tutti i codec abilitati supporta un'enorme varietà di formati di file. | ||
+ | |||
+ | Per creare e gestire "Pipeline" personalizzate di plugin media, è possibile utilizzare il programma integrato "gst-launch" (e più precisamente ''gst-launch-1.0''). | ||
+ | <BR>Il formato generale di "Pipeline" di GStreamer da utilizzare è il seguente: | ||
+ | gst-launch-1.0 -v xxxsrc ! xxxdemuxer ! xxxdecoder ! xxxprocessing ! xxxencoding ! xxxmux ! xxxsink | ||
+ | |||
+ | Invece nel codice la corrispondente funzione specifica di Gstreamer è la seguente: | ||
+ | GstElement * gst_parse_launch (const gchar *pipeline_description, GError **error) | ||
+ | Facciamo un elenco di questi plugin in ordine: | ||
+ | |||
+ | '''xxxsrc''': un sorgente di dati audio, da cui provengono i dati di input originari. Un plugin specifico al riguardo è, ad esempio, è "''filesrc location = /...''", che legge i dati da un file. | ||
+ | |||
+ | '''xxxdemuxer''': un ''demuxer'' - la maggior parte, ma non tutti, i media vengono commutati e miscelati in una sorta di formato contenitore. Ad esempio, si può avere l'audio Ogg/Vorbis e il video Ogg/Theora messi insieme in un contenitore Matroska (mkv). Il demuxer "rimuove" il contenitore, rendendo disponibili i suoi flussi interni di dati, che sono ancora codificati. | ||
+ | |||
+ | '''xxxdecoder''': un decodificatore - questo è, ad esempio, un decodificatore Vorbis o un decodificatore Theora. È possibile utilizzare lo strumento integrato "''gst-inspect''" per ottenere un elenco di elementi plug-in disponibili e per esaminare le proprietà dei singoli elementi. | ||
+ | |||
+ | '''xxxprocessing''': in generale, dopo aver decodificato i dati di input codificati (audio, video o entrambi) in un tipo di dati non elaborati (che è fondamentalmente un flusso di numeri interi o numeri in virgola mobile, ad esempio uno dei tipi di dati non elaborati audio è PCM ), è possibile eseguire alcune elaborazioni su di esso. L'elaborazione può essere necessaria per cambiarne gli aspetti (modificare la frequenza di campionamento, la risoluzione del video, FPS, ecc.) O potrebbe essere necessario per soddisfare i requisiti degli elementi più avanti lungo la pipeline. | ||
+ | |||
+ | '''xxxencoding''': in generale, dopo aver decodificato ed elaborato i dati grezzi, è necessario codificare i dati non elaborati (audio, video o entrambi) in un formato compresso, indipendentemente dalla compressione senza perdita come l'audio FLAC (per la migliore qualità), o compressione con perdita come MP3 o H264 (per la migliore dimensione del file). | ||
+ | |||
+ | '''xxxmux''': a questo punto che si è in possesso dei bit codificati grezzi nel loro formato compresso, è necessario metterli in una sorta di contenitore. I contenitori sono molto utili, perché possono contenere metadati, come "Titolo", "Autore", "Copyright", "Album", "Anno", ecc., nonché informazioni su quali codec audio e video sono stati usati per codificare i dati . Il Muxer facilita anche il missaggio e l'abbinamento di vari formati di dati. Ci sono alcuni formati di contenitori che sono estremamente flessibili e permettono di comprimere quasi tutti i formati codificati; Matroska è uno di questi esempi, dove è possibile teoricamente mettere l'audio Ogg/Vorbis e il video H264, o il video VP8 e l'audio FLAC. Le possibilità sono tantissime. | ||
+ | |||
+ | '''xxxsink''': questa è la destinazione finale del flusso di dati e della ''Pipeline''. Se si effettua la conversione da un file a un altro file, quasi sempre si utilizzerà il plug-in "''filesink location = /...." . | ||
+ | |||
+ | ====Esempio pratico==== | ||
+ | Qualche esempio pratico di utilizzo della funzione esterna "gst_parse_launch()" di GStreamer, può essere visto alla seguente pagina: | ||
+ | * [[Eseguire un file audio usando una linea di pipeline con la funzione 'gst parse launch()']] |
Versione delle 16:01, 4 lug 2024
Per gestire i dati, al fine di ottenere il risultato ed il fine desiderato: esecuzione sonora, video o altro, bisognerà utilizzare specifiche funzioni, anche finalizzate alla creazione ed all'uso delle funzionalità degli Elementi di GStreamer.
Indice
- 1 Impostare un Elemento per la gestione del flusso dei dati
- 2 Impostare lo stato di un Elemento
- 3 Caricare un file da gestire
- 4 Conoscere la durata del flusso di dati da eseguire
- 5 Conoscere durante l'esecuzione la posizione nel flusso dei dati
- 6 Conocere lo stato dell'Elemento
- 7 Termine e chiusura di GStreamer
- 8 Riassunto essenziale per la Riproduzione audio
- 9 La gestione dei dati audio con GStreamer mediante una Pipeline di elementi
Impostare un Elemento per la gestione del flusso dei dati
Un Elemento è la Classe di oggetti più importante in GStreamer. Esso svolge una determinata funzione, ed è utilizzato per gestire il flusso di dati, come ad esempio lettura, decodifica ed invio dei medesimi alla scheda audio. Di solito si crea una catena di Elementi collegati insieme (Pipeline) e si lascia che i dati passino attraverso questa catena di Elementi. In tal modo è possibile sfruttare le loro funzionalità ed ottenere gli obiettivi multimediali desiderati (come ad esempio la riproduzione audio).
Il modo più semplice per creare un Elemento è utilizzare la funzione:
GstElement * gst_element_factory_make(const gchar *factoryname, const gchar *name)
alla quale si passa il nome di un Elemento fra quelli predisposti da GStreamer ed una denominazione per l'Elemento appena creato. È possibile passare NULL come argomento name per ottenere un unico nome predefinito.
Quando un Elemento viene creato, esso assume un riferimento numerico pari ad un'unità pari al numero di elementi in quel momento creati. Così se ad esempio il nuovo Elemento creato è il secondo, esso assumerà un riferimento numerico uguale a 2.
Detta funzione restituisce una variabile di tipo Puntatore al nuovo Elemento creato, che sarà utilizzata per richiamare appunto quell'Elemento.
Il nuovo Elemento creato con un nome previsto da GStreamer è in grado di gestire solitamente file audio e video, nonché, a seconda dell'Elemento richiamato, altre determinate caratteristiche.
In Gambas dichiareremo la funzione nel seguente modo:
Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer
e la richiameremo in routine ad esempio così:
Private elem As Pointer Public Sub ......() elem = gst_element_factory_make("playbin", "esegui") ......
Eliminare un Elemento
Per eliminare un Elemento, precedentemente creato, si utilizza la funzione:
void gst_object_unref(gpointer object)
alla quale va passata la variabile di tipo Pointer che punta all'Elemento creato.
La distruzione dell'Elemento determina il decremento del riferimento numerico di un'unità.
In Gambas la funzione sarà così dichiarata:
Private Extern gst_object_unref(object As Pointer)
e sarà richiamata in routine ad esempio così:
gst_object_unref(elem)
Impostare lo stato di un Elemento
Per impostare un particolare stato di un Elemento, si utilizzerà la funzione:
GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)
La funzione può ritornare uno dei seguenti valori:
- GST_STATE_CHANGE_FAILURE, uguale a 0, se l'ultimo stato di cambiamento è fallito;
- GST_STATE_CHANGE_SUCCESS, uguale a 1, se l'Elemento non ha stato più attesa e l'ultimo cambiamento di stato è riuscito;
- GST_STATE_CHANGE_ASYNC, uguale a 2, se l'Elemento sta ancora eseguendo un cambiamento di stato;
- GST_STATE_CHANGE_NO_PREROLL, uguale a 3, se il cambiamento di stato è riuscito, ma l'Elemento non è in grado di produrre i dati in GST_STATE_PAUSED.
La funzione in Gambas sarà così dichiarata:
Private Extern gst_element_set_state(gstobject As Pointer, state As Integer) As Integer
Variando il parametro state, si varierà lo stato dell'Elemento di GStreamer. I possibili valori di stato di un Elemento sono:
- GST_STATE_VOID_PENDING = 0 ' nessuno stato sospeso
- GST_STATE_NULL = 1 ' lo stato con valore Null o lo stato iniziale di un "Elemento"
- GST_STATE_READY = 2 ' l'Elemento è "pronto" per essere posto in pausa
- GST_STATE_PAUSED = 3 ' l'Elemento è in "pausa"
- GST_STATE_PLAYING = 4 ' l'Elemento sta eseguendo i dati che fluiscono
Impostare lo stato per la Riproduzione di un flusso di dati
Per poter ottenere la riproduzione di un flusso di dati, ad esempio caricati da un file audio, si imposterà il parametro state con la costante GST_STATE_PLAYING di GStreamer, che equivale al valore 4. Pertanto la predetta funzione sarà in routine impostata:
Private Const GST_STATE_PLAYING As Integer = 4 Public Sub ......() gst_element_set_state(elem, GST_STATE_PLAYING) ......
Richiamata detta funzione, si avrà la riproduzione audio dei dati caricati.
Caricare un file da gestire
Per far gestire (ad esempio farlo eseguire) un file audio, è necessario attribuire detto file come proprietà all'Elemento creato. Si utilizzerà la seguente funzione esterna:
void g_object_set(gpointer object, const gchar *first_property_name, const gchar *value, Null)
laddove in particolare la varibile di tipo Puntatore *value conterrà il percorso del file da gestire.
In Gambas detta funzione sarà così dichiarata:
Private Extern g_object_set(object As Pointer, nomeProprietà As String, value As String, nl As String)
Va precisato che il nom del file va passato con la codifica della Universal Resource Identifiers (URIs). Per trasformare un ordinario indirizzo del file nella sua codifica URI, potremo servirci della funzione esterna:
gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)
che dichiareremo come segue:
Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String
Pertanto avremo in routine ad esempio:
Dim percorsoFile As String percorsoFile = Dialog.Path g_object_set(elem, "nome", g_filename_to_uri(percorsoFile, Null, 0), Null)
Conoscere la durata del flusso di dati da eseguire
Per conoscere la durata del flusso di dati da eseguire, ad esempio la durata di un brano audio, si utilizzerà la funzione esterna:
gboolean gst_element_query_duration(GstElement *element, GstFormat format, gint64 *duration)
laddove il parametro format è un intero che può assumere uno dei seguenti valori da impostare preventivamente a seconda del bisogno:
- GST_FORMAT_UNDEFINED = 0 ' formato indefinito
- GST_FORMAT_DEFAULT = 1 ' il formato di default dell'lemento, che può essere in campioni per l'audio, fotogrammi per il video
- GST_FORMAT_BYTES = 2 ' byte
- GST_FORMAT_TIME = 3 ' nanosecondi
- GST_FORMAT_BUFFERS = 4 ' buffer
- GST_FORMAT_PERCENT = 5 ' percentuale di dati
Il parametro duration è la variabile di tipo Pointer nella quale viene immagazzinata la durata complessiva. Parametro per i ritorni derivanti. Il default è il trasferimento completo. Può assumere il valore 0.
La funzione ritorna un valore booleano True se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata.
In Gambas questa funzione sarà così dichiarata:
Private Extern gst_element_query_duration(gselement As Pointer, formatI As Integer, duration As Pointer) As Boolean
e sarà richiamata in routine ad esempio così:
Dim Dim GST_FORMAT_TIME As Integer = 3 Dim durata As Long gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) Print durata
Conoscere durante l'esecuzione la posizione nel flusso dei dati
Per conoscere la posizione corrente all'interno dei dati da processare, si farà uso della funzione esterna:
gboolean gst_element_query_position(GstElement *element, GstFormat format, gint64 *cur)
laddove il parametro format è un intero che può assumere uno dei seguenti valori da impostare preventivamente a seconda del bisogno:
- GST_FORMAT_UNDEFINED = 0 ' formato indefinito
- GST_FORMAT_DEFAULT = 1 ' il formato di default dell'lemento, che può essere in campioni per l'audio, fotogrammi per il video
- GST_FORMAT_BYTES = 2 ' byte
- GST_FORMAT_TIME = 3 ' nanosecondi
- GST_FORMAT_BUFFERS = 4 ' buffer
- GST_FORMAT_PERCENT = 5 ' percentuale di dati
Il parametro cur è la variabile di tipo Pointer nella quale viene immagazzinata la posizione corrente.
La funzione ritorna un valore booleano True se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata.
In Gambas questa funzione sarà così dichiarata:
Private Extern gst_element_query_position(gselement As Pointer, formatI As Integer, cur As Pointer) As Boolean
e sarà richiamata in routine ad esempio così:
Dim GST_FORMAT_TIME As Integer = 3 Dim pos As Long gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(pos)) Print pos
Conocere lo stato dell'Elemento
Per conoscere lo stato corrente di un Elemento, si utilizzerà la funzione esterna:
GstStateChangeReturn gst_element_get_state(GstElement *element, GstState *state, GstState *pending, GstClockTime timeout)
laddove il parametro state è una variabile di tipo Pointer che punta alla zona di memoria, nella quale è contenuto il valore dello stato corrente dell'Elemento. La funzione può ritornare uno dei seguenti valori:
- GST_STATE_CHANGE_FAILURE, uguale a 0, se l'ultimo stato di cambiamento è fallito;
- GST_STATE_CHANGE_SUCCESS, uguale a 1, se l'elemento non ha stato più attesa e l'ultimo cambiamento di stato è riuscito;
- GST_STATE_CHANGE_ASYNC, uguale a 2, se l'elemento sta ancora eseguendo un cambiamento di stato.
Per gli elementi che non ritornano il valore GST_STATE_CHANGE_ASYNC, questa funzione restituisce immediatamente lo stato attuale e in sospeso.
In Gambas questa funzione sarà così dichiarata:
Private Extern gst_element_get_state(gstobject As Pointer, stateP As Pointer, pendingP As Pointer, timeLout As Long) As Integer
e sarà richiamata in routine ad esempio così:
Dim state, pending As Pointer Dim timeout As Long state = Alloc(SizeOf(gb.Byte), 4) pending = Alloc(SizeOf(gb.Byte), 4) gst_element_get_state(player, state, pending, timeout) Print Int@(state)
Termine e chiusura di GStreamer
Nel caso in cui si intendano chiudere o comunque interrompere le risorse di GStreamer, ad esempio quando si procede alla chiusura del programma, è buona abitudine effettuare la chiusura mediante la funzione:
void gst_object_unref(gpointer object)
precedentementre vista, che eliminerà l'Elemento; nonché la funzione:
GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)
anche questa precedentementre vista, alla quale in Gambas attribuiremo il secondo parametro a Null:
gst_element_set_state(elem, GST_STATE_NULL)
Riassunto essenziale per la Riproduzione audio
In conclusione possiamo dire che bastano solo poche funzioni esterne del API di GStreamer per effettuare la riproduzione di un file audio.
Riportiamo alcuni esempi con applicazioni in ambiente grafico ed applicazione a riga di comando.
Esempio con applicazione in ambiente grafico usando la Classe Timer
Mostriamo di seguito un esempio pratico e funzionante di un'applicazione in ambiente grafico che fa uso della la Classe Timer per consentire l'estrazione della durata totale e del tempo trascorso di esecuzione del file mediale:
Private elem As Pointer Private tempus As Timer Library "libgstreamer-1.0:0.2403.0" Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING Private GST_FORMAT_TIME As Integer = 3 ' gst_init (int *argc, char **argv[]) ' Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins. Private Extern gst_init(argc As Pointer, argv As Pointer) ' GstElement * gst_element_factory_make(const gchar *factoryname, Const gchar * name) ' Create a new element of the type defined by the given element factory. Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer ' gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error) ' Converts an absolute filename to an escaped ASCII-encoded URI. Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String ' void g_object_set(gpointer object, const gchar *first_property_name, ...) ' Sets properties on an object. Private Extern g_object_set(gobject As Pointer, key As String, value As String, tertium As String) ' GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state) ' Sets the state of the element. Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer ' gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration) ' Queries an element for the total stream duration in nanoseconds. Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean ' gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur) ' Queries an element for the stream position in nanoseconds. Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean ' void gst_object_unref(gpointer object) ' Decrements the reference count on object . Private Extern gst_object_unref(gobject As Pointer) Public Sub Form_Open() gst_init(0, 0) With tempus = New Timer As "Tempus" .Delay = 70 End With End Public Sub Button1_Click() ' Avvia la riproduzione del file mediale Dim fileaudio as string elem = gst_element_factory_make("playbin", "Riproduzione") fileaudio = "/percorso/del/file/audio" g_object_set(elem, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) ' Avviamo la riproduzione audio: gst_element_set_state(elem, GST_STATE_PLAYING) tempus.Start End Public Sub Button2_Click() ' Arresta la riproduzione del file mediale tempus.Stop gst_element_set_state(elem, GST_STATE_NULL) gst_object_unref(elem) End Public Sub ToggleButton1_Click() ' Pone in pausa e riprende la riproduzione del file mediale If ToggleButton1.Value Then tempus.Stop gst_element_set_state(elem, GST_STATE_PAUSED) Else gst_element_set_state(elem, GST_STATE_PLAYING) tempus.Start Endif End Public Sub Tempus_Timer() Dim positio, durata As Long gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(positio)) Write #File.Out, "\rDurata: " & Time(0, 0, 0, durata / 1000000) & " - Posizione: " & Time(0, 0, 0, positio / 1000000) If (positio > 0) And (durata = positio) Then tempus.Stop gst_element_set_state(elem, GST_STATE_NULL) gst_object_unref(elem) Endif End
Esempio con applicazione in ambiente grafico usando la funzione Wait
Mostriamo di seguito un esempio pratico e funzionante di un'applicazione in ambiente grafico che fa uso della funzione Wait per consentire l'estrazione della durata totale e del tempo trascorso di esecuzione del file mediale:
Private elem As Pointer Private v As Boolean Library "libgstreamer-1.0:0.2403.0" Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING Private GST_FORMAT_TIME As Integer = 3 ' gst_init (int *argc, char **argv[]) ' Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins. Private Extern gst_init(argc As Pointer, argv As Pointer) ' GstElement * gst_element_factory_make(const gchar *factoryname, Const gchar * name) ' Create a new element of the type defined by the given element factory. Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer ' gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error) ' Converts an absolute filename to an escaped ASCII-encoded URI. Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String ' void g_object_set(gpointer object, const gchar *first_property_name, ...) ' Sets properties on an object. Private Extern g_object_set(gobject As Pointer, key As String, value As String, tertium As String) ' GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state) ' Sets the state of the element. Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer ' gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration) ' Queries an element for the total stream duration in nanoseconds. Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean ' gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur) ' Queries an element for the stream position in nanoseconds. Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean ' void gst_object_unref(gpointer object) ' Decrements the reference count on object . Private Extern gst_object_unref(gobject As Pointer) Public Sub Form_Open() gst_init(0, 0) End Public Sub Button1_Click() ' Avvia la riproduzione del file mediale Dim fileaudio as string Dim durata As Long = 1 Dim positio As Long elem = gst_element_factory_make("playbin", "Riproduzione") fileaudio = "/percorso/del/file/audio" g_object_set(elem, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) ' Avviamo la riproduzione audio: gst_element_set_state(elem, GST_STATE_PLAYING) v = False While (positio < durata) And (v = False) Wait 0.01 gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(positio)) Write #File.Out, "\rDurata: " & Time(0, 0, 0, durata / 1000000) & " - Posizione: " & Time(0, 0, 0, positio / 1000000) Wend gst_element_set_state(elem, GST_STATE_NULL) gst_object_unref(elem) End Public Sub Button2_Click() ' Arresta la riproduzione del file mediale v = True End Public Sub ToggleButton1_Click() ' Pone in pausa e riprende la riproduzione del file mediale If ToggleButton1.Value Then gst_element_set_state(elem, GST_STATE_PAUSED) Else gst_element_set_state(elem, GST_STATE_PLAYING) Endif End
Esempio con applicazione a riga di comando
Mostriamo di seguito un esempio pratico e funzionante di un'applicazione a riga di comando:
Library "libgstreamer-1.0:0.2403.0" Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING Private Const GST_FORMAT_TIME As Integer = 3 ' gst_init (int *argc, char **argv[]) ' Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins. Private Extern gst_init(argc As Pointer, argv As Pointer) ' GstElement * gst_element_factory_make(const gchar *factoryname, Const gchar * name) ' Create a new element of the type defined by the given element factory. Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer ' gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error) ' Converts an absolute filename to an escaped ASCII-encoded URI. Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String ' void g_object_set(gpointer object, const gchar *first_property_name, ...) ' Sets properties on an object. Private Extern g_object_set(gobject As Pointer, key As String, value As String, tertium As String) ' void g_object_set(gpointer object, const gchar *first_property_name, ...) ' Sets properties on an object. Private Extern g_object_set_Volume(gobject As Pointer, key As String, value As Float, tertium As String) Exec "g_object_set" ' GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state) ' Sets the state of the element. Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer ' gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration) ' Queries an element for the total stream duration in nanoseconds. Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean ' gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur) ' Queries an element for the total stream position in nanoseconds. Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean ' void gst_object_unref(gpointer object) ' Decrements the reference count on object . Private Extern gst_object_unref(gobject As Pointer) Public Sub Main() Dim elem As Pointer Dim fileaudio as string Dim durata, pos As Long Dim volume As Float gst_init(0, 0) elem = gst_element_factory_make("playbin", "riproduzione") fileaudio = "/percorso/del/file/audio" g_object_set(elem, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) ' Imposta il valore del volume (da 0.0 a 1.0) di esecuzione: volume = 0.7 g_object_set_Volume(elem, "volume", volume, Null) ' Avvia la riproduzione audio: gst_element_set_state(elem, GST_STATE_PLAYING) Repeat gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) Wait 0.01 Until durata > -1 Repeat gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(pos)) Write "\r\e[0mDurata: " & Time(0, 0, 0, durata / 1000000) & " Pos. \e[31m" & Time(0, 0, 0, pos / 1000000) Wait 0.001 Until pos >= durata gst_object_unref(elem) Print "\nEsecuzione terminata." End
La gestione dei dati audio con GStreamer mediante una Pipeline di elementi
Gstreamer fornisce una potente struttura per consentire agli utenti esperti di gestire flussi audio e video in modi estremamente flessibili.
Gstreamer con tutti i codec abilitati supporta un'enorme varietà di formati di file.
Per creare e gestire "Pipeline" personalizzate di plugin media, è possibile utilizzare il programma integrato "gst-launch" (e più precisamente gst-launch-1.0).
Il formato generale di "Pipeline" di GStreamer da utilizzare è il seguente:
gst-launch-1.0 -v xxxsrc ! xxxdemuxer ! xxxdecoder ! xxxprocessing ! xxxencoding ! xxxmux ! xxxsink
Invece nel codice la corrispondente funzione specifica di Gstreamer è la seguente:
GstElement * gst_parse_launch (const gchar *pipeline_description, GError **error)
Facciamo un elenco di questi plugin in ordine:
xxxsrc: un sorgente di dati audio, da cui provengono i dati di input originari. Un plugin specifico al riguardo è, ad esempio, è "filesrc location = /...", che legge i dati da un file.
xxxdemuxer: un demuxer - la maggior parte, ma non tutti, i media vengono commutati e miscelati in una sorta di formato contenitore. Ad esempio, si può avere l'audio Ogg/Vorbis e il video Ogg/Theora messi insieme in un contenitore Matroska (mkv). Il demuxer "rimuove" il contenitore, rendendo disponibili i suoi flussi interni di dati, che sono ancora codificati.
xxxdecoder: un decodificatore - questo è, ad esempio, un decodificatore Vorbis o un decodificatore Theora. È possibile utilizzare lo strumento integrato "gst-inspect" per ottenere un elenco di elementi plug-in disponibili e per esaminare le proprietà dei singoli elementi.
xxxprocessing: in generale, dopo aver decodificato i dati di input codificati (audio, video o entrambi) in un tipo di dati non elaborati (che è fondamentalmente un flusso di numeri interi o numeri in virgola mobile, ad esempio uno dei tipi di dati non elaborati audio è PCM ), è possibile eseguire alcune elaborazioni su di esso. L'elaborazione può essere necessaria per cambiarne gli aspetti (modificare la frequenza di campionamento, la risoluzione del video, FPS, ecc.) O potrebbe essere necessario per soddisfare i requisiti degli elementi più avanti lungo la pipeline.
xxxencoding: in generale, dopo aver decodificato ed elaborato i dati grezzi, è necessario codificare i dati non elaborati (audio, video o entrambi) in un formato compresso, indipendentemente dalla compressione senza perdita come l'audio FLAC (per la migliore qualità), o compressione con perdita come MP3 o H264 (per la migliore dimensione del file).
xxxmux: a questo punto che si è in possesso dei bit codificati grezzi nel loro formato compresso, è necessario metterli in una sorta di contenitore. I contenitori sono molto utili, perché possono contenere metadati, come "Titolo", "Autore", "Copyright", "Album", "Anno", ecc., nonché informazioni su quali codec audio e video sono stati usati per codificare i dati . Il Muxer facilita anche il missaggio e l'abbinamento di vari formati di dati. Ci sono alcuni formati di contenitori che sono estremamente flessibili e permettono di comprimere quasi tutti i formati codificati; Matroska è uno di questi esempi, dove è possibile teoricamente mettere l'audio Ogg/Vorbis e il video H264, o il video VP8 e l'audio FLAC. Le possibilità sono tantissime.
xxxsink: questa è la destinazione finale del flusso di dati e della Pipeline. Se si effettua la conversione da un file a un altro file, quasi sempre si utilizzerà il plug-in "filesink location = /...." .
Esempio pratico
Qualche esempio pratico di utilizzo della funzione esterna "gst_parse_launch()" di GStreamer, può essere visto alla seguente pagina: