Differenze tra le versioni di "Estrarre un'immagine da un file video con le funzioni esterne del API di GStreamer"
Da Gambas-it.org - Wikipedia.
Riga 111: | Riga 111: | ||
uri = "file://" & "<FONT Color=gray>''/percorso/del/file/fideo''</font>" | uri = "file://" & "<FONT Color=gray>''/percorso/del/file/fideo''</font>" | ||
− | caps = "\x22video/x-raw,format=RGB,width=480,pixel-aspect-ratio=1/1\x22" | + | caps = "\x22video/x-raw,format=RGB,width=640,height=480,pixel-aspect-ratio=1/1\x22" |
imagen = "<FONT Color=gray>''/percorso/del/file.png''</font>" | imagen = "<FONT Color=gray>''/percorso/del/file.png''</font>" |
Versione delle 17:12, 26 ago 2022
La risorsa GStreamer consente anche di estrarre fotogrammi da un file video e salvarli come file immagine.
Sarà necessario avere installata nel sistema e richiamare nell'applicazione Gambas la librerie condivise:
- libgstreamer-1.0
- libgdk_pixbuf-2.0.so.0.4000.0
Mostriamo un esempio, nel quale sarà creato un file immagine di tipo .png da un fotogramma di un file video:
Library "libgstreamer-1.0" Public Struct GstMapInfo GstMemory As Pointer flags As Integer data As Pointer size As Long maxsize As Long End Struct Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING Private Enum GST_STATE_CHANGE_FAILURE = 0, GST_STATE_CHANGE_SUCCESS, GST_STATE_CHANGE_ASYNC, GST_STATE_CHANGE_NO_PREROLL Private Const GST_SECOND As Long = 1000000000 Private Const GST_FORMAT_TIME As Integer = 3 Private Const GST_SEEK_FLAG_FLUSH As Integer = 1 Private Const GST_SEEK_FLAG_KEY_UNIT As Integer = 4 Private Const GST_MAP_READ As Integer = 1 Private Const GDK_COLORSPACE_RGB As Integer = 0 ' 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_parse_launch (const gchar *pipeline_description, GError **error) ' Create a new pipeline based on command line syntax. Private Extern gst_parse_launch(description As String, GError As Pointer) As Pointer ' GstElement * gst_bin_get_by_name (GstBin *bin, const gchar *name) ' Gets the element with the given name from a bin. Private Extern gst_bin_get_by_name(bin As Pointer, name As String) As Pointer ' GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state) ' Sets the state of the element. Private Extern gst_element_set_state(element As Pointer, state As Integer) As Integer ' GstStateChangeReturn gst_element_get_state (GstElement *element, GstState *state, GstState *pending, GstClockTime timeout) ' Gets the state of the element. Private Extern gst_element_get_state(element As Pointer, state As Pointer, pending As Pointer, timeout As Long) As Integer ' gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration) ' Queries an element (usually top-level pipeline or playbin element) for the total stream duration in nanoseconds. Private Extern gst_element_query_duration(element As Pointer, GstFormat As Integer, duration As Pointer) As Boolean ' gboolean gst_element_seek_simple (GstElement *element, GstFormat format, GstSeekFlags seek_flags, gint64 seek_pos) ' Simple API to perform a seek on the given element. Private Extern gst_element_seek_simple(element As Pointer, GstFormat As Integer, seek_flags As Integer, seek_pos As Long) As Boolean ' void g_signal_emit_by_name (gpointer instance, const gchar *detailed_signal, ...) ' Emits a signal. Private Extern g_signal_emit_by_name(instance As Pointer, detailed_signal As String, GstSample As Pointer) ' GstCaps * gst_sample_get_caps (GstSample *sample) ' Get the caps associated with sample. Private Extern gst_sample_get_caps(GstSample As Pointer) As Pointer ' GstStructure * gst_caps_get_structure (const GstCaps *caps, guint index) ' Finds the structure in caps that has the index index , and returns it. Private Extern gst_caps_get_structure(GstCaps As Pointer, index As Integer) As Pointer ' gboolean gst_structure_get_int (const GstStructure *structure, const gchar *fieldname, gint *value) ' Sets the int pointed to by value corresponding to the value of the given field. Private Extern gst_structure_get_int(structure As Pointer, fieldname As String, value As Pointer) As Boolean ' GstBuffer * gst_sample_get_buffer (GstSample *sample) ' Get the buffer associated with sample. Private Extern gst_sample_get_buffer(GstSample As Pointer) As Pointer ' gboolean gst_buffer_map (GstBuffer *buffer, GstMapInfo *info, GstMapFlags flags) ' Fills info with the GstMapInfo of all merged memory blocks in buffer. Private Extern gst_buffer_map(GstBuffer As Pointer, info As GstMapInfo, flags As Integer) As Boolean ' void gst_buffer_unmap (GstBuffer *buffer, GstMapInfo *info) ' Release the memory previously mapped with gst_buffer_map(). Private Extern gst_buffer_unmap(GstBuffer As Pointer, info As GstMapInfo) ' void gst_object_unref(gpointer object) ' Decrements the reference count on object. Private Extern gst_object_unref(gobject As Pointer) Library "libgdk_pixbuf-2.0:0.4000.0" ' GdkPixbuf * gdk_pixbuf_new_from_data (const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data) ' Creates a new GdkPixbuf out of in-memory image data. Private Extern gdk_pixbuf_new_from_data(data As GstMapInfo, colorspace As Integer, has_alpha As Boolean, bits_per_sample As Integer, width As Integer, height As Integer, rowstride As Integer, destroy_fn As Pointer, destroy_fn_data As Pointer) As Pointer ' gboolean gdk_pixbuf_save (GdkPixbuf *pixbuf, const char *filename, const char *type, GError **error, ...) ' Saves pixbuf to a file in format type. By default, "jpeg", "png", "ico" and "bmp" are possible file formats to save in. Private Extern gdk_pixbuf_save(GdkPixbuf As Pointer, filename As String, type As String, GError As Pointer, altro As String) As Boolean Public Sub Main() Dim uri, caps, linea, imagen As String Dim pipeline, sink, sample As Pointer Dim capsP, s, buffer, pixbuf As Pointer Dim rit, width, height As Integer Dim dur, pos As Long Dim tempus As Float Dim bo As Boolean Dim map As New GstMapInfo uri = "file://" & "/percorso/del/file/fideo" caps = "\x22video/x-raw,format=RGB,width=640,height=480,pixel-aspect-ratio=1/1\x22" imagen = "/percorso/del/file.png" ' Estrae il fotogramma alla posizione pari al 44,33% dell'intera durata del video: tempus = 44.33 ' Inizializza la libreria Gstreamer: gst_init(0, 0) ' Crea una nuova pipeline: linea = "uridecodebin uri=" & uri & " ! videoconvert ! videoscale ! appsink name=sink caps=" & caps pipeline = gst_parse_launch(linea, s) If pipeline == 0 Then Error.Raise("Impossibile creare una pipeline !") sink = gst_bin_get_by_name(pipeline, "sink") rit = gst_element_set_state(pipeline, GST_STATE_PAUSED) If rit = GST_STATE_CHANGE_FAILURE Then Error.Raise("Impossibile eseguire il file video !") rit = gst_element_get_state(pipeline, 0, 0, 5 * GST_SECOND) If rit = GST_STATE_CHANGE_FAILURE Then Error.Raise("Impossibile eseguire il file video !") ' Ottiene la durata complessiva del video: gst_element_query_duration(pipeline, GST_FORMAT_TIME, VarPtr(dur)) If dur <> -1 Then pos = dur * tempus / 100 Else pos = 1 * GST_SECOND Endif gst_element_seek_simple(pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_KEY_UNIT Or GST_SEEK_FLAG_FLUSH, pos) g_signal_emit_by_name(sink, "pull-preroll", VarPtr(sample)) gst_object_unref(sink) If sample > 0 Then capsP = gst_sample_get_caps(sample) If capsP == 0 Then Error.Raise("Impossibile ottenere il formato del frame !") s = gst_caps_get_structure(capsP, 0) bo = gst_structure_get_int(s, "width", VarPtr(width)) bo = bo Or gst_structure_get_int(s, "height", VarPtr(height)) If bo = False Then Error.Raise("Impossibile ottenere la dimensione del frame !") ' Crea un oggetto "pixmap" dal buffer e lo salva: buffer = gst_sample_get_buffer(sample) gst_buffer_map(buffer, map, GST_MAP_READ) pixbuf = gdk_pixbuf_new_from_data(map.data, GDK_COLORSPACE_RGB, False, 8, width, height, ((width * 3) + 3) Xor 3, Null, Null) If pixbuf == 0 Then Error.Raise("Impossibile creare un nuovo pixbuf dai dati !") gdk_pixbuf_save(pixbuf, imagen, "png", 0, Null) gst_buffer_unmap(buffer, map) Else Error.Raise("Impossibile salvare il file immagine !") Endif ' Va in chiusura: gst_element_set_state(pipeline, GST_STATE_NULL) gst_object_unref(pipeline) End