gst/gstbuffer.override: the GstBuffer overrides seem to be confused about whether...
authorJan Schmidt <thaytan@mad.scientist.com>
Fri, 27 Jun 2008 08:39:37 +0000 (08:39 +0000)
committerJan Schmidt <thaytan@mad.scientist.com>
Fri, 27 Jun 2008 08:39:37 +0000 (08:39 +0000)
Original commit message from CVS:
* gst/gstbuffer.override:
the GstBuffer overrides seem to be confused about whether they're
mini-objects or a GBoxed, and it makes copy_on_write no actually
return a usable gst.Buffer. Fix up places where GstBuffers are
treated as GBoxed to use pygstminiobject functions.
Makes gst.Buffer('blah').copy_on_write() work.
* testsuite/test_buffer.py:
Add test for copy-on-write writability
* examples/buffer-draw.py:
Add an example of drawing on a GStreamer buffer with cairo
* gst/gstpad.override:
Make function static

ChangeLog
examples/buffer-draw.py [new file with mode: 0644]
gst/gstbuffer.override
gst/gstpad.override
testsuite/test_buffer.py

index 9533986..bca9979 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2008-06-27  Jan Schmidt  <jan.schmidt@sun.com>
+
+       * gst/gstbuffer.override:
+        the GstBuffer overrides seem to be confused about whether they're
+       mini-objects or a GBoxed, and it makes copy_on_write no actually
+       return a usable gst.Buffer. Fix up places where GstBuffers are 
+       treated as GBoxed to use pygstminiobject functions.
+
+       Makes gst.Buffer('blah').copy_on_write() work.
+
+       * testsuite/test_buffer.py:
+       Add test for copy-on-write writability
+
+       * examples/buffer-draw.py:
+       Add an example of drawing on a GStreamer buffer with cairo
+
+       * gst/gstpad.override:
+       Make function static
+
 2008-06-26  Edward Hervey  <edward.hervey@collabora.co.uk>
 
        * gst/common.h:
