static void
on_got_metadata_event (BaconVideoWidget *bvw, callback_data *data)
{
	GValue value = { 0, };
	GdkPixbuf *pixbuf;

	PROGRESS_DEBUG("Got metadata, checking if we have a cover");
	bacon_video_widget_get_metadata (bvw, BVW_INFO_COVER, &value);
	pixbuf = g_value_dup_object (&value);
	g_value_unset (&value);

	if (pixbuf) {
		PROGRESS_DEBUG("Saving cover image");

		bacon_video_widget_close (bvw);
		totem_resources_monitor_stop ();
		gtk_widget_destroy (GTK_WIDGET (bvw));

		save_pixbuf (pixbuf, data->output, data->input, output_size, TRUE);
		g_object_unref (pixbuf);

		exit (0);
	} else if (has_video (bvw) == FALSE) {
		PROGRESS_DEBUG("No covers, and no video, exiting");
		exit (0);
	}
}
Example #2
0
int
main (int argc, char *argv[])
{
  ClutterActor   *video;
  GdkPixbuf      *shot = NULL;
  gint            duration;
  CoglHandle      tex_id;
  CoglPixelFormat format;
  gint            size;
  gint            width;
  gint            height; 
  gint            rowstride;
  guchar         *data = NULL;

#ifdef USE_HELIX
  clutter_helix_init (&argc, &argv);
#else
  gst_init (&argc, &argv);
#endif
  clutter_init (&argc, &argv);

  if (argc < 3)
    {
      g_print ("Usage: %s <path to movie file> <output png>\n", argv[0]);
      exit(-1);
    }

  totem_resources_monitor_start (argv[1], 60 * G_USEC_PER_SEC);

#ifdef USE_HELIX
  video = clutter_helix_video_texture_new ();
#else
  video = clutter_gst_video_texture_new ();
#endif

  if (argv[1][0] == '/')
    clutter_media_set_filename(CLUTTER_MEDIA(video), argv[1]);
  else
    clutter_media_set_uri(CLUTTER_MEDIA(video), argv[1]);
  clutter_media_set_volume (CLUTTER_MEDIA(video), 0);
  clutter_media_set_playing (CLUTTER_MEDIA(video), TRUE);

  do {

    while (g_main_context_pending (NULL))
      g_main_context_iteration (NULL, FALSE);

    duration = clutter_media_get_duration (CLUTTER_MEDIA(video));

  } while (duration == 0);

  clutter_actor_realize (video);

  clutter_media_set_position (CLUTTER_MEDIA(video), duration/3);

  do {

    while (g_main_context_pending (NULL))
      g_main_context_iteration (NULL, FALSE);

  } while (clutter_media_get_position (CLUTTER_MEDIA(video)) <= duration/3);

  tex_id = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (video));
  if (tex_id)
    {
      format = cogl_texture_get_format (tex_id);
      size = cogl_texture_get_data (tex_id, format, 0, NULL);
      width = cogl_texture_get_width (tex_id);
      height = cogl_texture_get_height (tex_id);
      rowstride = cogl_texture_get_rowstride (tex_id);
      
      data = (guchar*) g_malloc (sizeof(guchar) * size);
      if (!data)
	g_error ("malloc");;

      cogl_texture_get_data (tex_id, format, rowstride, data);


      shot = gdk_pixbuf_new_from_data (data, 
				       GDK_COLORSPACE_RGB, 
				       FALSE, 
				       8,
				       width, 
				       height, 
				       rowstride, 
				       NULL, 
				       NULL);
      
    }

  totem_resources_monitor_stop ();

  if (shot)
    {
      GdkPixbuf *thumb, *pic;
      gint       x, y, nw, nh, w, h, size;
      
      size = 128;

      /* FIXME swap RGB pixels */

      w = clutter_actor_get_width (video);
      h = clutter_actor_get_height (video);
      
      nh = ( h * size) / w;

      if (nh <= size)
	{
	  nw = size;
	  x = 0;
	  y = (size - nh) / 2;
	}
      else
	{
	  nw  = ( w * size ) / h;
	  nh = size;
	  x = (size - nw) / 2;
	  y = 0;
	}

      thumb = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size);
      gdk_pixbuf_fill (thumb, 0x000000FF);

      pic = gdk_pixbuf_scale_simple (shot, nw, nh, GDK_INTERP_BILINEAR);
      gdk_pixbuf_copy_area  (pic, 0, 0, nw, nh, thumb, x, y);
      
      if (!gdk_pixbuf_save (thumb, argv[2], "png", NULL, NULL))
	{
	  g_error ("%s: Pixbuf save failed\n", argv[0]);
	  exit(-1);
	}

      g_object_unref (shot);
      g_object_unref (thumb);
      g_object_unref (pic);

      exit(0);
    }

  exit (-1);
}
int main (int argc, char *argv[])
{
	GOptionGroup *options;
	GOptionContext *context;
	GError *err = NULL;
	BaconVideoWidget *bvw;
	GdkPixbuf *pixbuf;
	const char *input, *output;
	callback_data data;

	g_thread_init (NULL);

	context = g_option_context_new ("Thumbnail movies");
	options = bacon_video_widget_get_option_group ();
	g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
	g_option_context_add_group (context, options);
#ifndef THUMB_DEBUG
	g_type_init ();
#else
	g_option_context_add_group (context, gtk_get_option_group (TRUE));
#endif

	if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
		g_print ("couldn't parse command-line options: %s\n", err->message);
		g_error_free (err);
		return 1;
	}

