[totem] thumbnailer: Remove the --gallery option



commit 66659eac4f0a0b83c6159d2b98c3bf487feee592
Author: Bastien Nocera <hadess hadess net>
Date:   Tue Jul 25 13:35:49 2017 +0200

    thumbnailer: Remove the --gallery option
    
    Or checks that it's never negative for the gallery thumbnailer.

 src/totem-gallery-thumbnailer.c |  135 +-----------------
 src/totem-video-thumbnailer.c   |  299 ++-------------------------------------
 2 files changed, 16 insertions(+), 418 deletions(-)
---
diff --git a/src/totem-gallery-thumbnailer.c b/src/totem-gallery-thumbnailer.c
index c4eedcd..70d797d 100644
--- a/src/totem-gallery-thumbnailer.c
+++ b/src/totem-gallery-thumbnailer.c
@@ -55,7 +55,6 @@
 #define MIN_PROGRESS 10.0
 #define MAX_PROGRESS 90.0
 
-#define BORING_IMAGE_VARIANCE 256.0            /* Tweak this if necessary */
 #define GALLERY_MIN 3                          /* minimum number of screenshots in a gallery */
 #define GALLERY_MAX 30                         /* maximum number of screenshots in a gallery */
 #define GALLERY_HEADER_HEIGHT 66               /* header height (in pixels) for the gallery */
@@ -227,40 +226,6 @@ thumb_app_set_error_handler (ThumbApp *app)
        g_object_unref (bus);
 }
 
