wang-bin / QtAV

A cross-platform multimedia framework based on Qt and FFmpeg. 基于Qt和FFmpeg的跨平台高性能音视频播放框架. Recommand to use new sdk https://github.com/wang-bin/mdk-sdk
http://qtav.org
3.94k stars 1.5k forks source link

Crash on delete with threaded render loop (Win/VS2013) #492

Open ps17092012 opened 9 years ago

ps17092012 commented 9 years ago

There is a crash whenever deleting a QML Video item once it has been playing, both when trying to delete it manually and when using QQuickView::setSource to set a new QML source.

Win7, QtAV VS2013, Qt 5.5, threaded render loop (QSG_RENDER_LOOP=threaded). Happens with both OpenGL and ANGLE rendering.

It works fine with the default windows render loop, but I would like to use the threaded loop for performance reasons.

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/26027182-crash-on-delete-with-threaded-render-loop-win-vs2013?utm_campaign=plugin&utm_content=tracker%2F307703&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F307703&utm_medium=issues&utm_source=github).
wang-bin commented 9 years ago

complete sample code please

ps17092012 commented 9 years ago

Here is a minimal example, just adjust the video path and run with set QSG_RENDER_LOOP=threaded qmlscene.exe test.qml Pressing D will delete the video player, pressing Q quit. Both lead to a crash.

import QtQuick 2.3
import QtAV 1.6

Item {
    width: 400
    height: 300

    Video {
        id: videoplayer
        autoPlay: true
        anchors.fill: parent
        source: "file:///C:/path/to/video.mp4"
    }

    focus: true
    Keys.onPressed: {
        if(event.key === Qt.Key_Q) {
            Qt.quit();
        }
        if(event.key === Qt.Key_D) {
            videoplayer.destroy();
        }
    }
}
wang-bin commented 9 years ago

confirmed on windows

ps17092012 commented 9 years ago

Did you have a chance to look into this issue yet? I tried using some workarounds (e.g. stopping the video first, setting an empty source), but nothing seems to help.

wang-bin commented 9 years ago

I can continue on the weekend. I'm curious why you have to destroy the object

ps17092012 commented 9 years ago

I am working on an application that has to visualize user-defined content. The user can "design" their own layouts, containing Videos, Images, Texts and more. The active layout can be changed (or a completely different layout can be loaded) during application runtime, so I dynamically create and destroy the items.

ps17092012 commented 9 years ago

I maybe found a workaround: If I set NULL as the player's parent, move it to the render thread (with moveToThread()) and then delete, it does not crash.

I will do some more testing when I get a chance, I am not sure if this approach is safe in any way ;)

wang-bin commented 9 years ago

Tell me more details about your workaround? There are some unsafe code in QuickFBORenderer.cpp which may crash the program. I also tested on linux. But even if I remove all the contents in FBORenderer functions, it still crashes a lot and I don't know how to debug.

0   QSGOpaqueTextureMaterialShader::updateState(QSGMaterialShader::RenderState const&, QSGMaterial*, QSGMaterial*)  /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b373c2  
1   QSGBatchRenderer::Renderer::renderMergedBatch(QSGBatchRenderer::Batch const*)   /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b1f1dd  
2   QSGBatchRenderer::Renderer::renderBatches() /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b20b0d  
3   QSGBatchRenderer::Renderer::render()    /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b2636a  
4   QSGRenderer::renderScene(QSGBindable const&)    /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b31456  
5   QSGRenderer::renderScene(unsigned int)  /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b3190b  
6   QSGRenderContext::renderNextFrame(QSGRenderer*, unsigned int)   /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b4031e  
7   QQuickWindowPrivate::renderSceneGraph(QSize const&) /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b8c0cc  
8   ??  /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b5d986  
9   ??  /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5      0x7ffff7b5f360  
10  ??  /usr/lib/x86_64-linux-gnu/libQt5Core.so.5       0x7ffff6bccb0e  
11  start_thread        333 0x7ffff65ba6aa  
12  clone       109 0x7ffff5a4eeed  
ps17092012 commented 9 years ago

About the workaround: I have the qml Video in an Item like this:

Item {
    // other items
    Item {
        id: container
        Video {
            // [...]
        }
    }
}

To delete the item without a crash, I do the following:

container->setParent(NULL); // container is the item around the Video
container->setParentItem(NULL);
container->moveToThread(viewer->openglContext()->thread()); // viewer is the QQuickView
delete container;

I still get a crash, if I do this to more than 1 video at once.

ps17092012 commented 8 years ago

I might have found one potential cause of crashes during threaded rendering: I have a RotationAnimator running in my application. This is one of the new Animation types that runs on the render thread even when the GUI thread is blocked. So the scene graph tries to render new frames, somewhere in the middle of the video being deleted. If i remove the Animator, the crashes seem to be gone for now, or at least way less.

I can probably do some more testing next week