Differenze tra le versioni di "Gestione dei dati media con GStreamer"
Riga 99: | Riga 99: | ||
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 | ||
− | Dim durata | + | Dim durata As Long |
− | |||
− | + | gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata)) | |
− | + | ||
− | + | Print durata | |
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Riga 131: | Riga 123: | ||
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 | ||
− | Dim pos | + | Dim pos As Long |
− | |||
− | + | gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(pos)) | |
− | + | Print pos | |
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
Riga 163: | Riga 149: | ||
pending = Alloc(4) | pending = Alloc(4) | ||
− | + | gst_element_get_state(player, state, pending, timeout) | |
Print Int@(state) | Print Int@(state) | ||
+ | |||
Versione delle 18:00, 10 ago 2015
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
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. Concatenando più Elementi (pipeline) è possibile sfruttare le loro funzionalità ed ottenere gli obiettivi desiderati (come ad esmepio la riproduzione audio) multimediali.
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(element As Pointer, format 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(element As Pointer, format As Integer, curP 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(4) pending = Alloc(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 un esempio pratico funzionante con un'applicazione in ambiente grafico:
Private play As Pointer Library "libgstreamer-1.0" Private Const GST_STATE_NULL As Integer = 1 Private Const GST_STATE_PLAYING As Integer = 4 ' 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(gstobject As Pointer, state As Integer) As Integer ' void gst_object_unref(gpointer object) ' Decrements the reference count on object . Private Extern gst_object_unref(gobject As Pointer) Public Sub Form_Open() Dim fileaudio as string gst_init(0, Null) play = gst_element_factory_make("playbin", "play") fileaudio = "/percorso/del/file/audio" g_object_set(play, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) ' Avviamo la riproduzione audio: gst_element_set_state(play, GST_STATE_PLAYING) End Public Sub Button1_Click() Dim retI As Integer ' Arrestiamo la riproduzione audio: retI = gst_element_set_state(play, GST_STATE_NULL) Print "Stato di cambiamento = "; retI gst_object_unref(play) End
Quet'altro esempio, invece, prevede un'applicazione a riga di comando. Saranno mostrati anche la durata del brano e la posizione temporale corrente durante l'esecuzione:
Library "libgstreamer-1.0" Private Const GST_STATE_NULL As Integer = 1 Private Const GST_FORMAT_TIME As Integer = 3 Private Const GST_STATE_PLAYING As Integer = 4 ' 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 Main() Dim play As Pointer Dim fileaudio as string Dim posizione, durata As Long gst_init(0, Null) play = gst_element_factory_make("playbin", "audio") fileaudio = "/percorso/del/file/audio" g_object_set(play, "uri", g_filename_to_uri(fileaudio, Null, 0), Null) ' Avviamo la riproduzione audio: gst_element_set_state(play, GST_STATE_PLAYING) While (posizione = 0) Or (durata > posizione) gst_element_query_duration(play, GST_FORMAT_TIME, VarPtr(durata)) gst_element_query_position(play, GST_FORMAT_TIME, VarPtr(posizione)) Write #File.Out, "\rDurata: " & Date(0, 0, 0, 0, 0, 0, durata / 1000000) & " Pos. " & Date(0, 0, 0, 0, 0, 0, posizione / 1000000) Wend gst_object_unref(play) End