-static void
-check_cover_for_stream (ThumbApp   *app,
-                       const char *signal_name)
-{
-       GdkPixbuf *pixbuf;
-       GstTagList *tags = NULL;
-
-       g_signal_emit_by_name (G_OBJECT (app->play), signal_name, 0, &tags);
-
-       if (!tags)
-               return;
-
-       pixbuf = totem_gst_tag_list_get_cover (tags);
-       if (!pixbuf) {
-               gst_tag_list_unref (tags);
-               return;
-       }
-
-       g_debug("Saving cover image to %s", app->output);
-       thumb_app_cleanup (app);
-       save_pixbuf (pixbuf, app->output, app->input, output_size, TRUE);
-       g_object_unref (pixbuf);
-
-       exit (0);
-}
-
-static void
-thumb_app_check_for_cover (ThumbApp *app)
-{
-       g_debug ("Checking whether file has cover");
-       check_cover_for_stream (app, "get-audio-tags");
-       check_cover_for_stream (app, "get-video-tags");
-}
-
 static gboolean
 thumb_app_set_duration (ThumbApp *app)
 {
@@ -434,42 +399,6 @@ thumb_app_seek (ThumbApp *app,
        gst_element_get_state (app->play, NULL, NULL, GST_CLOCK_TIME_NONE);
 }
 
-/* This function attempts to detect images that are mostly solid images
- * It does this by calculating the statistical variance of the
- * black-and-white image */
-static gboolean
-is_image_interesting (GdkPixbuf *pixbuf)
-{
-       /* We're gonna assume 8-bit samples. If anyone uses anything different,
-        * it doesn't really matter cause it's gonna be ugly anyways */
-       int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
-       int height = gdk_pixbuf_get_height(pixbuf);
-       guchar* buffer = gdk_pixbuf_get_pixels(pixbuf);
-       int num_samples = (rowstride * height);
-       int i;
-       float x_bar = 0.0f;
-       float variance = 0.0f;
-
-       /* FIXME: If this proves to be a performance issue, this function
-        * can be modified to perhaps only check 3 rows. I doubt this'll
-        * be a problem though. */
-
-       /* Iterate through the image to calculate x-bar */
-       for (i = 0; i < num_samples; i++) {
-               x_bar += (float) buffer[i];
-       }
-       x_bar /= ((float) num_samples);
-
-       /* Calculate the variance */
-       for (i = 0; i < num_samples; i++) {
-               float tmp = ((float) buffer[i] - x_bar);
-               variance += tmp * tmp;
-       }
-       variance /= ((float) (num_samples - 1));
-
-       return (variance > BORING_IMAGE_VARIANCE);
-}
-
 static GdkPixbuf *
 scale_pixbuf (GdkPixbuf *pixbuf, int size, gboolean is_still)
 {
@@ -553,48 +482,6 @@ capture_frame_at_time (ThumbApp   *app,
 }
 
 static GdkPixbuf *
-capture_interesting_frame (ThumbApp *app)
-{
-       GdkPixbuf* pixbuf;
-       guint current;
-       const double frame_locations[] = {
-               1.0 / 3.0,
-               2.0 / 3.0,
-               0.1,
-               0.9,
-               0.5
-       };
-
-       if (app->duration == -1) {
-               g_debug("Video has no duration, so capture 1st frame");
-               return capture_frame_at_time (app, 0);
-       }
-
-       /* Test at multiple points in the file to see if we can get an
-        * interesting frame */
-       for (current = 0; current < G_N_ELEMENTS(frame_locations); current++)
-       {
-               g_debug("About to seek to %f", frame_locations[current]);
-               thumb_app_seek (app, frame_locations[current] * app->duration);
-
-               /* Pull the frame, if it's interesting we bail early */
-               g_debug("About to get frame for iter %d", current);
-               pixbuf = totem_gst_playbin_get_frame (app->play);
-               if (pixbuf != NULL && is_image_interesting (pixbuf) != FALSE) {
-                       g_debug("Frame for iter %d is interesting", current);
-                       break;
-               }
-
-               /* If we get to the end of this loop, we'll end up using
-                * the last image we pulled */
-               if (current + 1 < G_N_ELEMENTS(frame_locations))
-                       g_clear_object (&pixbuf);
-               g_debug("Frame for iter %d was not interesting", current);
-       }
-       return pixbuf;
-}
-
-static GdkPixbuf *
 cairo_surface_to_pixbuf (cairo_surface_t *surface)
 {
        gint stride, width, height, x, y;
@@ -924,9 +811,6 @@ int main (int argc, char *argv[])
        }
        thumb_app_set_error_handler (&app);
 
-       /* We don't need covers when we're in gallery mode */
-       if (gallery == -1)
-               thumb_app_check_for_cover (&app);
        if (thumb_app_get_has_video (&app) == FALSE) {
                g_debug ("totem-video-thumbnailer couldn't find a video track in '%s'\n", input);
                exit (1);
@@ -936,22 +820,9 @@ int main (int argc, char *argv[])
        g_debug("Opened video file: '%s'", input);
        PRINT_PROGRESS (10.0);
 
-       if (gallery == -1) {
-               /* If the user has told us to use a frame at a specific second
-                * into the video, just use that frame no matter how boring it
-                * is */
-               if (second_index != -1) {
-                       assert_duration (&app);
-                       pixbuf = capture_frame_at_time (&app, second_index * 1000);
-               } else {
-                       pixbuf = capture_interesting_frame (&app);
-               }
-               PRINT_PROGRESS (90.0);
-       } else {
-               assert_duration (&app);
-               /* We're producing a gallery of screenshots from throughout the file */
-               pixbuf = create_gallery (&app);
-       }
+       assert_duration (&app);
+       /* We're producing a gallery of screenshots from throughout the file */
+       pixbuf = create_gallery (&app);
 
        /* Cleanup */
        thumb_app_cleanup (&app);
diff --git a/src/totem-video-thumbnailer.c b/src/totem-video-thumbnailer.c
index b244a11..7d20f16 100644
--- a/src/totem-video-thumbnailer.c
+++ b/src/totem-video-thumbnailer.c
@@ -63,9 +63,6 @@
 #define MAX_PROGRESS 90.0
 
 #define BORING_IMAGE_VARIANCE 256.0            /* Tweak this if necessary */
-#define GALLERY_MIN 3                          /* minimum number of screenshots in a gallery */
-#define GALLERY_MAX 30                         /* maximum number of screenshots in a gallery */
-#define GALLERY_HEADER_HEIGHT 66               /* header height (in pixels) for the gallery */
 #define DEFAULT_OUTPUT_SIZE 256
 
 static gboolean raw_output = FALSE;
@@ -73,7 +70,6 @@ static int output_size = -1;
 static gboolean time_limit = TRUE;
 static gboolean verbose = FALSE;
 static gboolean print_progress = FALSE;
-static gint gallery = -1;
 static gint64 second_index = -1;
 static char **filenames = NULL;
 
@@ -530,9 +526,9 @@ save_pixbuf (GdkPixbuf *pixbuf, const char *path,
        height = gdk_pixbuf_get_height (pixbuf);
        width = gdk_pixbuf_get_width (pixbuf);
 
-       /* If we're outputting a gallery or a raw image without a size,
+       /* If we're outputting a raw image without a size,
         * don't scale the pixbuf or add borders */
-       if (gallery != -1 || (raw_output != FALSE && size == -1))
+       if (raw_output != FALSE && size == -1)
                with_holes = g_object_ref (pixbuf);
        else if (raw_output != FALSE)
                with_holes = scale_pixbuf (pixbuf, size, TRUE);
@@ -614,272 +610,12 @@ capture_interesting_frame (ThumbApp *app)
        return pixbuf;
 }
 
-static GdkPixbuf *
-cairo_surface_to_pixbuf (cairo_surface_t *surface)
-{
-       gint stride, width, height, x, y;
-       guchar *data, *output, *output_pixel;
-
-       /* This doesn't deal with alpha --- it simply converts the 4-byte Cairo ARGB
-        * format to the 3-byte GdkPixbuf packed RGB format. */
-       g_assert (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_RGB24);
-
-       stride = cairo_image_surface_get_stride (surface);
-       width = cairo_image_surface_get_width (surface);
-       height = cairo_image_surface_get_height (surface);
-       data = cairo_image_surface_get_data (surface);
-
-       output = g_malloc (stride * height);
-       output_pixel = output;
-
-       for (y = 0; y < height; y++) {
-               guint32 *row = (guint32*) (data + y * stride);
-
-               for (x = 0; x < width; x++) {
-                       output_pixel[0] = (row[x] & 0x00ff0000) >> 16;
-                       output_pixel[1] = (row[x] & 0x0000ff00) >> 8;
-                       output_pixel[2] = (row[x] & 0x000000ff);
-
-                       output_pixel += 3;
-               }
-       }
-
-       return gdk_pixbuf_new_from_data (output, GDK_COLORSPACE_RGB, FALSE, 8,
-                                        width, height, width * 3,
-                                        (GdkPixbufDestroyNotify) g_free, NULL);
-}
-
-
-static GdkPixbuf *
-create_gallery (ThumbApp *app)
-{
-       GdkPixbuf *screenshot, *pixbuf = NULL;
-       cairo_t *cr;
-       cairo_surface_t *surface;
-       PangoLayout *layout;
-       PangoFontDescription *font_desc;
-       gint64 stream_length, screenshot_interval, pos;
-       guint columns = 3, rows, current_column, current_row, x, y;
-       gint screenshot_width = 0, screenshot_height = 0, x_padding = 0, y_padding = 0;
-       gfloat scale = 1.0;
-       gchar *header_text, *duration_text, *filename;
-       GFile *file;
-
-       /* Calculate how many screenshots we're going to take */
-       stream_length = app->duration;
-
-       /* As a default, we have one screenshot per minute of stream,
-        * but adjusted so we don't have any gaps in the resulting gallery. */
-       if (gallery == 0) {
-               gallery = stream_length / 60000;
-
-               while (gallery % 3 != 0 &&
-                      gallery % 4 != 0 &&
-                      gallery % 5 != 0) {
-                       gallery++;
-               }
-       }
-
-       if (gallery < GALLERY_MIN)
-               gallery = GALLERY_MIN;
-       if (gallery > GALLERY_MAX)
-               gallery = GALLERY_MAX;
-       screenshot_interval = stream_length / gallery;
-
-       /* Put a lower bound on the screenshot interval so we can't enter an infinite loop below */
-       if (screenshot_interval == 0)
-               screenshot_interval = 1;
-
-       PROGRESS_DEBUG ("Producing gallery of %u screenshots, taken at %" G_GINT64_FORMAT " millisecond 
intervals throughout a %" G_GINT64_FORMAT " millisecond-long stream.",
-                       gallery, screenshot_interval, stream_length);
-
-       /* Calculate how to arrange the screenshots so we don't get ones orphaned on the last row.
-        * At this point, only deal with arrangements of 3, 4 or 5 columns. */
-       y = G_MAXUINT;
-       for (x = 3; x <= 5; x++) {
-               if (gallery % x == 0 || x - gallery % x < y) {
-                       y = x - gallery % x;
-                       columns = x;
-
-                       /* Have we found an optimal solution already? */
-                       if (y == x)
-                               break;
-               }
-       }
-
-       rows = ceil ((gfloat) gallery / (gfloat) columns);
-
-       PROGRESS_DEBUG ("Outputting as %u rows and %u columns.", rows, columns);
-
-       /* Take the screenshots and composite them into a pixbuf */
-       current_column = current_row = x = y = 0;
-       for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) {
-               if (pos == stream_length)
-                       screenshot = capture_frame_at_time (app, pos - 1);
-               else
-                       screenshot = capture_frame_at_time (app, pos);
-
-               if (pixbuf == NULL) {
-                       screenshot_width = gdk_pixbuf_get_width (screenshot);
-                       screenshot_height = gdk_pixbuf_get_height (screenshot);
-
-                       /* Calculate a scaling factor so that screenshot_width -> output_size */
-                       scale = (float) output_size / (float) screenshot_width;
-
-                       x_padding = x = MAX (output_size * 0.05, 1);
-                       y_padding = y = MAX (scale * screenshot_height * 0.05, 1);
-
-                       PROGRESS_DEBUG ("Scaling each screenshot by %f.", scale);
-
-                       /* Create our massive pixbuf */
-                       pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
-                                                columns * output_size + (columns + 1) * x_padding,
-                                                (guint) (rows * scale * screenshot_height + (rows + 1) * 
y_padding));
-                       gdk_pixbuf_fill (pixbuf, 0x000000ff);
-
-                       PROGRESS_DEBUG ("Created output pixbuf (%ux%u).", gdk_pixbuf_get_width (pixbuf), 
gdk_pixbuf_get_height (pixbuf));
-               }
-
-               /* Composite the screenshot into our gallery */
-               gdk_pixbuf_composite (screenshot, pixbuf,
-                                     x, y, output_size, scale * screenshot_height,
-                                     (gdouble) x, (gdouble) y, scale, scale,
-                                     GDK_INTERP_BILINEAR, 255);
-               g_object_unref (screenshot);
-
-               PROGRESS_DEBUG ("Composited screenshot from %" G_GINT64_FORMAT " milliseconds (address %u) at 
(%u,%u).",
-                               pos, GPOINTER_TO_UINT (screenshot), x, y);
-
-               /* We print progress in the range 10% (MIN_PROGRESS) to 50% (MAX_PROGRESS - MIN_PROGRESS) / 
2.0 */
-               PRINT_PROGRESS (MIN_PROGRESS + (current_row * columns + current_column) * (((MAX_PROGRESS - 
MIN_PROGRESS) / gallery) / 2.0));
-
-               current_column = (current_column + 1) % columns;
-               x += output_size + x_padding;
-               if (current_column == 0) {
-                       x = x_padding;
-                       y += scale * screenshot_height + y_padding;
-                       current_row++;
-               }
-       }
-
-       PROGRESS_DEBUG ("Converting pixbuf to a Cairo surface.");
-
-       /* Load the pixbuf into a Cairo surface and overlay the text. The height is the height of
-        * the gallery plus the necessary height for 3 lines of header (at ~18px each), plus some
-        * extra padding. */
-       surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, gdk_pixbuf_get_width (pixbuf),
-                                             gdk_pixbuf_get_height (pixbuf) + GALLERY_HEADER_HEIGHT + 
y_padding);
-       cr = cairo_create (surface);
-       cairo_surface_destroy (surface);
-
-       /* First, copy across the gallery pixbuf */
-       gdk_cairo_set_source_pixbuf (cr, pixbuf, 0.0, GALLERY_HEADER_HEIGHT + y_padding);
-       cairo_rectangle (cr, 0.0, GALLERY_HEADER_HEIGHT + y_padding, gdk_pixbuf_get_width (pixbuf), 
gdk_pixbuf_get_height (pixbuf));
-       cairo_fill (cr);
-       g_object_unref (pixbuf);
-
-       /* Build the header information */
-       duration_text = totem_time_to_string (stream_length, FALSE, FALSE);
-       file = g_file_new_for_commandline_arg (app->input);
-       filename = g_file_get_basename (file);
-       g_object_unref (file);
-
-       /* Translators: The first string is "Filename" (as translated); the second is an actual filename.
-                       The third string is "Resolution" (as translated); the fourth and fifth are screenshot 
height and width, respectively.
-                       The sixth string is "Duration" (as translated); the seventh is the movie duration in 
words. */
-       header_text = g_markup_printf_escaped (_("<b>%s</b>: %s\n<b>%s</b>: %d\303\227%d\n<b>%s</b>: %s"),
-                                              _("Filename"),
-                                              filename,
-                                              _("Resolution"),
-                                              screenshot_width,
-                                              screenshot_height,
-                                              _("Duration"),
-                                              duration_text);
-       g_free (duration_text);
-       g_free (filename);
-
-       PROGRESS_DEBUG ("Writing header text with Pango.");
-
-       /* Write out some header information */
-       layout = pango_cairo_create_layout (cr);
-       font_desc = pango_font_description_from_string ("Sans 18px");
-       pango_layout_set_font_description (layout, font_desc);
-       pango_font_description_free (font_desc);
-
-       pango_layout_set_markup (layout, header_text, -1);
-       g_free (header_text);
-
-       cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
-       cairo_move_to (cr, (gdouble) x_padding, (gdouble) y_padding);
-       pango_cairo_show_layout (cr, layout);
-
-       /* Go through each screenshot and write its timestamp */
-       current_column = current_row = 0;
-       x = x_padding + output_size;
-       y = y_padding * 2 + GALLERY_HEADER_HEIGHT + scale * screenshot_height;
-
-       font_desc = pango_font_description_from_string ("Sans 10px");
-       pango_layout_set_font_description (layout, font_desc);
-       pango_font_description_free (font_desc);
-
-       PROGRESS_DEBUG ("Writing screenshot timestamps with Pango.");
-
-       for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) {
-               gchar *timestamp_text;
-               gint layout_width, layout_height;
-
-               timestamp_text = totem_time_to_string (pos, FALSE, FALSE);
-
-               pango_layout_set_text (layout, timestamp_text, -1);
-               pango_layout_get_pixel_size (layout, &layout_width, &layout_height);
-
-               /* Display the timestamp in the bottom-right corner of the current screenshot */
-               cairo_move_to (cr, x - layout_width - 0.02 * output_size, y - layout_height - 0.02 * scale * 
screenshot_height);
-
-               /* We have to stroke the text so it's visible against screenshots of the same
-                * foreground color. */
-               pango_cairo_layout_path (cr, layout);
-               cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
-               cairo_stroke_preserve (cr);
-               cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
-               cairo_fill (cr);
-
-               PROGRESS_DEBUG ("Writing timestamp \"%s\" at (%f,%f).", timestamp_text,
-                               x - layout_width - 0.02 * output_size,
-                               y - layout_height - 0.02 * scale * screenshot_height);
-
-               /* We print progress in the range 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0) to 90% 
(MAX_PROGRESS) */
-               PRINT_PROGRESS (MIN_PROGRESS + (MAX_PROGRESS - MIN_PROGRESS) / 2.0 + (current_row * columns + 
current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0));
-
-               g_free (timestamp_text);
-
-               current_column = (current_column + 1) % columns;
-               x += output_size + x_padding;
-               if (current_column == 0) {
-                       x = x_padding + output_size;
-                       y += scale * screenshot_height + y_padding;
-                       current_row++;
-               }
-       }
-
-       g_object_unref (layout);
-
-       PROGRESS_DEBUG ("Converting Cairo surface back to pixbuf.");
-
-       /* Create a new pixbuf from the Cairo context */
-       pixbuf = cairo_surface_to_pixbuf (cairo_get_target (cr));
-       cairo_destroy (cr);
-
-       return pixbuf;
-}
-
 static const GOptionEntry entries[] = {
-       { "size", 's', 0, G_OPTION_ARG_INT, &output_size, "Size of the thumbnail in pixels (with --gallery 
sets the size of individual screenshots)", NULL },
+       { "size", 's', 0, G_OPTION_ARG_INT, &output_size, "Size of the thumbnail in pixels", NULL },
        { "raw", 'r', 0, G_OPTION_ARG_NONE, &raw_output, "Output the raw picture of the video without scaling 
or adding borders", NULL },
        { "no-limit", 'l', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &time_limit, "Don't limit the 
thumbnailing time to 30 seconds", NULL },
        { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Output debug information", NULL },
-       { "time", 't', 0, G_OPTION_ARG_INT64, &second_index, "Choose this time (in seconds) as the thumbnail 
(can't be used with --gallery)", NULL },
-       { "gallery", 'g', 0, G_OPTION_ARG_INT, &gallery, "Output a gallery of the given number (0 is default) 
of screenshots (can't be used with --time)", NULL },
+       { "time", 't', 0, G_OPTION_ARG_INT64, &second_index, "Choose this time (in seconds) as the 
thumbnail", NULL },
        { "print-progress", 'p', 0, G_OPTION_ARG_NONE, &print_progress, "Only print progress updates (can't 
be used with --verbose)", NULL },
        { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, "[INPUT FILE] [OUTPUT 
FILE]" },
        { NULL }
@@ -927,7 +663,6 @@ int main (int argc, char *argv[])
                output_size = DEFAULT_OUTPUT_SIZE;
 
        if (filenames == NULL || g_strv_length (filenames) != 2 ||
-           (second_index != -1 && gallery != -1) ||
            (print_progress == TRUE && verbose == TRUE)) {
                char *help;
                help = g_option_context_get_help (context, FALSE, NULL);
@@ -961,9 +696,7 @@ int main (int argc, char *argv[])
        }
        thumb_app_set_error_handler (&app);
 
-       /* We don't need covers when we're in gallery mode */
-       if (gallery == -1)
-               thumb_app_check_for_cover (&app);
+       thumb_app_check_for_cover (&app);
        if (thumb_app_get_has_video (&app) == FALSE) {
                PROGRESS_DEBUG ("totem-video-thumbnailer couldn't find a video track in '%s'\n", input);
                exit (1);
@@ -973,22 +706,16 @@ int main (int argc, char *argv[])
        PROGRESS_DEBUG("Opened video file: '%s'", input);
        PRINT_PROGRESS (10.0);
 
-       if (gallery == -1) {
-               /* If the user has told us to use a frame at a specific second
-                * into the video, just use that frame no matter how boring it
-                * is */
-               if (second_index != -1) {
-                       assert_duration (&app);
-                       pixbuf = capture_frame_at_time (&app, second_index * 1000);
-               } else {
-                       pixbuf = capture_interesting_frame (&app);
-               }
-               PRINT_PROGRESS (90.0);
-       } else {
+       /* If the user has told us to use a frame at a specific second
+        * into the video, just use that frame no matter how boring it
+        * is */
+       if (second_index != -1) {
                assert_duration (&app);
-               /* We're producing a gallery of screenshots from throughout the file */
-               pixbuf = create_gallery (&app);
+               pixbuf = capture_frame_at_time (&app, second_index * 1000);
+       } else {
+               pixbuf = capture_interesting_frame (&app);
        }
+       PRINT_PROGRESS (90.0);
 
        /* Cleanup */
        totem_resources_monitor_stop ();


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