From 4db67e385c9c2d89947077f1520aa31af2538d65 Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Wed, 09 Jan 2013 01:11:27 +0000 Subject: Ports Shotwell to GStreamer 1.0. Closes #6055. --- diff --git a/Makefile b/Makefile 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 LOCAL_LANG_DIR=locale-langpack SYSTEM_LANG_DIR := $(DESTDIR)$(PREFIX)/share/locale -VALAFLAGS := -g --enable-checking --thread --fatal-warnings --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 @@ -293,9 +293,9 @@ EXT_PKGS = \ gio-unix-2.0 \ glib-2.0 \ gmodule-2.0 \ - gstreamer-0.10 \ - gstreamer-base-0.10 \ - gstreamer-pbutils-0.10 \ + gstreamer-1.0 \ + gstreamer-base-1.0 \ + gstreamer-pbutils-1.0 \ gtk+-3.0 \ gudev-1.0 \ libexif \ @@ -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 DIRECT_LIBS = @@ -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 \ - gstreamer-0.10 >= 0.10.28 \ - gstreamer-base-0.10 >= 0.10.28 \ - gstreamer-plugins-base-0.10 >= 0.10.32 \ - gstreamer-pbutils-0.10 >= 0.10.32 \ + gstreamer-1.0 >= 1.0.0 \ + gstreamer-base-1.0 >= 1.0.0 \ + gstreamer-plugins-base-1.0 >= 1.0.0 \ + gstreamer-pbutils-1.0 >= 1.0.0 \ 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 +++ b/src/VideoSupport.vala @@ -163,8 +163,8 @@ public class VideoReader { file.get_path())); try { - Gst.Discoverer d = new Gst.Discoverer((Gst.ClockTime) (Gst.SECOND * 5)); - Gst.DiscovererInfo info = d.discover_uri(file.get_uri()); + Gst.PbUtils.Discoverer d = new Gst.PbUtils.Discoverer((Gst.ClockTime) (Gst.SECOND * 5)); + Gst.PbUtils.DiscovererInfo info = d.discover_uri(file.get_uri()); clip_duration = ((double) info.get_duration()) / 1000000000.0; @@ -172,7 +172,7 @@ public class VideoReader { // TODO: Note that TAG_DATE can be changed to TAG_DATE_TIME in the future // (and the corresponding output struct) in order to implement #2836. Date? video_date = null; - if (info.get_tags() != null && info.get_tags().get_date(Gst.TAG_DATE, out video_date)) { + if (info.get_tags() != null && info.get_tags().get_date(Gst.Tags.DATE, out video_date)) { timestamp = new DateTime.local(video_date.get_year(), video_date.get_month(), video_date.get_day(), 0, 0, 0); } @@ -323,7 +323,7 @@ public class Video : VideoSource, Flaggable, Monitorable, Dateable { Gst.init(ref fake_unowned_args); int saved_state = Config.Facade.get_instance().get_video_interpreter_state_cookie(); - current_state = (int) Gst.Registry.get_default().get_feature_list_cookie(); + current_state = (int) Gst.Registry.get().get_feature_list_cookie(); if (saved_state == Config.Facade.NO_VIDEO_INTERPRETER_STATE) { 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 79a2d7e..ae1e537 100644 --- a/thumbnailer/shotwell-video-thumbnailer.vala +++ b/thumbnailer/shotwell-video-thumbnailer.vala @@ -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 { - const string caps_string = """video/x-raw-rgb,bpp = (int) 32, depth = (int) 32, - endianness = (int) BIG_ENDIAN, - red_mask = (int) 0xFF000000, - green_mask = (int) 0x00FF0000, - blue_mask = (int) 0x0000FF00, - 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 ! videoscale ! ".printf(args[1]) + "appsink name=sink caps=\"%s\"".printf(caps_string); try { @@ -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); - 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 = sample.get_caps(); if (caps == null) { stderr.printf("could not get snapshot format\n"); return 5; @@ -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, - 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 { stderr.printf("Could not make snapshot\n"); return 10; -- cgit v0.9