totem r5462 - in trunk: . src src/backend



Author: hadess
Date: Tue Jun 10 21:16:49 2008
New Revision: 5462
URL: http://svn.gnome.org/viewvc/totem?rev=5462&view=rev

Log:
2008-06-10  Bastien Nocera  <hadess hadess net>

	* configure.in: Require gstreamer-tag as well
	* src/backend/bacon-video-widget.h:
	* src/backend/bacon-video-widget-gst-0.10.c
	(bacon_video_widget_get_metadata_pixbuf),
	(bacon_video_widget_get_best_image),
	(bacon_video_widget_get_metadata): Add code to read covers from
	video and audio files, through the tags
	* src/backend/bacon-video-widget-xine.c
	(bacon_video_widget_get_metadata): Implement stubs of the above
	* src/totem-video-thumbnailer.c (capture_interesting_frame),
	(capture_frame_at_time), (has_audio), (on_got_metadata_event),
	(main): Implement saving the cover of a video/audio file
	(Closes: #318748)



Modified:
   trunk/ChangeLog
   trunk/src/backend/bacon-video-widget-gst-0.10.c
   trunk/src/backend/bacon-video-widget-xine.c
   trunk/src/backend/bacon-video-widget.h
   trunk/src/totem-video-thumbnailer.c

Modified: trunk/src/backend/bacon-video-widget-gst-0.10.c
==============================================================================
--- trunk/src/backend/bacon-video-widget-gst-0.10.c	(original)
+++ trunk/src/backend/bacon-video-widget-gst-0.10.c	Tue Jun 10 21:16:49 2008
@@ -50,6 +50,9 @@
 /* for missing decoder/demuxer detection */
 #include <gst/pbutils/pbutils.h>
 
+/* for the cover metadata info */
+#include <gst/tag/tag.h>
+
 /* system */
 #include <unistd.h>
 #include <time.h>
@@ -4568,6 +4571,67 @@
   gst_object_unref (bus);
 }
 
+static GdkPixbuf *
+bacon_video_widget_get_metadata_pixbuf (BaconVideoWidget * bvw,
+					GstBuffer *buffer)
+{
+  GdkPixbufLoader *loader;
+  GdkPixbuf *pixbuf;
+
+  loader = gdk_pixbuf_loader_new ();
+  if (!gdk_pixbuf_loader_write (loader, buffer->data, buffer->size, NULL)) {
+    g_object_unref (loader);
+    return NULL;
+  }
+  if (!gdk_pixbuf_loader_close (loader, NULL)) {
+    g_object_unref (loader);
+    return NULL;
+  }
+
+  pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+  if (pixbuf)
+    g_object_ref (pixbuf);
+  g_object_unref (loader);
+  return pixbuf;
+}
+
+static const GValue *
+bacon_video_widget_get_best_image (BaconVideoWidget *bvw)
+{
+  const GValue *cover_value;
+  guint i;
+
+  for (i = 0; ; i++) {
+    const GValue *value;
+    GstBuffer *buffer;
+    GstStructure *caps_struct;
+    int type;
+
+    value = gst_tag_list_get_value_index (bvw->priv->tagcache,
+					  GST_TAG_IMAGE,
+					  i);
+    if (value == NULL)
+      break;
+
+    buffer = gst_value_get_buffer (value);
+
+    caps_struct = gst_caps_get_structure (buffer->caps, 0);
+    gst_structure_get_enum (caps_struct,
+			    "image-type",
+			    GST_TYPE_TAG_IMAGE_TYPE,
+			    &type);
+    if (type == GST_TAG_IMAGE_TYPE_UNDEFINED) {
+      if (cover_value == NULL)
+        cover_value = value;
+    } else if (type == GST_TAG_IMAGE_TYPE_FRONT_COVER) {
+      cover_value = value;
+      break;
+    }
+  }
+
+  return cover_value;
+}
+
 void
 bacon_video_widget_get_metadata (BaconVideoWidget * bvw,
                                  BaconVideoWidgetMetadataType type,
@@ -4603,6 +4667,31 @@
     case BVW_INFO_HAS_AUDIO:
       bacon_video_widget_get_metadata_bool (bvw, type, value);
       break;
+    case BVW_INFO_COVER:
+      {
+        const GValue *cover_value;
+
+	g_value_init (value, GDK_TYPE_PIXBUF);
+
+        if (bvw->priv->tagcache == NULL)
+          break;
+        cover_value = bacon_video_widget_get_best_image (bvw);
+	if (!cover_value) {
+	  cover_value = gst_tag_list_get_value_index (bvw->priv->tagcache,
+						      GST_TAG_PREVIEW_IMAGE,
+						      0);
+	}
+	if (cover_value) {
+	  GstBuffer *buffer;
+	  GdkPixbuf *pixbuf;
+
+	  buffer = gst_value_get_buffer (cover_value);
+	  pixbuf = bacon_video_widget_get_metadata_pixbuf (bvw, buffer);
+	  if (pixbuf)
+	    g_value_take_object (value, pixbuf);
+	}
+      }
+      break;
     default:
       g_return_if_reached ();
     }

