[arch-commits] Commit in shotwell/trunk (3 files)

Balló György bgyorgy at nymeria.archlinux.org
Tue Mar 5 07:36:35 UTC 2013


    Date: Tuesday, March 5, 2013 @ 08:36:35
  Author: bgyorgy
Revision: 85689

upgpkg: shotwell 0.13.1-6

Fix thumbnail generation for videos by two upstream patches.

Added:
  shotwell/trunk/regenerate-video-thumbnails.patch
Modified:
  shotwell/trunk/0001-Port-to-GStreamer-1.0.patch
  shotwell/trunk/PKGBUILD

-----------------------------------+
 0001-Port-to-GStreamer-1.0.patch  |  150 ++++++++++++++++++++++++-----------
 PKGBUILD                          |   15 ++-
 regenerate-video-thumbnails.patch |  154 ++++++++++++++++++++++++++++++++++++
 3 files changed, 270 insertions(+), 49 deletions(-)

Modified: 0001-Port-to-GStreamer-1.0.patch
===================================================================
--- 0001-Port-to-GStreamer-1.0.patch	2013-03-05 05:37:06 UTC (rev 85688)
+++ 0001-Port-to-GStreamer-1.0.patch	2013-03-05 07:36:35 UTC (rev 85689)
@@ -1,17 +1,11 @@
-From 9cb0726dd0873e3664f3589aabadea8bb7c8ff37 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= <olivier.crete at collabora.com>
-Date: Tue, 25 Sep 2012 18:15:02 -0400
-Subject: [PATCH] Port to GStreamer 1.0
+From 4db67e385c9c2d89947077f1520aa31af2538d65 Mon Sep 17 00:00:00 2001
+From: Alban Browaeys <prahal at yahoo.com>
+Date: Wed, 09 Jan 2013 01:11:27 +0000
+Subject: Ports Shotwell to GStreamer 1.0. Closes #6055.
 
 ---
- Makefile                                    | 21 +++++++++++----------
- src/VideoSupport.vala                       |  8 ++++----
- src/libshotwell.deps                        |  5 +++--
- thumbnailer/shotwell-video-thumbnailer.vala | 18 ++++++++----------
- 4 files changed, 26 insertions(+), 26 deletions(-)
-
 diff --git a/Makefile b/Makefile
-index 1bd09e0..06059e3 100644
+index 2488f82..5a7e262 100644
 --- a/Makefile
 +++ b/Makefile
 @@ -37,7 +37,7 @@ EXTRAS_SUPPORTED_LANGUAGES=fr de it es pl et sv sk lv pt bg bn nl da zh_CN el ru
@@ -19,7 +13,7 @@
  SYSTEM_LANG_DIR := $(DESTDIR)$(PREFIX)/share/locale
  
 -VALAFLAGS := -g --enable-checking --thread --fatal-warnings --enable-deprecated $(USER_VALAFLAGS)
-+VALAFLAGS := -g --enable-checking --thread --enable-deprecated $(USER_VALAFLAGS)
++VALAFLAGS := -g --enable-checking --thread --fatal-warnings --enable-deprecated --enable-experimental $(USER_VALAFLAGS)
  ifdef UNITY_SUPPORT
  VALAFLAGS := $(VALAFLAGS) --define UNITY_SUPPORT
  endif
@@ -36,19 +30,18 @@
  	gtk+-3.0 \
  	gudev-1.0 \
  	libexif \
-@@ -314,8 +314,9 @@ endif
+@@ -314,8 +314,8 @@ endif
  THUMBNAILER_PKGS = \
      gtk+-3.0 \
      gee-1.0 \
 -    gstreamer-0.10 \
 -    gstreamer-base-0.10
 +    gstreamer-1.0 \
-+    gstreamer-base-1.0 \
-+    gstreamer-app-1.0 \
++    gstreamer-base-1.0
  
  DIRECT_LIBS =
  
-@@ -325,10 +326,10 @@ EXT_PKG_VERSIONS = \
+@@ -325,10 +325,10 @@ EXT_PKG_VERSIONS = \
  	gio-unix-2.0 >= 2.20 \
  	glib-2.0 >= $(MIN_GLIB_VERSION) \
  	gmodule-2.0 >= 2.24.0 \
@@ -63,6 +56,15 @@
  	gtk+-3.0 >= 3.0.11 \
  	gudev-1.0 >= 145 \
  	libexif >= 0.6.16 \
