From b24cb56dd49cccd9025b668584203e6dbfe5b4a5 Mon Sep 17 00:00:00 2001 From: wang-bin Date: Sat, 6 Feb 2016 12:41:40 +0800 Subject: [PATCH] vo: remove qimage member in qpainter renderer --- src/QtAV/QPainterRenderer.h | 2 +- src/output/video/GraphicsItemRenderer.cpp | 2 +- src/output/video/QPainterRenderer.cpp | 48 ++++++++++------------- src/output/video/WidgetRenderer.cpp | 2 +- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/QtAV/QPainterRenderer.h b/src/QtAV/QPainterRenderer.h index 3ff71cec..b051d65d 100644 --- a/src/QtAV/QPainterRenderer.h +++ b/src/QtAV/QPainterRenderer.h @@ -35,7 +35,7 @@ public: QPainterRenderer(); bool isSupported(VideoFormat::PixelFormat pixfmt) const Q_DECL_OVERRIDE; protected: - bool prepareFrame(const VideoFrame& frame); + bool preparePixmap(const VideoFrame& frame); void drawBackground() Q_DECL_OVERRIDE; //draw the current frame using the current paint engine. called by paintEvent() void drawFrame() Q_DECL_OVERRIDE; diff --git a/src/output/video/GraphicsItemRenderer.cpp b/src/output/video/GraphicsItemRenderer.cpp index a9dfd967..9d4fa75f 100644 --- a/src/output/video/GraphicsItemRenderer.cpp +++ b/src/output/video/GraphicsItemRenderer.cpp @@ -124,7 +124,7 @@ bool GraphicsItemRenderer::receiveFrame(const VideoFrame& frame) } else #endif { - prepareFrame(frame); + preparePixmap(frame); } scene()->update(sceneBoundingRect()); //TODO: thread? //update(); //does not cause an immediate paint. my not redraw. diff --git a/src/output/video/QPainterRenderer.cpp b/src/output/video/QPainterRenderer.cpp index 26602b16..dbbadb6d 100644 --- a/src/output/video/QPainterRenderer.cpp +++ b/src/output/video/QPainterRenderer.cpp @@ -43,34 +43,30 @@ bool QPainterRenderer::isSupported(VideoFormat::PixelFormat pixfmt) const return VideoFormat::imageFormatFromPixelFormat(pixfmt) != QImage::Format_Invalid; } -bool QPainterRenderer::prepareFrame(const VideoFrame &frame) +bool QPainterRenderer::preparePixmap(const VideoFrame &frame) { DPTR_D(QPainterRenderer); - /* - * QImage constructed from memory do not deep copy the data, data should be available throughout - * image's lifetime and not be modified. painting image happens in main thread, we must ensure the - * image data is not changed if not use the original frame size, so we need the lock. - * In addition, the data passed by ref, so even if we lock, the original data may changed in decoder - * (ImageConverter), so we need a copy of this data(not deep copy) to ensure the image's data not changes before it - * is painted. - * But if we use the fixed original frame size, the data address and size always the same, so we can - * avoid the lock and use the ref data directly and safely - */ // already locked in a larger scope of receive() - //If use d.data.data() it will eat more cpu, deep copy? - if (frame.constBits(0)) + QImage::Format imgfmt = frame.imageFormat(); + if (frame.constBits(0)) { d.video_frame = frame; - else - d.video_frame = frame.to(frame.pixelFormat()); // assume frame format is supported - // DO NOT use frameData().data() because it's temp ptr while QImage does not deep copy the data - QImage::Format imgfmt = d.video_frame.imageFormat(); + } else { + if (imgfmt == QImage::Format_Invalid) { + d.video_frame = frame.to(VideoFormat::Format_RGB32); + imgfmt = d.video_frame.imageFormat(); + } else { + d.video_frame = frame.to(frame.pixelFormat()); + } + } const bool swapRGB = (int)imgfmt < 0; if (swapRGB) { imgfmt = (QImage::Format)(-imgfmt); } - d.image = QImage((uchar*)d.video_frame.constBits(), d.video_frame.width(), d.video_frame.height(), d.video_frame.bytesPerLine(), imgfmt); + // DO NOT use frameData().data() because it's temp ptr while d.image does not deep copy the data + QImage image = QImage((uchar*)d.video_frame.constBits(), d.video_frame.width(), d.video_frame.height(), d.video_frame.bytesPerLine(), imgfmt); if (swapRGB) - d.image = d.image.rgbSwapped(); + image = image.rgbSwapped(); + d.pixmap = QPixmap::fromImage(image); //Format_RGB32 is fast. see document return true; } @@ -101,20 +97,17 @@ void QPainterRenderer::drawFrame() DPTR_D(QPainterRenderer); if (!d.painter) return; - if (d.image.isNull()) + if (d.pixmap.isNull()) return; QRect roi = realROI(); if (orientation() == 0) { //assume that the image data is already scaled to out_size(NOT renderer size!) if (roi.size() == d.out_rect.size()) { - d.painter->drawPixmap(d.out_rect.topLeft(), QPixmap::fromImage(d.image), roi); - //d.painter->drawImage(d.out_rect.topLeft(), d.image, roi); + d.painter->drawPixmap(d.out_rect.topLeft(), d.pixmap, roi); } else { - // drawPixmap() is faster for on screen painting - d.painter->drawPixmap(d.out_rect, QPixmap::fromImage(d.image), roi); - //d.painter->drawImage(d.out_rect, d.image, roi); + d.painter->drawPixmap(d.out_rect, d.pixmap, roi); //what's the difference? - //d.painter->drawImage(QPoint(), image.scaled(d.renderer_width, d.renderer_height)); + //d.painter->drawPixmap(QPoint(), d.pixmap.scaled(d.renderer_width, d.renderer_height)); } return; } @@ -129,8 +122,7 @@ void QPainterRenderer::drawFrame() d.painter->scale((qreal)d.out_rect.width()/(qreal)rendererWidth(), (qreal)d.out_rect.height()/(qreal)rendererHeight()); d.painter->rotate(orientation()); d.painter->translate(-rendererWidth()/2, -rendererHeight()/2); - d.painter->drawPixmap(QRect(0, 0, rendererWidth(), rendererHeight()), QPixmap::fromImage(d.image), roi); - //d.painter->drawImage(QRect(0, 0, rendererWidth(), rendererHeight()), d.image, roi); + d.painter->drawPixmap(QRect(0, 0, rendererWidth(), rendererHeight()), d.pixmap, roi); d.painter->restore(); } diff --git a/src/output/video/WidgetRenderer.cpp b/src/output/video/WidgetRenderer.cpp index cb268332..f98f2f29 100644 --- a/src/output/video/WidgetRenderer.cpp +++ b/src/output/video/WidgetRenderer.cpp @@ -78,7 +78,7 @@ WidgetRenderer::WidgetRenderer(WidgetRendererPrivate &d, QWidget *parent, Qt::Wi bool WidgetRenderer::receiveFrame(const VideoFrame &frame) { - prepareFrame(frame); + preparePixmap(frame); updateUi(); /* * workaround for the widget not updated if has parent. don't know why it works and why update() can't