summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/multimedia/video/qvideoframe.cpp4
-rw-r--r--src/multimedia/video/qvideotexturehelper.cpp60
-rw-r--r--src/multimedia/video/qvideotexturehelper_p.h9
-rw-r--r--tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp38
4 files changed, 60 insertions, 51 deletions
diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp
index 8f95706bb..a120d850b 100644
--- a/src/multimedia/video/qvideoframe.cpp
+++ b/src/multimedia/video/qvideoframe.cpp
@@ -291,7 +291,7 @@ QVideoFrame::QVideoFrame(const QVideoFrameFormat &format)
// Check the memory was successfully allocated.
if (!data.isEmpty())
- d->buffer = new QMemoryVideoBuffer(data, textureDescription->stride*format.frameWidth());
+ d->buffer = new QMemoryVideoBuffer(data, textureDescription->strideForWidth(format.frameWidth()));
}
}
@@ -751,6 +751,8 @@ int QVideoFrame::planeCount() const
*/
quint64 QVideoFrame::textureHandle(int plane) const
{
+ if (!d->buffer)
+ return 0;
return d->buffer->textureHandle(plane);
}
diff --git a/src/multimedia/video/qvideotexturehelper.cpp b/src/multimedia/video/qvideotexturehelper.cpp
index 77ad98f3e..4ff64a3e4 100644
--- a/src/multimedia/video/qvideotexturehelper.cpp
+++ b/src/multimedia/video/qvideotexturehelper.cpp
@@ -46,166 +46,170 @@ namespace QVideoTextureHelper
static const TextureDescription descriptions[QVideoFrameFormat::NPixelFormats] = {
// Format_Invalid
{ 0, 0,
- [](QSize) { return 0; },
+ [](int, int) { return 0; },
{ QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat},
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_ARGB32
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_ARGB32_Premultiplied
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_RGB32
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_BGRA32
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_BGRA32_Premultiplied
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_ABGR32
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_BGR32
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_AYUV444
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_AYUV444_Premultiplied
{ 1, 4,
- [](QSize s) { return 4*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_YUV420P
{ 3, 1,
- [](QSize s) { return 3*s.width()*s.height() / 2; },
+ [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); },
{ QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
{ { 1, 1 }, { 2, 2 }, { 2, 2 } }
},
// Format_YUV422P
{ 3, 1,
- [](QSize s) { return 2*s.width()*s.height(); },
+ [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); },
{ QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
{ { 1, 1 }, { 2, 1 }, { 2, 1 } }
},
// Format_YV12
{ 3, 1,
- [](QSize s) { return 2*s.width()*s.height(); },
+ [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); },
{ QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
{ { 1, 1 }, { 2, 2 }, { 2, 2 } }
},
// Format_UYVY
{ 1, 2,
- [](QSize s) { return 2*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 2, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_YUYV
{ 1, 2,
- [](QSize s) { return 2*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::BGRA8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 2, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_NV12
{ 2, 1,
- [](QSize s) { return 3*s.width()*s.height() / 2; },
+ [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); },
{ QRhiTexture::R8, QRhiTexture::RG8, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 2, 2 }, { 1, 1 } }
},
// Format_NV21
{ 2, 1,
- [](QSize s) { return 3*s.width()*s.height() / 2; },
+ [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); },
{ QRhiTexture::R8, QRhiTexture::RG8, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 2, 2 }, { 1, 1 } }
},
// Format_IMC1
{ 3, 1,
- [](QSize s) {
+ [](int stride, int height) {
// IMC1 requires that U and V components are aligned on a multiple of 16 lines
- return s.width()*((s.height()*3/2 + 15) & ~15 + s.height()/2);
+ int h = (height + 15) & ~15;
+ h += 2*((h/2) + 15 & ~15);
+ return stride * h;
},
{ QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
{ { 1, 1 }, { 2, 2 }, { 2, 2 } }
},
// Format_IMC2
{ 2, 1,
- [](QSize s) { return 2*s.width()*s.height(); },
+ [](int stride, int height) { return 2*stride*height; },
{ QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 2 }, { 1, 1 } }
},
// Format_IMC3
{ 3, 1,
- [](QSize s) {
+ [](int stride, int height) {
// IMC3 requires that U and V components are aligned on a multiple of 16 lines
- return s.width()*((s.height()*3/2 + 15) & ~15 + s.height()/2);
+ int h = (height + 15) & ~15;
+ h += 2*((h/2) + 15 & ~15);
+ return stride * h;
},
{ QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::R8 },
{ { 1, 1 }, { 2, 2 }, { 2, 2 } }
},
// Format_IMC4
{ 2, 1,
- [](QSize s) { return 2*s.width()*s.height(); },
+ [](int stride, int height) { return 2*stride*height; },
{ QRhiTexture::R8, QRhiTexture::R8, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 2 }, { 1, 1 } }
},
// Format_Y8
{ 1, 1,
- [](QSize s) { return s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::R8, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_Y16
{ 1, 2,
- [](QSize s) { return 2*s.width()*s.height(); },
+ [](int stride, int height) { return stride*height; },
{ QRhiTexture::R16, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
},
// Format_P010
{ 2, 2,
- [](QSize s) { return 3*s.width()*s.height(); },
+ [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); },
{ QRhiTexture::R16, QRhiTexture::RG16, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 2, 2 }, { 1, 1 } }
},
// Format_P016
{ 2, 2,
- [](QSize s) { return 3*s.width()*s.height(); },
+ [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); },
{ QRhiTexture::R16, QRhiTexture::RG16, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 2, 2 }, { 1, 1 } }
},
// Format_Jpeg
{ 1, 0,
- [](QSize) { return 0; },
+ [](int, int) { return 0; },
{ QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat, QRhiTexture::UnknownFormat },
{ { 1, 1 }, { 1, 1 }, { 1, 1 } }
}
diff --git a/src/multimedia/video/qvideotexturehelper_p.h b/src/multimedia/video/qvideotexturehelper_p.h
index e0b72243a..a984101e5 100644
--- a/src/multimedia/video/qvideotexturehelper_p.h
+++ b/src/multimedia/video/qvideotexturehelper_p.h
@@ -57,11 +57,14 @@ struct TextureDescription
int x;
int y;
};
- using BytesForSize = int(*)(QSize s);
+ using BytesRequired = int(*)(int stride, int height);
+
+ inline int strideForWidth(int width) const { return (width*strideFactor + 15) & ~15; }
+ inline int bytesForSize(QSize s) const { return bytesRequired(strideForWidth(s.width()), s.height()); }
int nplanes;
- int stride;
- BytesForSize bytesForSize;
+ int strideFactor;
+ BytesRequired bytesRequired;
QRhiTexture::Format textureFormat[maxPlanes];
SizeScale sizeScale[maxPlanes];
};
diff --git a/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp b/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp
index db888fc60..fe933bdbb 100644
--- a/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp
+++ b/tests/auto/unit/multimedia/qvideoframe/tst_qvideoframe.cpp
@@ -198,10 +198,10 @@ void tst_QVideoFrame::createInvalid_data()
QTest::addColumn<QSize>("size");
QTest::addColumn<QVideoFrameFormat::PixelFormat>("pixelFormat");
- QTest::newRow("64x64 ARGB32 0 size")
+ QTest::newRow("0x64 ARGB32 0 size")
<< QSize(0, 64)
<< QVideoFrameFormat::Format_ARGB32;
- QTest::newRow("32x256 YUV420P 0 size")
+ QTest::newRow("32x0 YUV420P 0 size")
<< QSize(32, 0)
<< QVideoFrameFormat::Format_YUV420P;
}
@@ -622,12 +622,12 @@ void tst_QVideoFrame::mapPlanes_data()
<< (QList<int>() << 512 << 765);
QTest::newRow("Format_YUV420P")
<< QVideoFrame(QVideoFrameFormat(QSize(60, 64), QVideoFrameFormat::Format_YUV420P))
- << (QList<int>() << 64 << 62 << 62)
- << (QList<int>() << 4096 << 6080);
+ << (QList<int>() << 64 << 32 << 32)
+ << (QList<int>() << 4096 << 5120);
QTest::newRow("Format_YV12")
<< QVideoFrame(QVideoFrameFormat(QSize(60, 64), QVideoFrameFormat::Format_YV12))
- << (QList<int>() << 64 << 62 << 62)
- << (QList<int>() << 4096 << 6080);
+ << (QList<int>() << 64 << 32 << 32)
+ << (QList<int>() << 4096 << 5120);
QTest::newRow("Format_NV12")
<< QVideoFrame(QVideoFrameFormat(QSize(60, 64), QVideoFrameFormat::Format_NV12))
<< (QList<int>() << 64 << 64)
@@ -654,7 +654,7 @@ void tst_QVideoFrame::mapPlanes_data()
<< (QList<int>() << 4096 << 6144);
QTest::newRow("Format_ARGB32")
<< QVideoFrame(QVideoFrameFormat(QSize(60, 64), QVideoFrameFormat::Format_ARGB32))
- << (QList<int>() << 256)
+ << (QList<int>() << 240)
<< (QList<int>());
}
@@ -772,10 +772,10 @@ void tst_QVideoFrame::formatConversion_data()
<< QImage::Format_Invalid
<< QVideoFrameFormat::Format_IMC4;
QTest::newRow("QVideoFrameFormat::Format_Y8")
- << QImage::Format_Invalid
+ << QImage::Format_Grayscale8
<< QVideoFrameFormat::Format_Y8;
QTest::newRow("QVideoFrameFormat::Format_Y16")
- << QImage::Format_Invalid
+ << QImage::Format_Grayscale16
<< QVideoFrameFormat::Format_Y16;
QTest::newRow("QVideoFrameFormat::Format_Jpeg")
<< QImage::Format_Invalid
@@ -912,52 +912,52 @@ void tst_QVideoFrame::image_data()
QTest::newRow("64x64 BGRA32")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_BGRA32
- << QImage::Format_ARGB32;
+ << QImage::Format_ARGB32_Premultiplied;
QTest::newRow("64x64 BGRA32_Premultiplied")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_BGRA32_Premultiplied
- << QImage::Format_ARGB32;
+ << QImage::Format_ARGB32_Premultiplied;
QTest::newRow("64x64 BGR32")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_BGR32
- << QImage::Format_ARGB32;
+ << QImage::Format_RGB32;
QTest::newRow("64x64 AYUV444")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_AYUV444
- << QImage::Format_ARGB32;
+ << QImage::Format_ARGB32_Premultiplied;
QTest::newRow("64x64 YUV420P")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_YUV420P
- << QImage::Format_ARGB32;
+ << QImage::Format_RGB32;
QTest::newRow("64x64 YV12")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_YV12
- << QImage::Format_ARGB32;
+ << QImage::Format_RGB32;
QTest::newRow("64x64 UYVY")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_UYVY
- << QImage::Format_ARGB32;
+ << QImage::Format_RGB32;
QTest::newRow("64x64 YUYV")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_YUYV
- << QImage::Format_ARGB32;
+ << QImage::Format_RGB32;
QTest::newRow("64x64 NV12")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_NV12
- << QImage::Format_ARGB32;
+ << QImage::Format_RGB32;
QTest::newRow("64x64 NV21")
<< QSize(64, 64)
<< QVideoFrameFormat::Format_NV21
- << QImage::Format_ARGB32;
+ << QImage::Format_RGB32;
}
void tst_QVideoFrame::image()