+@@ -683,7 +683,7 @@ $(VALA_STAMP): $(EXPANDED_SRC_FILES) $(EXPANDED_VAPI_FILES) $(GPHOTO_VAPI_FILE)
+ 	$(call check_valac_version)
+ 	@echo Compiling Vala code...
+ 	@mkdir -p $(BUILD_DIR)
+-	@$(VALAC) --ccode --directory=$(BUILD_DIR) --basedir=src \
++	$(VALAC) --ccode --directory=$(BUILD_DIR) --basedir=src \
+ 		$(foreach pkg,$(VALA_PKGS),--pkg=$(pkg)) \
+ 		$(foreach vapidir,$(VAPI_DIRS),--vapidir=$(vapidir)) \
+ 		$(foreach def,$(DEFINES),-X -D$(def)) \
 diff --git a/src/VideoSupport.vala b/src/VideoSupport.vala
 index deb45e2..f679bd0 100644
 --- a/src/VideoSupport.vala
@@ -97,10 +99,10 @@
              message("interpreter state cookie not found; assuming all video thumbnails are out of date");
              interpreter_state_changed = true;
 diff --git a/thumbnailer/shotwell-video-thumbnailer.vala b/thumbnailer/shotwell-video-thumbnailer.vala
-index a4d7dc2..c12784e 100644
+index 79a2d7e..ae1e537 100644
 --- a/thumbnailer/shotwell-video-thumbnailer.vala
 +++ b/thumbnailer/shotwell-video-thumbnailer.vala