diff --git a/examples/buffer-draw.py b/examples/buffer-draw.py
new file mode 100644 (file)
index 0000000..7058382
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+
+import sys
+import traceback
+from math import pi
+
+import pygtk
+pygtk.require ("2.0")
+import gobject
+gobject.threads_init()
+
+import pygst
+pygst.require('0.10')
+import gst
+
+import cairo
+
+WIDTH, HEIGHT = 640, 480
+FRAMES = 300
+FRAMERATE = 15
+
+class PyGstBufferDraw(gst.Element):
+    _sinkpadtemplate = gst.PadTemplate ("sink",
+                                         gst.PAD_SINK,
+                                         gst.PAD_ALWAYS,
+                                         gst.caps_from_string ("video/x-raw-rgb,bpp=32,depth=32,blue_mask=-16777216,green_mask=16711680, red_mask=65280, alpha_mask=255,width=[ 1, 2147483647 ],height=[ 1, 2147483647 ],framerate=[ 0/1, 2147483647/1 ]"))
+    _srcpadtemplate = gst.PadTemplate ("src",
+                                         gst.PAD_SRC,
+                                         gst.PAD_ALWAYS,
+                                         gst.caps_from_string ("video/x-raw-rgb,bpp=32,depth=32,blue_mask=-16777216,green_mask=16711680, red_mask=65280, alpha_mask=255,width=[ 1, 2147483647 ],height=[ 1, 2147483647 ],framerate=[ 0/1, 2147483647/1 ]"))
+
+    def __init__(self):
+        gst.Element.__init__(self)
+
+        self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink")
+        self.sinkpad.set_chain_function(self.chainfunc)
+        self.sinkpad.set_event_function(self.eventfunc)
+        self.sinkpad.set_getcaps_function(gst.Pad.proxy_getcaps)
+        self.sinkpad.set_setcaps_function(gst.Pad.proxy_setcaps)
+        self.add_pad (self.sinkpad)
+
+        self.srcpad = gst.Pad(self._srcpadtemplate, "src")
+
+        self.srcpad.set_event_function(self.srceventfunc)
+        self.srcpad.set_query_function(self.srcqueryfunc)
+        self.srcpad.set_getcaps_function(gst.Pad.proxy_getcaps)
+        self.srcpad.set_setcaps_function(gst.Pad.proxy_setcaps)
+        self.add_pad (self.srcpad)
+
+    def chainfunc(self, pad, buffer):
+        try:
+            outbuf = buffer.copy_on_write ()
+            self.draw_on (outbuf)
+            return self.srcpad.push (outbuf)
+        except:
+            return GST_FLOW_ERROR
+
+    def eventfunc(self, pad, event):
+        return self.srcpad.push_event (event)
+        
+    def srcqueryfunc (self, pad, query):
+        return self.sinkpad.query (query)
+    def srceventfunc (self, pad, event):
+        return self.sinkpad.push_event (event)
+
+    def draw_on (self, buf):
+        try:
+            caps = buf.get_caps()
+            width = caps[0]['width']
+            height = caps[0]['height']
+            framerate = caps[0]['framerate']
+            surface = cairo.ImageSurface.create_for_data (buf, cairo.FORMAT_ARGB32, width, height, 4 * width)
+            ctx = cairo.Context(surface)
+        except:
+            print "Failed to create cairo surface for buffer"
+            traceback.print_exc()
+            return
+
+        try:
+            center_x = width/4
+            center_y = 3*height/4
+
+            # draw a circle
+            radius = float (min (width, height)) * 0.25
+            ctx.set_source_rgba (0.0, 0.0, 0.0, 0.9)
+            ctx.move_to (center_x, center_y)
+            ctx.arc (center_x, center_y, radius, 0, 2.0*pi)
+            ctx.close_path()
+            ctx.fill()
+            ctx.set_source_rgba (1.0, 1.0, 1.0, 1.0)
+            ctx.set_font_size(0.3 * radius)
+            txt = "Hello World"
+            extents = ctx.text_extents (txt)
+            ctx.move_to(center_x - extents[2]/2, center_y + extents[3]/2)
+            ctx.text_path(txt)
+            ctx.fill()
+
+        except:
+            print "Failed cairo render"
+            traceback.print_exc()
+
+gobject.type_register(PyGstBufferDraw)
+
+pipe = gst.Pipeline()
+vt = gst.element_factory_make ("videotestsrc")
+cf = gst.element_factory_make ("capsfilter")
+c1 = PyGstBufferDraw()
+color = gst.element_factory_make ("ffmpegcolorspace")
+scale = gst.element_factory_make ("videoscale")
+q1 = gst.element_factory_make ("queue")
+sink = gst.element_factory_make ("autovideosink")
+
+caps = gst.caps_from_string ("video/x-raw-rgb,width=%d,height=%d,framerate=%d/1" % (WIDTH, HEIGHT, FRAMERATE))
+cf.set_property ("caps", caps)
+
+vt.set_property ("num-buffers", FRAMES)
+
+pipe.add (vt, cf, c1, q1, color, scale, sink)
+gst.element_link_many (vt, cf, c1, q1, color, scale, sink)
+
+def on_eos (bus, msg):
+    mainloop.quit()
+
+bus = pipe.get_bus()
+bus.add_signal_watch()
+bus.connect('message::eos', on_eos)
+
+pipe.set_state (gst.STATE_PLAYING)
+
+mainloop = gobject.MainLoop()
+try:
+    mainloop.run()
+except:
+    pass
+
+pipe.set_state (gst.STATE_NULL)
+pipe.get_state (gst.CLOCK_TIME_NONE)
+
index 161bea3..7a9eb94 100644 (file)
@@ -89,7 +89,7 @@ _wrap_gst_buffer_tp_str (PyGstMiniObject *self)
        GstBuffer *buf;
 
        g_assert (self);
