mirror of
https://github.com/wang-bin/QtAV.git
synced 2026-10-26 01:59:31 +08:00
vo: remove qimage member in qpainter renderer
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user