add support for NV12 camera format

This commit is contained in:
Arisotura 2022-10-02 15:38:31 +02:00
parent 23fc51f4bd
commit 3e7108b2e1
2 changed files with 65 additions and 5 deletions

View File

@ -35,9 +35,22 @@ void CameraFrameDumper::present(const QVideoFrame& _frame)
if (!frame.map(QVideoFrame::ReadOnly)) if (!frame.map(QVideoFrame::ReadOnly))
return; return;
if (!frame.isReadable()) if (!frame.isReadable())
{
frame.unmap();
return; return;
}
cam->feedFrame((u32*)frame.bits(0), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrameFormat::Format_YUYV); switch (frame.pixelFormat())
{
case QVideoFrameFormat::Format_XRGB8888:
case QVideoFrameFormat::Format_YUYV:
cam->feedFrame((u32*)frame.bits(0), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrameFormat::Format_YUYV);
break;
case QVideoFrameFormat::Format_NV12:
cam->feedFrame_NV12((u8*)frame.bits(0), (u8*)frame.bits(1), frame.width(), frame.height());
break;
}
frame.unmap(); frame.unmap();
} }
@ -55,9 +68,22 @@ bool CameraFrameDumper::present(const QVideoFrame& _frame)
if (!frame.map(QAbstractVideoBuffer::ReadOnly)) if (!frame.map(QAbstractVideoBuffer::ReadOnly))
return false; return false;
if (!frame.isReadable()) if (!frame.isReadable())
{
frame.unmap();
return false; return false;
}
cam->feedFrame((u32*)frame.bits(), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrame::Format_YUYV); switch (frame.pixelFormat())
{
case QVideoFrame::Format_RGB32:
case QVideoFrame::Format_YUYV:
cam->feedFrame((u32*)frame.bits(0), frame.width(), frame.height(), frame.pixelFormat() == QVideoFrame::Format_YUYV);
break;
case QVideoFrame::Format_NV12:
cam->feedFrame_NV12((u8*)frame.bits(0), (u8*)frame.bits(1), frame.width(), frame.height());
break;
}
frame.unmap(); frame.unmap();
@ -70,6 +96,7 @@ QList<QVideoFrame::PixelFormat> CameraFrameDumper::supportedPixelFormats(QAbstra
ret.append(QVideoFrame::Format_RGB32); ret.append(QVideoFrame::Format_RGB32);
ret.append(QVideoFrame::Format_YUYV); ret.append(QVideoFrame::Format_YUYV);
ret.append(QVideoFrame::Format_NV12);
return ret; return ret;
} }
@ -94,6 +121,7 @@ CameraManager::CameraManager(int num, int width, int height, bool yuv) : QObject
int fbsize = frameWidth * frameHeight; int fbsize = frameWidth * frameHeight;
if (yuv) fbsize /= 2; if (yuv) fbsize /= 2;
frameBuffer = new u32[fbsize]; frameBuffer = new u32[fbsize];
tempFrameBuffer = new u32[fbsize];
inputType = -1; inputType = -1;
xFlip = false; xFlip = false;
@ -181,6 +209,7 @@ void CameraManager::init()
for (const QCameraFormat& item : supported) for (const QCameraFormat& item : supported)
{ {
if (item.pixelFormat() != QVideoFrameFormat::Format_YUYV && if (item.pixelFormat() != QVideoFrameFormat::Format_YUYV &&
item.pixelFormat() != QVideoFrameFormat::Format_NV12 &&
item.pixelFormat() != QVideoFrameFormat::Format_XRGB8888) item.pixelFormat() != QVideoFrameFormat::Format_XRGB8888)
continue; continue;
@ -223,6 +252,7 @@ void CameraManager::init()
for (const QCameraViewfinderSettings& item : supported) for (const QCameraViewfinderSettings& item : supported)
{ {
if (item.pixelFormat() != QVideoFrame::Format_YUYV && if (item.pixelFormat() != QVideoFrame::Format_YUYV &&
item.pixelFormat() != QVideoFrame::Format_NV12 &&
item.pixelFormat() != QVideoFrame::Format_RGB32) item.pixelFormat() != QVideoFrame::Format_RGB32)
continue; continue;
@ -387,6 +417,34 @@ void CameraManager::feedFrame(u32* frame, int width, int height, bool yuv)
frameMutex.unlock(); frameMutex.unlock();
} }
void CameraManager::feedFrame_NV12(u8* planeY, u8* planeUV, int width, int height)
{
for (int y = 0; y < frameHeight; y++)
{
int sy = (y * height) / frameHeight;
for (int x = 0; x < frameWidth; x+=2)
{
int sx1 = (x * width) / frameWidth;
int sx2 = ((x+1) * width) / frameWidth;
u32 val;
u8 y1 = planeY[(sy*width) + sx1];
u8 y2 = planeY[(sy*width) + sx2];
int uvpos = (((sy>>1)*(width>>1)) + (sx1>>1));
u8 u = planeUV[uvpos << 1];
u8 v = planeUV[(uvpos << 1) + 1];
val = y1 | (u << 8) | (y2 << 16) | (v << 24);
tempFrameBuffer[((y*frameWidth) + x) >> 1] = val;
}
}
feedFrame(tempFrameBuffer, frameWidth, frameHeight, true);
}
void CameraManager::copyFrame_Straight(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight, bool xflip, bool yuv) void CameraManager::copyFrame_Straight(u32* src, int swidth, int sheight, u32* dst, int dwidth, int dheight, bool xflip, bool yuv)
{ {
if (yuv) if (yuv)

View File

@ -42,13 +42,13 @@ class CameraManager;
class CameraFrameDumper : public QVideoSink class CameraFrameDumper : public QVideoSink
{ {
Q_OBJECT Q_OBJECT
public: public:
CameraFrameDumper(QObject* parent = nullptr); CameraFrameDumper(QObject* parent = nullptr);
public slots: public slots:
void present(const QVideoFrame& frame); void present(const QVideoFrame& frame);
private: private:
CameraManager* cam; CameraManager* cam;
}; };
@ -92,6 +92,7 @@ public:
void captureFrame(u32* frame, int width, int height, bool yuv); void captureFrame(u32* frame, int width, int height, bool yuv);
void feedFrame(u32* frame, int width, int height, bool yuv); void feedFrame(u32* frame, int width, int height, bool yuv);
void feedFrame_NV12(u8* planeY, u8* planeUV, int width, int height);
signals: signals:
void camStartSignal(); void camStartSignal();
@ -119,6 +120,7 @@ private:
int frameWidth, frameHeight; int frameWidth, frameHeight;
bool frameFormatYUV; bool frameFormatYUV;
u32* frameBuffer; u32* frameBuffer;
u32* tempFrameBuffer;
QMutex frameMutex; QMutex frameMutex;
bool xFlip; bool xFlip;