c++ - 来自原始像素数据的损坏的 QImage

标签 c++ multithreading qt bitmap qimage

我的工作基于 this answer ,我正在尝试使用 Qt 的 QGLWidget 来呈现视频,但我遇到了一些问题。在我的视频解码线程中解码后立即保存帧时,结果很好:

intact frame

但是当画出来的时候,它被严重破坏了:

mangled frame

看起来好像正在复制图像,但复制没有完成,但是

  1. 我正在使用互斥体来确保在绘图代码绘制时图像未被触及。

  2. 我将指向 QImage 的指针传递给绘图代码,因此它应该是同一 block 内存。

在解码线程中我有以下内容:

/* Read in the frame up here, skipped for brevity */

// Set a new image
auto frameImage = make_shared<QImage>(nextFrame->getPixels(),
                                      nextFrame->getWidth(),
                                      nextFrame->getHeight(),
                                      QImage::Format_RGB888);

canvas->setImage(frameImage);
// Post a new order to repaint.
// Done this way because another thread cannot directly call repaint()
QCoreApplication::postEvent(canvas, new QPaintEvent(canvas->rect()));

然后,在 Canvas 中(派生自 QGLWidget):

void QGLCanvas::setImage(const std::shared_ptr<QImage>& image)
{
    // Keep the QGL canvas from drawing while we change the image
    lock_guard<mutex> pixelLock(pixelsMutex);
    img = image; // img is just a shared_ptr
}

void QGLCanvas::paintEvent(QPaintEvent*)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, 1);

    // Lock the image so that other threads can't access it at the same time
    lock_guard<mutex> pixelLock(pixelsMutex);
    painter.drawImage(this->rect(), *img);
}

这是怎么回事?

最佳答案

我忘记了 QImage 在给定像素数据时是浅拷贝,而不是深拷贝。只要 QImage 存在,就可以通过保持分配的实际帧数据来解决问题,如下所示:

void QGLCanvas::setFrame(const std::shared_ptr<VideoFrame>& newFrame)
{
    // Keep the QGL canvas from drawing while we change the image
    lock_guard<mutex> pixelLock(pixelsMutex);

    // Keep a shared_ptr reference to our frame data
    frame = newFrame;

    // Create a new QImage, which is just a shallow copy of the frame.
    img.reset(new QImage(frame->getPixels(),
                         frame->getWidth(),
                         frame->getHeight(),
                         QImage::Format_RGB888));
}

关于c++ - 来自原始像素数据的损坏的 QImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17428072/

相关文章:

c++ - 在多线程程序中禁用 boost::asio 上的线程是否安全?

c++ - Lua + SWIG 猴子补丁

c++ - 遍历 Boost multi_array View

iOS 确保每个 session 只调用一次函数

c++ - Malloc 宏重载也适用于对 malloc (C++) 的编译器调用吗?

c++ - 在 C++ 中使用并行化的预期加速是多少(不是 OpenMp,而是 <thread>)

c# - 无法处理 ThreadAbortException

javascript - 带背景图片的Qt Installer

c++ - 如何终止长时间运行的 Qt 线程

windows - 部署时 QSoundEffect 不播放声音