Initial commit
[fillmore] / src / marina / thumbnailsink.vala
diff --git a/src/marina/thumbnailsink.vala b/src/marina/thumbnailsink.vala
new file mode 100644 (file)
index 0000000..fe4f358
--- /dev/null
@@ -0,0 +1,68 @@
+class ThumbnailSink : Gst.BaseSink {
+    int width;
+    int height;
+    
+    const string caps_string = """video/x-raw-rgb,bpp = (int) 32, depth = (int) 32,
+                                  endianness = (int) BIG_ENDIAN,
+                                  blue_mask = (int)  0xFF000000,
+                                  green_mask = (int) 0x00FF0000,
+                                  red_mask = (int)   0x0000FF00,
+                                  width = (int) [ 1, max ],
+                                  height = (int) [ 1, max ],
+                                  framerate = (fraction) [ 0, max ]""";
+
+    public signal void have_thumbnail(Gdk.Pixbuf b);
+    
+    class construct {
+        Gst.StaticPadTemplate pad;        
+        pad.name_template = "sink";
+        pad.direction = Gst.PadDirection.SINK;
+        pad.presence = Gst.PadPresence.ALWAYS;
+        pad.static_caps.str = caps_string;
+        
+        add_pad_template(pad.get());        
+    }
+    
+    // This empty construct block eliminates a build warning about chaining up to a private
+    // constructor.
+    construct {
+    }
+    
+    public ThumbnailSink() {
+        set_sync(false);
+    }
+    
+    public override bool set_caps(Gst.Caps c) {
+        if (c.get_size() < 1)
+            return false;
+            
+        Gst.Structure s = c.get_structure(0);
+        
+        if (!s.get_int("width", out width) ||
+            !s.get_int("height", out height))
+            return false;
+        return true;
+    }
+    
+    void convert_pixbuf_to_rgb(Gdk.Pixbuf buf) {
+        uchar* data = buf.get_pixels();
+        int limit = buf.get_width() * buf.get_height();
+        
+        while (limit-- != 0) {
+            uchar temp = data[0];
+            data[0] = data[2];
+            data[2] = temp;
+            
+            data += 4;
+        }
+    }
+    
+    public override Gst.FlowReturn preroll(Gst.Buffer b) {
+        Gdk.Pixbuf buf = new Gdk.Pixbuf.from_data(b.data, Gdk.Colorspace.RGB, 
+                                                    true, 8, width, height, width * 4, null);
+        convert_pixbuf_to_rgb(buf);
+        
+        have_thumbnail(buf);
+        return Gst.FlowReturn.OK;
+    }
+}