mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 21:21:12 +00:00
gst/gstbuffer.override: the GstBuffer overrides seem to be confused about whether they're mini-objects or a GBoxed, a...
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
This commit is contained in:
parent
103e13fa66
commit
468cb05597
5 changed files with 179 additions and 11 deletions
19
ChangeLog
19
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>
|
2008-06-26 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||||
|
|
||||||
* gst/common.h:
|
* gst/common.h:
|
||||||
|
|
138
examples/buffer-draw.py
Normal file
138
examples/buffer-draw.py
Normal file
|
@ -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)
|
||||||
|
|
|
@ -89,7 +89,7 @@ _wrap_gst_buffer_tp_str (PyGstMiniObject *self)
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
g_assert (self);
|
g_assert (self);
|
||||||
buf = pyg_boxed_get (self, GstBuffer);
|
buf = GST_BUFFER(pygstminiobject_get(self));
|
||||||
g_assert (buf);
|
g_assert (buf);
|
||||||
|
|
||||||
return PyString_FromStringAndSize((const gchar*) GST_BUFFER_DATA(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,
|
gst_buffer_getreadbuffer(PyObject *self, Py_ssize_t index,
|
||||||
void **ptr)
|
void **ptr)
|
||||||
{
|
{
|
||||||
GstBuffer *buf = pyg_boxed_get(self, GstBuffer);
|
GstBuffer *buf = GST_BUFFER(pygstminiobject_get(self));
|
||||||
|
|
||||||
if ( index != 0 ) {
|
if ( index != 0 ) {
|
||||||
PyErr_SetString(PyExc_SystemError,
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
@ -158,7 +158,7 @@ gst_buffer_getreadbuffer(PyObject *self, Py_ssize_t index,
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
gst_buffer_getsegcount(PyObject *self, Py_ssize_t *lenp)
|
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)
|
if (lenp)
|
||||||
*lenp = GST_BUFFER_SIZE(buf);
|
*lenp = GST_BUFFER_SIZE(buf);
|
||||||
|
@ -180,7 +180,7 @@ static Py_ssize_t gst_buffer_getcharbuf (PyObject *self,
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
gst_buffer_getwritebuf(PyObject *self, Py_ssize_t index, void **ptr)
|
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 ) {
|
if ( index != 0 ) {
|
||||||
PyErr_SetString(PyExc_SystemError,
|
PyErr_SetString(PyExc_SystemError,
|
||||||
|
@ -299,7 +299,7 @@ define GstBuffer.copy_on_write
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_wrap_gst_buffer_copy_on_write (PyObject *self)
|
_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");
|
GST_INFO("INCREF");
|
||||||
if (gst_buffer_is_writable (buf)) {
|
if (gst_buffer_is_writable (buf)) {
|
||||||
|
@ -307,7 +307,8 @@ _wrap_gst_buffer_copy_on_write (PyObject *self)
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
buf = gst_buffer_copy (buf);
|
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;
|
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))
|
if (!PyArg_ParseTuple(args, "i:GstBuffer.flag_is_set", &flag))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buf = pyg_boxed_get(self, GstBuffer);
|
buf = GST_BUFFER(pygstminiobject_get(self));
|
||||||
g_assert(GST_IS_BUFFER(buf));
|
g_assert(GST_IS_BUFFER(buf));
|
||||||
|
|
||||||
retval = GST_BUFFER_FLAG_IS_SET(buf, flag) ? Py_True : Py_False;
|
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))
|
if (!PyArg_ParseTuple(args, "i:GstBuffer.set", &flag))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buf = pyg_boxed_get(self, GstBuffer);
|
buf = GST_BUFFER(pygstminiobject_get(self));
|
||||||
g_assert(GST_IS_BUFFER(buf));
|
g_assert(GST_IS_BUFFER(buf));
|
||||||
GST_BUFFER_FLAG_SET(buf, flag);
|
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))
|
if (!PyArg_ParseTuple(args, "i:GstBuffer.unset", &flag))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buf = pyg_boxed_get(self, GstBuffer);
|
buf = GST_BUFFER(pygstminiobject_get(self));
|
||||||
g_assert(GST_IS_BUFFER(buf));
|
g_assert(GST_IS_BUFFER(buf));
|
||||||
GST_BUFFER_FLAG_UNSET(buf, flag);
|
GST_BUFFER_FLAG_UNSET(buf, flag);
|
||||||
|
|
||||||
|
@ -374,7 +375,7 @@ _wrap_gst_buffer__get_data(PyObject *self, void *closure)
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
g_assert (self);
|
g_assert (self);
|
||||||
buf = pyg_boxed_get (self, GstBuffer);
|
buf = GST_BUFFER(pygstminiobject_get(self));
|
||||||
g_assert (buf);
|
g_assert (buf);
|
||||||
|
|
||||||
return PyString_FromStringAndSize((const gchar*) GST_BUFFER_DATA(buf),
|
return PyString_FromStringAndSize((const gchar*) GST_BUFFER_DATA(buf),
|
||||||
|
|
|
@ -1006,7 +1006,7 @@ _wrap_gst_pad_add_buffer_probe(PyGObject *self, PyObject *args)
|
||||||
%%
|
%%
|
||||||
override-slot GstPadTemplate.tp_getattr
|
override-slot GstPadTemplate.tp_getattr
|
||||||
#define IS_ATTR(name) (strcmp (name, attr) == 0)
|
#define IS_ATTR(name) (strcmp (name, attr) == 0)
|
||||||
PyObject *
|
static PyObject *
|
||||||
_wrap_gst_pad_template_tp_getattr(PyObject *self, char *attr)
|
_wrap_gst_pad_template_tp_getattr(PyObject *self, char *attr)
|
||||||
{
|
{
|
||||||
GstPadTemplate *templ = GST_PAD_TEMPLATE (pygobject_get (self));
|
GstPadTemplate *templ = GST_PAD_TEMPLATE (pygobject_get (self));
|
||||||
|
|
|
@ -87,6 +87,16 @@ class BufferTest(TestCase):
|
||||||
|
|
||||||
spaned_buffer = buffer1.span(0L, buffer2, 6L)
|
spaned_buffer = buffer1.span(0L, buffer2, 6L)
|
||||||
assert str(spaned_buffer) == 'foobar'
|
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):
|
def testBufferFlagIsSet(self):
|
||||||
buffer = gst.Buffer()
|
buffer = gst.Buffer()
|
||||||
|
|
Loading…
Reference in a new issue