1. Do not inherit from clutter.Texture. I think you are creating a
circular reference here so your class has to be garbage collected
instead of ref count-deleted (which will be slower to happen). 
        self.sink =  cluttergst.VideoSink(self)   # circ ref???
I couldn't get this thing to be garbage collected for some reason (
Player::__del__ is not called if you inherited, even when you do a
gc.collect() )

BTW, gst.Pipeline() creates a new thread, and you are passing some data
around between threads here as well. 

2. It seems you need to do pipeline.set_state(gst.STATE_NULL) BEFORE you
unref myplayer. This is likely a bug in gstreamer. 

So for example, this one seems to work for me:

import clutter
from clutter import cluttergst
import gst
#import gc

myplayer = None

class Player():

    def __init__(self):
        self.texture = clutter.Texture()
        self.pipeline = gst.Pipeline()
        self.src = gst.element_factory_make("audiotestsrc")
        self.goom = gst.element_factory_make("goom")
        self.colorspace = gst.element_factory_make("ffmpegcolorspace")
        self.sink = cluttergst.VideoSink(self.texture)

        self.pipeline.add(self.src, self.goom, self.colorspace,
self.sink)
        gst.element_link_many(self.src, self.goom, self.colorspace,
self.sink)

        self.pipeline.set_state(gst.STATE_PLAYING)

    def __del__(self):
          ### This is called BEFORE object is destroyed
        print 'Player del'
        self.pipeline.set_state(gst.STATE_NULL)   #### IMPORTANT
        #gc.collect()

def restart_player(a,b):
    global myplayer
    if myplayer:
        print 'removing old player: %s' % myplayer
        stage.remove(myplayer.texture)
        myplayer = None

    myplayer = Player()
    print 'created new player: %s' % myplayer
    myplayer.texture.show()
    stage.add(myplayer.texture)



stage = clutter.stage_get_default()
stage.set_size(320,240)
stage.connect('key-press-event', restart_player)
stage.show_all()
clutter.main()

-Ashwin


-----Original Message-----
From: Emmanuele Bassi [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, February 06, 2008 5:01 PM
To: [email protected]
Subject: Re: [clutter] Memory leak with pyclutter


On Wed, 2008-02-06 at 23:40 +0200, Tero Saarni wrote:
> Hi,
> 
> I have a Clutter based Python application that leaks a lot of memory.
> Objects instantiated from my python classes inheriting from clutter
> never seem to get freed.

which version of python is it? 2.4 or 2.5? unfortunately, python is
known for leaking memory pool all around; 2.5 lessened the leaks, but
there are some issues with lists and tuples (for instance) that would
require a complete overhaul.

> I created a small example (modified from examples/videosink.py) that
> demonstrates the memory leak.  Key press event on the stage window
> will assign over the previously created Player object which I assume
> should trigger the old one being garbage collected at some point.

in theory. in practise, it's better if you explicitly call del() on the
variable before reassigning it.

> However there seems to be some references that keep the objects in
> memory forever.

it is possible that the bindings keep a reference too much; it's mostly
autogenerated code, though.

> After running this loop couple of times the process reserves all my
> memory (be careful not getting your computer completely unresponsive).
> 
> 
> import clutter
> from clutter import cluttergst
> import gst
> 
> myplayer = None
> 
> class Player(clutter.Texture):
> 
>     def __init__(self):
>         super(Player, self).__init__()
> 
>         self.pipeline = gst.Pipeline()
>         self.src = gst.element_factory_make("audiotestsrc")
>         self.goom = gst.element_factory_make("goom")
>         self.colorspace = gst.element_factory_make("ffmpegcolorspace")
>         self.sink = cluttergst.VideoSink(self)
> 
>         self.pipeline.add(self.src, self.goom, self.colorspace,
self.sink)
>         gst.element_link_many(self.src, self.goom, self.colorspace,
self.sink)
>         self.pipeline.set_state(gst.STATE_PLAYING)
> 
> 
> 
> def restart_player(a,b):
>     global myplayer
>     if myplayer:
>         print 'removing old player: %s' % myplayer
>         stage.remove(myplayer)
>     myplayer = Player()
>     print 'created new player: %s' % myplayer
>     myplayer.show()
>     stage.add(myplayer)

you miss a:

      return True

at the end of the event handler.

> I must be missing something obvious...  All help is appreciated! :)

as I said, it can be either:

  1. a bug in python
  2. a bug in the pygobject/pygst bindings
  3. a bug in pyclutter

yours is also somewhat a corner case: you should reuse the Player class
and change the source instead of removing/adding the entire actor every
time.

I'd appreciate if you could run valgrind on the script; I'll have a go
as soon as I can.

ciao,
 Emmanuele.

-- 
Emmanuele Bassi, OpenedHand Ltd.
Unit R, Homesdale Business Centre
216-218 Homesdale Rd., Bromley - BR12QZ
http://www.o-hand.com

-- 
To unsubscribe send a mail to [EMAIL PROTECTED]

--
To unsubscribe send a mail to [EMAIL PROTECTED]

Reply via email to