#ifdef G_OS_UNIX
	if (time_limit != FALSE) {
		errno = 0;
		if (nice (20) != 20 && errno != 0)
			g_warning ("Couldn't change nice value of process.");
	}
#endif

	if (print_progress) {
		fcntl (fileno (stdout), F_SETFL, O_NONBLOCK);
		setbuf (stdout, NULL);
	}

	if (g_fatal_warnings) {
		GLogLevelFlags fatal_mask;

		fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
		fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
		g_log_set_always_fatal (fatal_mask);
	}

	if (raw_output == FALSE && output_size == -1)
		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);
		g_print ("%s", help);
		g_free (help);
		return 1;
	}
	input = filenames[0];
	output = filenames[1];

	PROGRESS_DEBUG("Initialised libraries, about to create video widget");
	PRINT_PROGRESS (2.0);

	bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (-1, -1, BVW_USE_TYPE_CAPTURE, &err));
	if (err != NULL) {
		g_print ("totem-video-thumbnailer couldn't create the video "
				"widget.\nReason: %s.\n", err->message);
		g_error_free (err);
		exit (1);
	}
	data.input = input;
	data.output = output;
	g_signal_connect (G_OBJECT (bvw), "got-metadata",
			  G_CALLBACK (on_got_metadata_event),
			  &data);

	PROGRESS_DEBUG("Video widget created");
	PRINT_PROGRESS (6.0);

	if (time_limit != FALSE)
		totem_resources_monitor_start (input, 0);

	PROGRESS_DEBUG("About to open video file");

	if (bacon_video_widget_open (bvw, input, NULL, &err) == FALSE) {
		g_print ("totem-video-thumbnailer couldn't open file '%s'\n"
				"Reason: %s.\n",
				input, err->message);
		g_error_free (err);
		exit (1);
	}

	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)
			pixbuf = capture_frame_at_time (bvw, input, output, second_index);
		else
			pixbuf = capture_interesting_frame (bvw, input, output);
		PRINT_PROGRESS (90.0);
	} else {
		/* We're producing a gallery of screenshots from throughout the file */
		pixbuf = create_gallery (bvw, input, output);
	}

	/* Cleanup */
	bacon_video_widget_close (bvw);
	totem_resources_monitor_stop ();
	gtk_widget_destroy (GTK_WIDGET (bvw));
	PRINT_PROGRESS (92.0);

	if (pixbuf == NULL) {
		g_print ("totem-video-thumbnailer couldn't get a picture from "
					"'%s'\n", input);
		exit (1);
	}

	PROGRESS_DEBUG("Saving captured screenshot");
	save_pixbuf (pixbuf, output, input, output_size, FALSE);
	g_object_unref (pixbuf);
	PRINT_PROGRESS (100.0);

	return 0;
}
int
main (int argc,
      char **argv)
{
    FT_Error error;
    FT_Library library;
    FT_Face face;
    GFile *file;
    gint font_size, thumb_size = THUMB_SIZE;
    gchar *thumbstr_utf8 = NULL, *help, *uri;
    gchar **arguments = NULL;
    GOptionContext *context;
    GError *gerror = NULL;
    gchar *contents = NULL;
    gboolean retval, default_thumbstr = TRUE;
    gint rv = 1;
    GdkRGBA white = { 1.0, 1.0, 1.0, 1.0 };
    GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
    cairo_surface_t *surface;
    cairo_t *cr;
    cairo_text_extents_t text_extents;
    cairo_font_face_t *font;
    gchar *str;
    gdouble scale, scale_x, scale_y;

    const GOptionEntry options[] = {
	    { "text", 't', 0, G_OPTION_ARG_STRING, &thumbstr_utf8,
	      N_("Text to thumbnail (default: Aa)"), N_("TEXT") },
	    { "size", 's', 0, G_OPTION_ARG_INT, &thumb_size,
	      N_("Thumbnail size (default: 128)"), N_("SIZE") },
	    { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &arguments,
	      NULL, N_("FONT-FILE OUTPUT-FILE") },
	    { NULL }
    };

    bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    textdomain (GETTEXT_PACKAGE);

    setlocale (LC_ALL, "");

    g_type_init ();

    context = g_option_context_new (NULL);
    g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);

    retval = g_option_context_parse (context, &argc, &argv, &gerror);
    if (!retval) {
	g_printerr ("Error parsing arguments: %s\n", gerror->message);

	g_option_context_free  (context);
	g_error_free (gerror);
        return 1;
    }

    if (!arguments || g_strv_length (arguments) != 2) {
	help = g_option_context_get_help (context, TRUE, NULL);
	g_printerr ("%s", help);

	g_option_context_free (context);
	goto out;
    }

    g_option_context_free (context);

    if (thumbstr_utf8 != NULL)
	default_thumbstr = FALSE;

    error = FT_Init_FreeType (&library);
    if (error) {
	g_printerr("Could not initialise freetype: %s\n", get_ft_error (error));
	goto out;
    }

    totem_resources_monitor_start (arguments[0], 30 * G_USEC_PER_SEC);

    file = g_file_new_for_commandline_arg (arguments[0]);
    uri = g_file_get_uri (file);
    g_object_unref (file);

    face = sushi_new_ft_face_from_uri (library, uri, &contents, &gerror);
    if (gerror) {
	g_printerr ("Could not load face '%s': %s\n", uri,
		    gerror->message);
        g_free (uri);
        g_error_free (gerror);
	goto out;
    }

    g_free (uri);

    if (default_thumbstr) {
        if (check_font_contain_text (face, "Aa"))
            str = g_strdup ("Aa");
        else
            str = build_fallback_thumbstr (face);
    } else {
        str = thumbstr_utf8;
    }

    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                          thumb_size, thumb_size);
    cr = cairo_create (surface);

    gdk_cairo_set_source_rgba (cr, &white);
    cairo_paint (cr);

    font = cairo_ft_font_face_create_for_ft_face (face, 0);
    cairo_set_font_face (cr, font);
    cairo_font_face_destroy (font);

    font_size = thumb_size - 2 * PADDING_VERTICAL;
    cairo_set_font_size (cr, font_size);
    cairo_text_extents (cr, str, &text_extents);

    if ((text_extents.width) > (thumb_size - 2 * PADDING_HORIZONTAL)) {
        scale_x = (gdouble) (thumb_size - 2 * PADDING_HORIZONTAL) / (text_extents.width);
    } else {
        scale_x = 1.0;
    }

    if ((text_extents.height) > (thumb_size - 2 * PADDING_VERTICAL)) {
        scale_y = (gdouble) (thumb_size - 2 * PADDING_VERTICAL) / (text_extents.height);
    } else {
        scale_y = 1.0;
    }

    scale = MIN (scale_x, scale_y);
    cairo_scale (cr, scale, scale);
    cairo_translate (cr, 
                     PADDING_HORIZONTAL - text_extents.x_bearing + (thumb_size - scale * text_extents.width) / 2.0,
                     PADDING_VERTICAL - text_extents.y_bearing + (thumb_size - scale * text_extents.height) / 2.0);

    gdk_cairo_set_source_rgba (cr, &black);
    cairo_show_text (cr, str);
    cairo_destroy (cr);

    cairo_surface_write_to_png (surface, arguments[1]);
    cairo_surface_destroy (surface);

    totem_resources_monitor_stop ();

    error = FT_Done_Face (face);
    if (error) {
	g_printerr("Could not unload face: %s\n", get_ft_error (error));
	goto out;
    }

    error = FT_Done_FreeType (library);
    if (error) {
	g_printerr ("Could not finalize freetype library: %s\n",
		   get_ft_error (error));
	goto out;
    }

    rv = 0; /* success */

  out:

    g_strfreev (arguments);
    g_free (str);
    g_free (contents);

    return rv;
}