[gthumb] video viewer: fixed screenshot when using the opengl backend



commit 473d9d3d8a5047bac76c36e9c3283569dcbe48cd
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Dec 31 10:21:01 2018 +0100

    video viewer: fixed screenshot when using the opengl backend

 extensions/gstreamer_utils/gstreamer-utils.c | 105 ++++++++++++++++++++-------
 1 file changed, 79 insertions(+), 26 deletions(-)
---
diff --git a/extensions/gstreamer_utils/gstreamer-utils.c b/extensions/gstreamer_utils/gstreamer-utils.c
index cf1ce49c..d1f5e972 100644
--- a/extensions/gstreamer_utils/gstreamer-utils.c
+++ b/extensions/gstreamer_utils/gstreamer-utils.c
@@ -42,6 +42,7 @@
 
 #include <config.h>
 #include <gst/gst.h>
+#include <gst/video/video.h>
 #include <gthumb.h>
 #include "gstreamer-utils.h"
 
@@ -682,62 +683,113 @@ _gst_playbin_get_current_frame (GstElement          *playbin,
                                gpointer             user_data)
 {
        ScreenshotData *data;
-       GstCaps        *to_caps;
+       GstElement     *sink;
        GstSample      *sample;
        GstCaps        *sample_caps;
+       const char     *format;
        GstStructure   *s;
-       int             outwidth;
-       int             outheight;
+       int             width;
+       int             height;
 
        data = g_new0 (ScreenshotData, 1);
        data->cb = cb;
        data->user_data = user_data;
 
-       /* our desired output format (RGB24) */
-       to_caps = gst_caps_new_simple ("video/x-raw",
-                                      "format", G_TYPE_STRING, "RGB",
-                                      /* Note: we don't ask for a specific width/height here, so that
-                                       * videoscale can adjust dimensions from a non-1/1 pixel aspect
-                                       * ratio to a 1/1 pixel-aspect-ratio. We also don't ask for a
-                                       * specific framerate, because the input framerate won't
-                                       * necessarily match the output framerate if there's a deinterlacer
-                                       * in the pipeline. */
-                                      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
-                                      NULL);
-
-       /* get frame */
+       sink = gst_bin_get_by_name (GST_BIN(playbin), "sink");
+       if (sink == NULL) {
+               g_warning ("Could not take screenshot: %s", "no sink on playbin");
+               screenshot_data_finalize (data);
+               return FALSE;
+       }
+
        sample = NULL;
-       g_signal_emit_by_name (playbin, "convert-sample", to_caps, &sample);
-       gst_caps_unref (to_caps);
+       g_object_get (sink, "last-sample", &sample, NULL);
+       g_object_unref (sink);
 
        if (sample == NULL) {
-               g_warning ("Could not take screenshot: %s", "failed to retrieve or convert video frame");
+               g_warning ("Could not take screenshot: %s", "failed to retrieve video frame");
+               screenshot_data_finalize (data);
+               return FALSE;
+       }
+
+       sample_caps = gst_sample_get_caps (sample);
+       if (sample_caps == NULL) {
+               g_warning ("Could not take screenshot: %s", "no caps on output buffer");
                screenshot_data_finalize (data);
                return FALSE;
        }
 
+       s = gst_caps_get_structure (sample_caps, 0);
+       format = gst_structure_get_string (s, "format");
+
+       /*g_print ("cap: %s\n", gst_caps_to_string (sample_caps));
+       g_print ("format: %s\n", format);*/
+
+       if ((g_strcmp0 (format, "RGB") != 0) && (g_strcmp0 (format, "RGBA") != 0)) {
+               GstCaps   *to_caps;
+               GstSample *to_sample;
+               GError    *error = NULL;
+
+               /* our desired output format (RGB24) */
+               to_caps = gst_caps_new_simple ("video/x-raw",
+                                              "format", G_TYPE_STRING, "RGB",
+                                              /* Note: we don't ask for a specific width/height here, so that
+                                               * videoscale can adjust dimensions from a non-1/1 pixel aspect
+                                               * ratio to a 1/1 pixel-aspect-ratio. We also don't ask for a
+                                               * specific framerate, because the input framerate won't
+                                               * necessarily match the output framerate if there's a 
deinterlacer
+                                               * in the pipeline. */
+                                              "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
+                                              NULL);
+               to_sample = gst_video_convert_sample (sample, to_caps, GST_CLOCK_TIME_NONE, &error);
+
+               gst_caps_unref (to_caps);
+               gst_sample_unref (sample);
+
+               if (to_sample == NULL) {
+                       g_warning ("Could not take screenshot: %s", (error != NULL) ? error->message : 
"failed to convert video frame");
+                       g_clear_error (&error);
+                       screenshot_data_finalize (data);
+                       return FALSE;
+               }
+
+               sample = to_sample;
+       }
+
        sample_caps = gst_sample_get_caps (sample);
        if (sample_caps == NULL) {
                g_warning ("Could not take screenshot: %s", "no caps on output buffer");
+               screenshot_data_finalize (data);
                return FALSE;
        }
 
+       /*g_print ("cap: %s\n", gst_caps_to_string (sample_caps));*/
+
        s = gst_caps_get_structure (sample_caps, 0);
-       gst_structure_get_int (s, "width", &outwidth);
-       gst_structure_get_int (s, "height", &outheight);
-       if ((outwidth > 0) && (outheight > 0)) {
+       gst_structure_get_int (s, "width", &width);
+       gst_structure_get_int (s, "height", &height);
+       format = gst_structure_get_string (s, "format");
+
+       if ((g_strcmp0 (format, "RGB") != 0) && (g_strcmp0 (format, "RGBA") != 0)) {
+               g_warning ("Could not take screenshot: %s", "wrong format");
+               screenshot_data_finalize (data);
+               return FALSE;
+       }
+
+       if ((width > 0) && (height > 0)) {
                GstMemory  *memory;
                GstMapInfo  info;
+               gboolean    with_alpha = (g_strcmp0 (format, "RGBA") == 0);
 
                memory = gst_buffer_get_memory (gst_sample_get_buffer (sample), 0);
                if (gst_memory_map (memory, &info, GST_MAP_READ))
                        data->pixbuf = gdk_pixbuf_new_from_data (info.data,
                                                                 GDK_COLORSPACE_RGB,
-                                                                FALSE,
+                                                                with_alpha,
                                                                 8,
-                                                                outwidth,
-                                                                outheight,
-                                                                GST_ROUND_UP_4 (outwidth * 3),
+                                                                width,
+                                                                height,
+                                                                GST_ROUND_UP_4 (width * (with_alpha ? 4 : 
3)),
                                                                 destroy_pixbuf,
                                                                 sample);
 
@@ -747,6 +799,7 @@ _gst_playbin_get_current_frame (GstElement          *playbin,
        if (data->pixbuf == NULL)
                g_warning ("Could not take screenshot: %s", "could not create pixbuf");
 
+       gst_sample_unref (sample);
        screenshot_data_finalize (data);
 
        return TRUE;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]