-       buf = pyg_boxed_get (self, GstBuffer);
+        buf = GST_BUFFER(pygstminiobject_get(self));
        g_assert (buf);
 
        return PyString_FromStringAndSize((const gchar*) GST_BUFFER_DATA(buf),
@@ -143,7 +143,7 @@ static Py_ssize_t
 gst_buffer_getreadbuffer(PyObject *self, Py_ssize_t index, 
     void **ptr)
 {
-       GstBuffer *buf = pyg_boxed_get(self, GstBuffer);
+       GstBuffer *buf = GST_BUFFER(pygstminiobject_get(self));
 
        if ( index != 0 ) {
                PyErr_SetString(PyExc_SystemError,
@@ -158,7 +158,7 @@ gst_buffer_getreadbuffer(PyObject *self, Py_ssize_t index,
 static Py_ssize_t
 gst_buffer_getsegcount(PyObject *self, Py_ssize_t *lenp)
 {
-       GstBuffer *buf = pyg_boxed_get(self, GstBuffer);
+       GstBuffer *buf = GST_BUFFER(pygstminiobject_get(self));
 
        if (lenp)
                *lenp = GST_BUFFER_SIZE(buf);
@@ -180,7 +180,7 @@ static Py_ssize_t gst_buffer_getcharbuf    (PyObject   *self,
 static Py_ssize_t
 gst_buffer_getwritebuf(PyObject *self, Py_ssize_t index, void **ptr)
 {
-       GstBuffer *buf = pyg_boxed_get(self, GstBuffer);
+       GstBuffer *buf = GST_BUFFER(pygstminiobject_get(self));
 
        if ( index != 0 ) {
                PyErr_SetString(PyExc_SystemError,
@@ -299,7 +299,7 @@ define GstBuffer.copy_on_write
 static PyObject *
 _wrap_gst_buffer_copy_on_write (PyObject *self)
 {
-       GstBuffer *buf = pyg_boxed_get(self, GstBuffer);
+       GstBuffer *buf = GST_BUFFER(pygstminiobject_get(self));
 
        GST_INFO("INCREF");
        if (gst_buffer_is_writable (buf)) {
@@ -307,7 +307,8 @@ _wrap_gst_buffer_copy_on_write (PyObject *self)
          return self;
        }
        buf = gst_buffer_copy (buf);
-       self = pyg_boxed_new (GST_TYPE_BUFFER, buf, FALSE, TRUE);
+       self = pygstminiobject_new ((GstMiniObject *)(buf));
+        gst_buffer_unref (buf);
        return self;
 }
 %%
@@ -322,7 +323,7 @@ _wrap_gst_buffer_flag_is_set(PyObject *self, PyObject *args)
        if (!PyArg_ParseTuple(args, "i:GstBuffer.flag_is_set", &flag))
                return NULL;
 
-       buf = pyg_boxed_get(self, GstBuffer);
+       buf = GST_BUFFER(pygstminiobject_get(self));
        g_assert(GST_IS_BUFFER(buf));
        
        retval = GST_BUFFER_FLAG_IS_SET(buf, flag) ? Py_True : Py_False;
@@ -340,7 +341,7 @@ _wrap_gst_buffer_flag_set(PyObject *self, PyObject *args)
        if (!PyArg_ParseTuple(args, "i:GstBuffer.set", &flag))
                return NULL;
 
-       buf = pyg_boxed_get(self, GstBuffer);
+       buf = GST_BUFFER(pygstminiobject_get(self));
        g_assert(GST_IS_BUFFER(buf));
        GST_BUFFER_FLAG_SET(buf, flag);
 
@@ -358,7 +359,7 @@ _wrap_gst_buffer_flag_unset(PyObject *self, PyObject *args)
        if (!PyArg_ParseTuple(args, "i:GstBuffer.unset", &flag))
                return NULL;
 
-       buf = pyg_boxed_get(self, GstBuffer);
+        buf = GST_BUFFER(pygstminiobject_get(self));
        g_assert(GST_IS_BUFFER(buf));
        GST_BUFFER_FLAG_UNSET(buf, flag);
 
@@ -374,7 +375,7 @@ _wrap_gst_buffer__get_data(PyObject *self, void *closure)
        GstBuffer *buf;
 
        g_assert (self);
-       buf = pyg_boxed_get (self, GstBuffer);
+        buf = GST_BUFFER(pygstminiobject_get(self));
        g_assert (buf);
 
        return PyString_FromStringAndSize((const gchar*) GST_BUFFER_DATA(buf),
index 8b32124..3ddb665 100644 (file)
@@ -1006,7 +1006,7 @@ _wrap_gst_pad_add_buffer_probe(PyGObject *self, PyObject *args)
 %%
 override-slot GstPadTemplate.tp_getattr
 #define IS_ATTR(name) (strcmp (name, attr) == 0)
-PyObject *
+static PyObject *
 _wrap_gst_pad_template_tp_getattr(PyObject *self, char *attr)
 {
   GstPadTemplate *templ = GST_PAD_TEMPLATE (pygobject_get (self));
index bce6d1a..b4a5fb2 100644 (file)
@@ -87,6 +87,16 @@ class BufferTest(TestCase):
 
         spaned_buffer = buffer1.span(0L, buffer2, 6L)
         assert str(spaned_buffer) == 'foobar'
+    def testBufferCopyOnWrite(self):
+        s='test_vector'
+        buffer = gst.Buffer(s)
+        sub = buffer.create_sub(0, buffer.size)
+        self.assertEquals(sub.size, buffer.size)
+        out = sub.copy_on_write ()
+        self.assertEquals(out.size, sub.size)
+        assert str(out) == str(buffer)
+        out[5] = 'w'
+        assert str(out) == 'test_wector'
 
     def testBufferFlagIsSet(self):
         buffer = gst.Buffer()