[FFmpeg-devel] [PATCH] ffplay: fix a crash caused by aborting the video queue

avcoder ffmpeg at gmail.com
Sat Aug 27 20:09:21 CEST 2011


On Sun, Aug 28, 2011 at 1:26 AM, Marton Balint <cus at passwd.hu> wrote:
>
> On Sun, 28 Aug 2011, avcoder wrote:
>
>> On Sun, Aug 28, 2011 at 12:40 AM, Marton Balint <cus at passwd.hu> wrote:
>>>
>>> On Sat, 27 Aug 2011, avcoder wrote:
>>>
>>>> On Sat, Aug 27, 2011 at 6:09 PM, Marton Balint <cus at passwd.hu> wrote:
>>>>>
>>>>> Yes, the patch description is probably not entirely correct, sorry, my
>>>>> mistake. The thought of changing w_index somehow remained in my mind
>>>>> from
>>>>> the time I debugged this.
>>>>>
>>>>> The main problem with the code is that multiple ALLOC events may occur
>>>>> at
>>>>> the same time if we don't pop them from the event queue on abort. If
>>>>> these
>>>>> alloc events tries to allocate the same vp, vp->bmp changes (free-d,
>>>>> and
>>>>> the
>>>>> then allocated again), I typically got the crash when
>>>>> SDL_LockYUVOverlay(vp->bmp) was called from the video thread, after
>>>>> SDL_FreeYUVOverlay(vp->bmp) was called from the main thread.
>>>>
>>>> Why do you get multiple ALLOC envents?
>>>>
>>>> I checked the ALLOC events, FF_ALLOC_EVENT is only pushed in
>>>> "queue_picture()" which is called by "video_thread()", it is
>>>> impossible to have MULTIPLE FF_ALLOC_EVENT.
>>>
>>> When you abort the video queue, an ALLOC event may be in the event queue.
>>> When another video_thread() is stared (e.g. when changing the video
>>> stream)
>>> the event from the first video_thread may still be in the queue.
>>>
>>
>> OK, that's the point.
>>
>> But this scenario has no relationship with your previous explanation
>> -----'if these alloc events tries to allocate the same vp...., "
>> The vp is not same if you start another video_thread(). so there's no
>> scenario to produce your bug: "  I typically got the crash when
>> SDL_LockYUVOverlay(vp->bmp) was called from the video thread, after
>> SDL_FreeYUVOverlay(vp->bmp) was called from the main thread."
>>
>> Your patch is harmless, but useless.
>>
>
> I don't agree, because with my patch, alloc_picture and SDL_LockYUVOverlay
> of queue_picture cannot run at the same time, therefore there is no chance
> that SDL_LockYUVOverlay will do a lock using a currently freed pointer,
> which may be the case, if SDL_LockYUVOverlay happens when the main thread is
> in the middle of alloc_picture.


SDL_LockYUVOverlay has no chance to happens when the main thread is in
the middle of alloc_picture in the original implementation

there are serialization.

    /* alloc or resize hardware picture buffer */
    if (!vp->bmp ||
#if CONFIG_AVFILTER
        vp->width  != is->out_video_filter->inputs[0]->w ||
        vp->height != is->out_video_filter->inputs[0]->h) {
#else
        vp->width != is->video_st->codec->width ||
        vp->height != is->video_st->codec->height) {
#endif
        SDL_Event event;

        vp->allocated = 0;

        /* the allocation must be done in the main thread to avoid
           locking problems */
        event.type = FF_ALLOC_EVENT;
        event.user.data1 = is;
        SDL_PushEvent(&event);

        // ----------------------- code a--------------------------------------
        /* wait until the picture is allocated */
        SDL_LockMutex(is->pictq_mutex);
        while (!vp->allocated && !is->videoq.abort_request) {
            SDL_CondWait(is->pictq_cond, is->pictq_mutex);
        }
        SDL_UnlockMutex(is->pictq_mutex);

        // -----------------------code b --------------------------------------
        if (is->videoq.abort_request)
            return -1;
    }

    /* if the frame is not skipped, then display it */
    if (vp->bmp) {
        AVPicture pict;
#if CONFIG_AVFILTER
        if(vp->picref)
            avfilter_unref_buffer(vp->picref);
        vp->picref = src_frame->opaque;
#endif

        // ----------------------------code c-----------------------------------
        /* get a pointer on the bitmap */
        SDL_LockYUVOverlay (vp->bmp);

        memset(&pict,0,sizeof(AVPicture));
        pict.data[0] = vp->bmp->pixels[0];
        pict.data[1] = vp->bmp->pixels[2];
        pict.data[2] = vp->bmp->pixels[1];

        pict.linesize[0] = vp->bmp->pitches[0];
        pict.linesize[1] = vp->bmp->pitches[2];
        pict.linesize[2] = vp->bmp->pitches[1];

......

}


'code c' and 'alloc_picture()' can be concurrent only in abort mode,
but 'code b ' prevent them.


-- 
-----------------------------------------------------------------------------------------
My key fingerprint: d1:03:f5:32:26:ff:d7:3c:e4:42:e3:51:ec:92:78:b2


More information about the ffmpeg-devel mailing list