[mythtv] segfault problem with current CVS.

Chris Pinkham cpinkham at bc2va.org
Mon Feb 24 00:49:14 EST 2003


> > Can you try running things in valgrind ( http://developer.kde.org/~sewardj/ ), 
> 
> Thanks for the link.  With the help of valgrind and a bunch of debugging
> printf()'s of my own, I've tracked it down to two pointers that are

OK, I figured out the bug.  I know what causes it and know why It's been
popping up during my testing.  I'm not sure how you want to fix it Isaac and
I don't have time to code a patch, test thoroughly, and submit it before
going out of town so I'll describe the problem and then how I think it
maybe could be fixed by only changing a couple lines of code.

When DecodeFrame is called, it is called with vbuffer[wpos] passed in
to the variable outbuf.  It then sets directbuf = outbuf.  During libavcodec's
decoding, it calls MythTV's get_buffer().  get_buffer() sets pic->data[0]
to directbuf.  Later in mpegvideo.c, libavcodec does this snippet of
code:

    for(i=0; i<MAX_PICTURE_COUNT; i++){
        if(s->picture[i].data[0] == s->current_picture.data[0]){
            s->picture[i]= s->current_picture;
            break;
        }
    }
    assert(i<MAX_PICTURE_COUNT);

The "if" statement checks the value of data (which is a vbuffer entry in
MythTV's case), it uses that to know which s->picture structure to
copy data back into.

That was the setup, here's where the problem happens to me although it
probably can pop up other places as well.

Whenever the user has a bookmark set, one of the first things that
NuppelVideoPlayer::StartPlaying does is do a GetFrame which calls
DecodeFrame (passing in vbuffer[0] since wpos == 0).  GetFrame then sets
wpos = 1.  Then StartPlayer calls DoFastForward to jump to the bookmark.
DoFastForward calls ClearAfterSeek when it's done fast forwarding.
ClearAfterSeek sets wpos back to 0 setting the events in motion.
Then StartPlayer proceeds down and goes into it's normal while() loop.
Inside the while loop, the very second call to GetFrame is called.
The problem occurs right here.  GetFrame calls DecodeFrame again
with vbuffer[0].  libavcodec assumes that you wouldn't use the same
buffer for 2 different frames and ends up overwriting some pointers
and trying to free the same memory twice causing a segfault.

A simple fix seems to be to change ClearAfterSeek to do this:

    vpos = wpos;
    rpos = wpos;

instead of setting vpos, wpos, and rpos all back to 0.  This should insure
that we don't give libavcodec 2 frames that have the same vbuffer.
libavcodec has it's own internal frame buffer and doesn't like it when
two of them have the same data passed in from the calling app it appears.

I have tested this and it appears to work correctly, but I won't be able
to do any testing over the next couple days since I'll be out of town so
I figured I'd post it here and let others try to reproduce the problem
and test it.

The good news is that it wasn't my commercial code doing it. :)  I'll
hopefully submit an update to the commercial skip stuff tomorrow.  I have
it coded and working but don't have time to get a patch ready tonight.

Chris

*****************************************************************************
** Chris Pinkham                  Linux v2.2.18, Sane v1.0.4, Cajun v3.0-8 **
** cpinkham at bc2va.org                          http://www.bc2va.org/chris/ **
*****************************************************************************


More information about the mythtv-dev mailing list