Modified: trunk/src/backend/bacon-video-widget-xine.c
==============================================================================
--- trunk/src/backend/bacon-video-widget-xine.c	(original)
+++ trunk/src/backend/bacon-video-widget-xine.c	Tue Jun 10 21:16:49 2008
@@ -4032,6 +4032,8 @@
 	case BVW_INFO_HAS_AUDIO:
 		bacon_video_widget_get_metadata_bool (bvw, type, value);
 		break;
+	case BVW_INFO_COVER:
+		break;
 	default:
 		g_assert_not_reached ();
 	}

Modified: trunk/src/backend/bacon-video-widget.h
==============================================================================
--- trunk/src/backend/bacon-video-widget.h	(original)
+++ trunk/src/backend/bacon-video-widget.h	Tue Jun 10 21:16:49 2008
@@ -199,6 +199,7 @@
 	BVW_INFO_ALBUM,
 	BVW_INFO_DURATION,
 	BVW_INFO_TRACK_NUMBER,
+	BVW_INFO_COVER,
 	/* Video */
 	BVW_INFO_HAS_VIDEO,
 	BVW_INFO_DIMENSION_X,

Modified: trunk/src/totem-video-thumbnailer.c
==============================================================================
--- trunk/src/totem-video-thumbnailer.c	(original)
+++ trunk/src/totem-video-thumbnailer.c	Tue Jun 10 21:16:49 2008
@@ -57,6 +57,11 @@
 static gint64 second_index = -1;
 static char **filenames = NULL;
 
+typedef struct {
+	const char *output;
+	const char *input;
+} callback_data;
+
 #ifdef THUMB_DEBUG
 static void
 show_pixbuf (GdkPixbuf *pix)
@@ -326,7 +331,9 @@
 }
 
 static GdkPixbuf *
-capture_interesting_frame (BaconVideoWidget * bvw, char *input, char *output) 
+capture_interesting_frame (BaconVideoWidget *bvw,
+			   const char *input,
+			   const char *output) 
 {
 	GdkPixbuf* pixbuf;
 	guint current;
@@ -343,9 +350,9 @@
 	 * interesting frame */
 	for (current = 0; current < G_N_ELEMENTS(frame_locations); current++)
 	{
-		PROGRESS_DEBUG("About to seek to %f\n", frame_locations[current]);
+		PROGRESS_DEBUG("About to seek to %f", frame_locations[current]);
 		if (bacon_video_widget_seek (bvw, frame_locations[current], NULL) == FALSE) {
-			PROGRESS_DEBUG("Couldn't seek to %f\n", frame_locations[current]);
+			PROGRESS_DEBUG("Couldn't seek to %f", frame_locations[current]);
 			bacon_video_widget_play (bvw, NULL);
 		}
 
@@ -362,10 +369,10 @@
 		}
 
 		/* Pull the frame, if it's interesting we bail early */
-		PROGRESS_DEBUG("About to get frame for iter %d\n", current);
+		PROGRESS_DEBUG("About to get frame for iter %d", current);
 		pixbuf = bacon_video_widget_get_current_frame (bvw);
 		if (pixbuf != NULL && is_image_interesting (pixbuf) != FALSE) {
-			PROGRESS_DEBUG("Frame for iter %d is interesting\n", current);
+			PROGRESS_DEBUG("Frame for iter %d is interesting", current);
 			break;
 		}
 
@@ -377,13 +384,16 @@
 				pixbuf = NULL;
 			}
 		}