-@@ -10,11 +10,7 @@
+@@ -10,22 +10,15 @@
  // Shotwell Thumbnailer takes in a video file and returns a thumbnail to stdout.  This is
  // a replacement for totem-video-thumbnailer
  class ShotwellThumbnailer {
@@ -109,51 +111,109 @@
 -                                      red_mask = (int)   0xFF000000,
 -                                      green_mask = (int) 0x00FF0000,
 -                                      blue_mask = (int)  0x0000FF00,
-+    const string caps_string = """video/x-raw, format=RGBA,
-                                       width = (int) [ 1, max ],
-                                       height = (int) [ 1, max ],
-                                       framerate = (fraction) [ 0, max ]""";
-@@ -36,7 +32,7 @@ class ShotwellThumbnailer {
+-                                      width = (int) [ 1, max ],
+-                                      height = (int) [ 1, max ],
+-                                      framerate = (fraction) [ 0, max ]""";
++    const string caps_string = """video/x-raw,format=RGB,bpp=32,depth=32,pixel-aspect-ratio=1/1""";
+     
+     public static int main(string[] args) {
+         Gst.Element pipeline, sink;
+         int width, height;
+-        Gst.Buffer buffer;
++        Gst.Sample sample;
+         string descr;
+         Gdk.Pixbuf pixbuf;
+-        int64 position;
++        int64 duration, position;
+         Gst.StateChangeReturn ret;
+         bool res;
+         
+@@ -36,7 +29,7 @@ class ShotwellThumbnailer {
              return 1;
          }
          
 -        descr = "filesrc location=\"%s\" ! decodebin2 ! ffmpegcolorspace ! ".printf(args[1]) + 
-+        descr = "filesrc location=\"%s\" ! decodebin ! videoconvert ! ".printf(args[1]) + 
++        descr = "filesrc location=\"%s\" ! decodebin ! videoconvert ! videoscale ! ".printf(args[1]) +
              "appsink name=sink caps=\"%s\"".printf(caps_string);
          
          try {
-@@ -69,7 +65,7 @@ class ShotwellThumbnailer {
-             // by seeking to somewhere else we have a bigger chance of getting something
-             // more interesting. An optimization would be to detect black images and then
-             // seek a little more.
+@@ -64,29 +57,41 @@ class ShotwellThumbnailer {
+                 stderr.printf("Failed to play the file: couldn't get state.\n");
+                 return 3;
+             }
+-            
+-            // Seek to the a position in the file. Most files have a black first frame so
+-            // by seeking to somewhere else we have a bigger chance of getting something
+-            // more interesting. An optimization would be to detect black images and then
+-            // seek a little more.
 -            position = (int64) (Gst.Format.PERCENT_MAX * 0.05);
-+            position = (int64) (Gst.FORMAT_PERCENT_MAX * 0.05);
-             pipeline.seek_simple(Gst.Format.PERCENT, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH , position);
-             
-             // Get the preroll buffer from appsink, this block untils appsink really
-@@ -86,7 +82,7 @@ class ShotwellThumbnailer {
+-            pipeline.seek_simple(Gst.Format.PERCENT, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH , position);
+-            
+-            // Get the preroll buffer from appsink, this block untils appsink really
+-            // prerolls.
+-            GLib.Signal.emit_by_name(sink, "pull-preroll", out buffer, null);
+-            
++
++            /* get the duration */
++            pipeline.query_duration (Gst.Format.TIME, out duration);
++
++            if (duration != -1) {
++                /* we have a duration, seek to 5% */
++                position = duration * 5 / 100;
++            } else {
++                /* no duration, seek to 1 second, this could EOS */
++                position = 1 * Gst.SECOND;
++            }
++
++            /* seek to the a position in the file. Most files have a black first frame so
++             * by seeking to somewhere else we have a bigger chance of getting something
++             * more interesting. An optimisation would be to detect black images and then
++             * seek a little more */
++            pipeline.seek_simple (Gst.Format.TIME, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH, position);
++
++            /* get the preroll buffer from appsink, this block untils appsink really
++             * prerolls */
++            GLib.Signal.emit_by_name (sink, "pull-preroll", out sample, null);
++
+             // if we have a buffer now, convert it to a pixbuf. It's possible that we
+             // don't have a buffer because we went EOS right away or had an error.
+-            if (buffer != null) {
++            if (sample != null) {
++                Gst.Buffer buffer;
+                 Gst.Caps caps;
+                 Gst.Structure s;
++                Gst.MapInfo mapinfo;
+ 
+                 // Get the snapshot buffer format now. We set the caps on the appsink so
                  // that it can only be an rgb buffer. The only thing we have not specified
                  // on the caps is the height, which is dependant on the pixel-aspect-ratio
                  // of the source material.
 -                caps = buffer.get_caps();
-+                caps = (sink as Gst.App.Sink).caps;
++                caps = sample.get_caps();
                  if (caps == null) {
                      stderr.printf("could not get snapshot format\n");
                      return 5;
-@@ -104,9 +100,11 @@ class ShotwellThumbnailer {
-                 
+@@ -101,14 +106,18 @@ class ShotwellThumbnailer {
+                     stderr.printf("Could not get snapshot dimension\n");
+                     return 6;
+                 }
+-                
++
++                buffer = sample.get_buffer();
++                buffer.map(out mapinfo, Gst.MapFlags.READ);
++
                  // Create pixmap from buffer and save, gstreamer video buffers have a stride
                  // that is rounded up to the nearest multiple of 4.
 -                pixbuf = new Gdk.Pixbuf.from_data(buffer.data, Gdk.Colorspace.RGB, true, 8, 
-+		Gst.MapInfo info;
-+		buffer.map(out info, Gst.MapFlags.READ);
-+                pixbuf = new Gdk.Pixbuf.from_data(info.data, Gdk.Colorspace.RGB, true, 8, 
-                     width, height, width * 4, null);
--                
-+                buffer.unmap(info);
+-                    width, height, width * 4, null);
++                pixbuf = new Gdk.Pixbuf.from_data(mapinfo.data, Gdk.Colorspace.RGB, false, 8,
++                    width, height, (((width * 3)+3)&~3), null);
+                 
                  // Save the pixbuf.
                  pixbuf.save("/dev/stdout", "png");
++                buffer.unmap(mapinfo);
              } else {
--- 
-1.7.11.4
-
+                 stderr.printf("Could not make snapshot\n");
+                 return 10;
+--
+cgit v0.9

Modified: PKGBUILD
===================================================================
--- PKGBUILD	2013-03-05 05:37:06 UTC (rev 85688)
+++ PKGBUILD	2013-03-05 07:36:35 UTC (rev 85689)
@@ -5,7 +5,7 @@
 
 pkgname=shotwell
 pkgver=0.13.1
-pkgrel=5
+pkgrel=6
 pkgdesc="A digital photo organizer designed for the GNOME desktop environment"
 arch=('i686' 'x86_64')
 url="http://yorba.org/shotwell/"
@@ -17,19 +17,26 @@
 install=shotwell.install
 source=("http://yorba.org/download/shotwell/0.13/shotwell-${pkgver}.tar.xz"
 	"no-libexec.patch"
-        "0001-Port-to-GStreamer-1.0.patch")
+        "0001-Port-to-GStreamer-1.0.patch"
+        "regenerate-video-thumbnails.patch")
 md5sums=('71eb1346093705ca2b37c12a21994d14'
          'b4124e022c98b4382530e6fbcef965e2'
-         '86e47eade2b5a49bd6503294751d95f0')
+         '666d28c2a1b78632df8ab5f24c3aa3cd'
+         '4b70442c6d9c04f3be23426ef92adb43')
 
 build() {
   cd "${srcdir}/${pkgname}-${pkgver}"
 
   patch -p1 <$srcdir/no-libexec.patch
 
-  # http://redmine.yorba.org/issues/5548
+  # Port to GSreamer 1.0 (video thumbnailer)
+  # http://redmine.yorba.org/issues/6055
   patch -p1 <$srcdir/0001-Port-to-GStreamer-1.0.patch
 
+  # Regenerate video thumbnails on lost
+  # http://redmine.yorba.org/issues/6152
+  patch -p1 <$srcdir/regenerate-video-thumbnails.patch
+
   ./configure --prefix=/usr \
 	--disable-schemas-compile \
 	--disable-desktop-update \

Added: regenerate-video-thumbnails.patch
===================================================================
--- regenerate-video-thumbnails.patch	                        (rev 0)
+++ regenerate-video-thumbnails.patch	2013-03-05 07:36:35 UTC (rev 85689)
@@ -0,0 +1,154 @@
+From 05c10b9c6107dc785808732216498ef5f3f6b87d Mon Sep 17 00:00:00 2001
+From: Clint Rogers <clinton at yorba.org>
+Date: Wed, 16 Jan 2013 00:09:42 +0000
+Subject: Causes video thumbnails to get regenerated if lost; closes #6152.
+
+Also moves some code around so regeneration for both stills and videos happens in the same spot, improving code navigability.
+---
+diff --git a/src/PhotoMonitor.vala b/src/PhotoMonitor.vala
+index 40416d1..3dcc481 100644
+--- a/src/PhotoMonitor.vala
++++ b/src/PhotoMonitor.vala
+@@ -287,16 +287,7 @@ private class PhotoMonitor : MediaMonitor {
+             
+             return MediaMonitor.DiscoveredFile.UNKNOWN;
+         }
+-        
+-        if (!ThumbnailCache.exists(photo)) {
+-            try {
+-                ThumbnailCache.import_from_source(photo, true);
+-                photo.notify_altered(new Alteration("image","thumbnail"));
+-            } catch (Error e) {
+-                // thumbnail for this object was already broken, so nothing got worse.
+-            }
+-        }
+-        
++
+         switch (state) {
+             case LibraryPhotoSourceCollection.State.ONLINE:
+             case LibraryPhotoSourceCollection.State.OFFLINE:
+diff --git a/src/ThumbnailCache.vala b/src/ThumbnailCache.vala
+index be97183..2a2c716 100644
+--- a/src/ThumbnailCache.vala
++++ b/src/ThumbnailCache.vala
+@@ -1,7 +1,7 @@
+-/* Copyright 2009-2012 Yorba Foundation
++/* Copyright 2009-2013 Yorba Foundation
+  *
+  * This software is licensed under the GNU LGPL (version 2.1 or later).
+- * See the COPYING file in this distribution. 
++ * See the COPYING file in this distribution.
+  */
+ 
+ public class Thumbnails {
+@@ -74,6 +74,7 @@ public class ThumbnailCache : Object {
+     private class AsyncFetchJob : BackgroundJob {
+         public ThumbnailCache cache;
+         public string thumbnail_name;
++        public ThumbnailSource source;
+         public PhotoFileFormat source_format;
+         public Dimensions dim;
+         public Gdk.InterpType interp;
+@@ -84,13 +85,14 @@ public class ThumbnailCache : Object {
+         public bool fetched = false;
+         
+         public AsyncFetchJob(ThumbnailCache cache, string thumbnail_name,
+-            PhotoFileFormat source_format, Gdk.Pixbuf? prefetched, Dimensions dim,
++            ThumbnailSource source, Gdk.Pixbuf? prefetched, Dimensions dim,
+             Gdk.InterpType interp, AsyncFetchCallback callback, Cancellable? cancellable) {
+             base(cache, async_fetch_completion_callback, cancellable);
+             
+             this.cache = cache;
+             this.thumbnail_name = thumbnail_name;
+-            this.source_format = source_format;
++            this.source = source;
++            this.source_format = source.get_preferred_thumbnail_format();
+             this.unscaled = prefetched;
+             this.dim = dim;
+             this.interp = interp;
+@@ -126,11 +128,42 @@ public class ThumbnailCache : Object {
+                 // scale if specified
+                 scaled = dim.has_area() ? resize_pixbuf(unscaled, dim, interp) : unscaled;
+             } catch (Error err) {
++                // Is the problem that the thumbnail couldn't be read? If so, it's recoverable;
++                // we'll just create it and leave this.err as null if creation works.
++                if (err is FileError) {
++                    try {
++                        Photo photo = source as Photo;
++                        Video video = source as Video;
++
++                        if (photo != null) {
++                            unscaled = photo.get_pixbuf(Scaling.for_best_fit(dim.width, true));
++                            photo.notify_altered(new Alteration("image","thumbnail"));
++                            return;
++                        }
++
++                        if (video != null) {
++                            unscaled = video.create_thumbnail(dim.width);
++                            scaled = resize_pixbuf(unscaled, dim, interp);
++                            cache.save_thumbnail(cache.get_source_cached_file(source),
++                                unscaled, source);
++                            replace(source, cache.size, unscaled);
++                            return;
++                        }
++
++                    } catch (Error e) {
++                        // Creating the thumbnail failed; tell the rest of the app.
++                        this.err = e;
++                        return;
++                    }
++                }
++
++                // ...the original error wasn't from reading the file, but something else;
++                // tell the rest of the app.
+                 this.err = err;
+             }
+         }
+     }
+-        
++
+     private static Workers fetch_workers = null;
+     
+     public const ulong MAX_BIG_CACHED_BYTES = 40 * 1024 * 1024;
+@@ -230,13 +263,13 @@ public class ThumbnailCache : Object {
+     
+     public static void fetch_async(ThumbnailSource source, int scale, AsyncFetchCallback callback,
+         Cancellable? cancellable = null) {
+-        get_best_cache(scale)._fetch_async(source.get_source_id(), source.get_preferred_thumbnail_format(),
++        get_best_cache(scale)._fetch_async(source, source.get_preferred_thumbnail_format(),
+             Dimensions(), DEFAULT_INTERP, callback, cancellable);
+     }
+     
+-    public static void fetch_async_scaled(ThumbnailSource source, int scale, Dimensions dim, 
++    public static void fetch_async_scaled(ThumbnailSource source, int scale, Dimensions dim,
+         Gdk.InterpType interp, AsyncFetchCallback callback, Cancellable? cancellable = null) {
+-        get_best_cache(scale)._fetch_async(source.get_source_id(),
++        get_best_cache(scale)._fetch_async(source,
+             source.get_preferred_thumbnail_format(), dim, interp, callback, cancellable);
+     }
+     
+@@ -343,9 +376,10 @@ public class ThumbnailCache : Object {
+         return pixbuf;
+     }
+     
+-    private void _fetch_async(string thumbnail_name, PhotoFileFormat format, Dimensions dim, 
++    private void _fetch_async(ThumbnailSource source, PhotoFileFormat format, Dimensions dim,
+         Gdk.InterpType interp, AsyncFetchCallback callback, Cancellable? cancellable) {
+         // check if the pixbuf is already in memory
++        string thumbnail_name = source.get_source_id();
+         Gdk.Pixbuf pixbuf = fetch_from_memory(thumbnail_name);
+         if (pixbuf != null && (!dim.has_area() || Dimensions.for_pixbuf(pixbuf).equals(dim))) {
+             // if no scaling operation required, callback in this context and done (otherwise,
+@@ -365,8 +399,8 @@ public class ThumbnailCache : Object {
+         // situation.  This may change in the future, and the caching situation will need to be 
+         // handled.
+         
+-        fetch_workers.enqueue(new AsyncFetchJob(this, thumbnail_name, format, pixbuf, dim, interp, 
+-            callback, cancellable));
++        fetch_workers.enqueue(new AsyncFetchJob(this, thumbnail_name, source, pixbuf, dim,
++            interp, callback, cancellable));
+     }
+     
+     // Called within Gtk.main's thread context
+--
+cgit v0.9




More information about the arch-commits mailing list