On Thu, Aug 7, 2014 at 12:24 PM, Ignacio Jaureguiberry <
ijaureguibe...@lifia.info.unlp.edu.ar> wrote:
> I'm programming using mlt framework (#include <mlt/framework/mlt.h>),
> and I'm having a segfault after my program runs for long periods (2
> times happened after 10 hours run, 1 after 5 hours run). I believe this
> might be related to synchronization issues between mlt threads, as I
> modify the running playlists and the composite transitions I've planted
> on the field while the system is running.
>
> My program setups 5 tracks, track #0 holds a full 768x576 video looping
> (10000 times for a 13 secs video), while tracks 1 to 4 holds other
> smaller videos that I stop and start all the time. I use composite
> transitions so that videos that start or stop do a fade in or fade out
> and also set its boundaries.
> Something like:
> ------------------
> | ------ ------ |
> | | t1 | | t2 | |
> | ------ ------ |
> | ------ ------ |
> | | t3 | | t4 | |
> | ------ ------ |
> ------------------
>
> The program randomly chooses one track from 1 to 4, and switches the
> video status of it: if it is running, the video is stopped. If it is
> stopped, the video is started. This is done every 1 second, and the
> program seems to run fine for the first couple of hours, but never
> reached 12 hours of running.
>
> I've managed to start gdb with a core dump, with ubuntu 13.10 version of
> mlt (0.8.8-2) with debugging package (libmlt-dbg), and found that the
> segfault is in producer_get_frame in mlt_producer.c:616, line is:
>
> if ( self->get_frame == NULL || ( !strcmp( eof, "continue" ) &&
> mlt_producer_position( self ) > mlt_producer_get_out( self ) ) )
>
> gdb states self is not NULL, self->get_frame is not NULL, but eof is:
>
> (gdb) info locals
> properties = 0x128b3e0
> eof = 0x0
> speed = 1
> clone = 0x128b3e0
> result = 1
> self = 0x128b3e0
> (gdb) print self->get_frame
> $10 = (int (*)(mlt_producer, mlt_frame_ptr, int)) 0x7f322005cb80
> <producer_get_frame>
>
>
There was a fix for this null pointer in version 0.9.2:
https://github.com/mltframework/mlt/commit/689ffbad7da48a5c795df6b5995f8b6b3c9a4299
> Now, on the thread i'm switching the videos on and off, I'm trying to
> add a video to the playlist with mlt_playlist_append_io, and the
> segfault stopped this thread in the process of setting the property
> "eof" to value "continue", so I believe the rendering process is trying
> to access eof property which is NULL while another thread is actually
> setting this value to "continue".
>
>
Is your code the one directly setting "eof" or is it the code in
mlt_multitrack_refresh()? Tracing all code paths that lead to
mlt_multitrack_refresh() can be some work. Basically, it is reached
whenever the graph changes or you change in/out on a producer. In any case,
the stack of get_frame() calls is protected by the service lock:
https://github.com/mltframework/mlt/blob/master/src/framework/mlt_service.c#L444
> While messing up with the playlist, I surrounded all the code with:
>
> mlt_service_lock(MLT_PLAYLIST_SERVICE(*_plist));
> mlt_service_unlock(MLT_PLAYLIST_SERVICE(*_plist));
>
> hoping that would stop the rendering thread from using the playlist
>
Yes, that is a good idea. There are some mailing list threads from April 23
and mid-May with Juan and Janne where I suggested that locks may be needed.
We might want to add these locks to these functions, but it is a fair
amount of work since that will require a mechanism to prevent deadlock due
to double-lock, and no one has volunteered that work yet.
> while I'm modifying it, but maybe I should lock not the playlist but the
> tracktor? Any other idea on what could be causing this error? I've
>
I am thinking that would be good as well as the mlt_multitrack. If
mlt_multitrack_refresh() is the one setting "eof" then that function is
called by the service-changed and producer-changed event listeners in
mlt_multitrack and mlt_tractor. Appending an item to the playlist should be
triggering these events according to my analysis. The render thread could
be in a part of the get_frame() call stack that has not yet reached the
locked mlt_playlist::producer_get_frame() while a playlist manipulation
function reaches an event listener calling mlt_multitrack_refresh() that is
changing the property.
All of this really exposes a fundamental design property with
mlt_properties_get() for string properties. The pointer it returns can
become invalid as soon as it leaves the function. I thought of a couple of
ways to address this, but I am starting to get a little off-topic now. I
think the newer version of MLT (or that particular change) combined with
the additional locks should fix your problem with consistency of the eof
property.
> searched the entire mlt-devel mailing list, but couldn't find any
> related post.
>
> Can I send the code as an attachment to this list?
>
> Sorry for the long mail :(
> Ignacio Jaureguiberry.
>
> --- pieces of the on() / off() video (C++) ------
> void on()
> {
> if (_playing)
> return;
> // add video to playlist
> mlt_producer vid = mlt_factory_producer(profile, NULL, _video);
> int original =
> mlt_producer_position(mlt_multitrack_producer(multitrack));
> mlt_service_lock(MLT_PLAYLIST_SERVICE(*_plist));
> mlt_playlist_clear(*_plist);
> mlt_playlist_blank(*_plist, original);
> mlt_playlist_append_io(*_plist, vid, 0, -1);
>
> // transition for fade video in:
> // builds a string like:
> "X=32/52:320x180:0;X+25=32/52:320x180:100" for simulating a fade in.
> std::string txs = transition_string(original, _x, 0) + ";" +
> transition_string(original + 25, _x, 100);
> mlt_properties_set(mlt_transition_properties(*_trans), "geometry",
> txs.c_str());
>
> mlt_service_unlock(MLT_PLAYLIST_SERVICE(*_plist));
>
> mlt_producer_close(vid);
> _playing = true;
> }
>
> void off()
> {
> if (!_playing)
> return;
>
> mlt_service_lock(MLT_PLAYLIST_SERVICE(*_plist));
> // transition to fade video out:
> int original =
> mlt_producer_position(mlt_multitrack_producer(multitrack));
>
> // builds a string like:
> "X=32/52:320x180:100;X+25=32/52:320x180:0" for simulating a fade out.
> std::string txs = transition_string(original - 1, _x, 100) +";"
> +transition_string(original + 25, _x, 0);
>
>
> mlt_properties_set(mlt_transition_properties(*_trans),"geometry",txs.c_str());
> mlt_service_unlock(MLT_PLAYLIST_SERVICE(*_plist));
>
> // wait for the fade out the hide the video...
> usleep(1000000);
>
> // clear the playlist.
> mlt_producer producer = MLT_PLAYLIST_PRODUCER(*_plist);
> mlt_service_lock(MLT_PLAYLIST_SERVICE(*_plist));
> mlt_playlist_clear(*_plist);
> mlt_producer_seek(producer, 0);
> mlt_service_unlock(MLT_PLAYLIST_SERVICE(*_plist));
> _playing = false;
> }
>
>
------------------------------------------------------------------------------
Want fast and easy access to all the code in your enterprise? Index and
search up to 200,000 lines of code with a free copy of Black Duck
Code Sight - the same software that powers the world's largest code
search on Ohloh, the Black Duck Open Hub! Try it now.
http://p.sf.net/sfu/bds
_______________________________________________
Mlt-devel mailing list
Mlt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlt-devel