-		PROGRESS_DEBUG("Frame for iter %d was not interesting\n", current);
+		PROGRESS_DEBUG("Frame for iter %d was not interesting", current);
 	}
 	return pixbuf;
 }
 
 static GdkPixbuf *
-capture_frame_at_time(BaconVideoWidget *bvw, char *input, char *output,  gint64 seconds) 
+capture_frame_at_time(BaconVideoWidget *bvw,
+		      const char *input,
+		      const char *output,
+		      gint64 seconds) 
 {
 	GError *err = NULL;
 
@@ -412,6 +422,42 @@
 	return bacon_video_widget_get_current_frame (bvw);
 }
 
+static gboolean
+has_audio (BaconVideoWidget *bvw)
+{
+	GValue value = { 0, };
+
+	bacon_video_widget_get_metadata (bvw, BVW_INFO_HAS_VIDEO, &value);
+	return g_value_get_boolean (&value);
+}
+
+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_get_object (&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_audio (bvw) == FALSE) {
+		PROGRESS_DEBUG("No covers, and no video, exiting");
+		exit (0);
+	}
+}
+
 static const GOptionEntry entries[] = {
 	{ "jpeg", 'j',  0, G_OPTION_ARG_NONE, &jpeg_output, "Output the thumbnail as a JPEG instead of PNG", NULL },
 	{ "size", 's', 0, G_OPTION_ARG_INT, &output_size, "Size of the thumbnail in pixels", NULL },
@@ -432,7 +478,8 @@
 	GError *err = NULL;
 	BaconVideoWidget *bvw;
 	GdkPixbuf *pixbuf;
-	char *input, *output;
+	const char *input, *output;
+	callback_data data;
 
 #ifdef G_OS_UNIX
 	nice (20);
@@ -456,7 +503,6 @@
 		return 1;
 	}
 
-#ifndef THUMB_DEBUG
 	if (g_fatal_warnings) {
 		GLogLevelFlags fatal_mask;
 
@@ -464,7 +510,6 @@
 		fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
 		g_log_set_always_fatal (fatal_mask);
 	}
-#endif /* THUMB_DEBUG */
 
 	if (filenames == NULL || g_strv_length (filenames) != 2) {
 		char *help;
@@ -476,7 +521,7 @@
 	input = filenames[0];
 	output = filenames[1];
 
-	PROGRESS_DEBUG("Initialised libraries, about to create video widget\n");
+	PROGRESS_DEBUG("Initialised libraries, about to create video widget");
 
 	bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (-1, -1, BVW_USE_TYPE_CAPTURE, &err));
 	if (err != NULL) {
@@ -485,13 +530,18 @@
 		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\n");
+	PROGRESS_DEBUG("Video widget created");
 
 	if (time_limit != FALSE)
 		totem_resources_monitor_start (input, 0);
 
-	PROGRESS_DEBUG("About to open video file\n");
+	PROGRESS_DEBUG("About to open video file");
 
 	if (bacon_video_widget_open (bvw, input, &err) == FALSE) {
 		g_print ("totem-video-thumbnailer couldn't open file '%s'\n"
@@ -501,8 +551,8 @@
 		exit (1);
 	}
 
-	PROGRESS_DEBUG("Opened video file: '%s'\n", input);
-	PROGRESS_DEBUG("About to play file\n");
+	PROGRESS_DEBUG("Opened video file: '%s'", input);
+	PROGRESS_DEBUG("About to play file");
 
 	bacon_video_widget_play (bvw, &err);
 	if (err != NULL) {
@@ -511,8 +561,7 @@
 		g_error_free (err);
 		exit (1);
 	}
-
-	PROGRESS_DEBUG("Started playing file\n");
+	PROGRESS_DEBUG("Started playing file");
 
 	/* 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
@@ -533,7 +582,7 @@
 		exit (1);
 	}
 
-	PROGRESS_DEBUG("Saving captured screenshot\n");
+	PROGRESS_DEBUG("Saving captured screenshot");
 	save_pixbuf (pixbuf, output, input, output_size, FALSE);
 	g_object_unref (pixbuf);
 



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