mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
- Image format NV12 and I420 added
- Flip mode - Scaling factor for MJPEG - VSCode (compile before run) - CI (push) dependency libjpeg-turbo added
This commit is contained in:
@@ -4,9 +4,12 @@
|
||||
static PixelFormat GetPixelFormatForGuid(const GUID guid)
|
||||
{
|
||||
if (IsEqualGUID(guid, MFVideoFormat_RGB32)) return PixelFormat::RGB32;
|
||||
if (IsEqualGUID(guid, MFVideoFormat_RGB24)) return PixelFormat::BGR24;
|
||||
if (IsEqualGUID(guid, MFVideoFormat_YUY2)) return PixelFormat::YUYV;
|
||||
if (IsEqualGUID(guid, MFVideoFormat_UYVY)) return PixelFormat::UYVY;
|
||||
if (IsEqualGUID(guid, MFVideoFormat_MJPG)) return PixelFormat::MJPEG;
|
||||
if (IsEqualGUID(guid, MFVideoFormat_NV12)) return PixelFormat::NV12;
|
||||
if (IsEqualGUID(guid, MFVideoFormat_I420)) return PixelFormat::I420;
|
||||
return PixelFormat::NO_CHANGE;
|
||||
};
|
||||
|
||||
@@ -40,7 +43,7 @@ MFGrabber::MFGrabber(const QString & device, unsigned width, unsigned height, un
|
||||
setInput(input);
|
||||
setWidthHeight(width, height);
|
||||
setFramerate(fps);
|
||||
// setDeviceVideoStandard(device, videoStandard);
|
||||
// setDeviceVideoStandard(device, videoStandard); // TODO
|
||||
|
||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
_hr = MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET);
|
||||
@@ -134,7 +137,7 @@ bool MFGrabber::init()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strict)
|
||||
if (strict && (val.fps <= 60 || _fps != 15))
|
||||
foundIndex = i;
|
||||
}
|
||||
|
||||
@@ -394,16 +397,32 @@ bool MFGrabber::init_device(QString deviceName, DevicePropertiesItem props)
|
||||
}
|
||||
break;
|
||||
|
||||
case PixelFormat::RGB32:
|
||||
case PixelFormat::BGR24:
|
||||
case PixelFormat::MJPEG:
|
||||
{
|
||||
_frameByteSize = props.x * props.y * 4;
|
||||
_frameByteSize = props.x * props.y * 3;
|
||||
_lineLength = props.x * 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case PixelFormat::MJPEG:
|
||||
case PixelFormat::RGB32:
|
||||
{
|
||||
_lineLength = props.x * 3;
|
||||
_frameByteSize = props.x * props.y * 4;
|
||||
_lineLength = props.x * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case PixelFormat::NV12:
|
||||
{
|
||||
_frameByteSize = (6 * props.x * props.y) / 4;
|
||||
_lineLength = props.x;
|
||||
}
|
||||
break;
|
||||
|
||||
case PixelFormat::I420:
|
||||
{
|
||||
_frameByteSize = (6 * props.x * props.y) / 4;
|
||||
_lineLength = props.x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -499,6 +518,8 @@ void MFGrabber::enumVideoCaptureDevices()
|
||||
di.pf = pixelformat;
|
||||
di.guid = format;
|
||||
properties.valid.append(di);
|
||||
|
||||
Debug(_log, "%s %d x %d @ %d fps (%s)", QSTRING_CSTR(dev), di.x, di.y, di.fps, QSTRING_CSTR(pixelFormatToString(di.pf)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -74,7 +74,6 @@ public:
|
||||
hrStatus = pSample->ConvertToContiguousBuffer(&buffer);
|
||||
if (SUCCEEDED(hrStatus))
|
||||
{
|
||||
|
||||
BYTE* data = nullptr;
|
||||
DWORD maxLength = 0, currentLength = 0;
|
||||
|
||||
@@ -89,11 +88,11 @@ public:
|
||||
else
|
||||
error = QString("buffer->Lock failed => %1").arg(hrStatus);
|
||||
|
||||
SAFE_RELEASE(buffer);
|
||||
}
|
||||
else
|
||||
error = QString("pSample->ConvertToContiguousBuffer failed => %1").arg(hrStatus);
|
||||
|
||||
SAFE_RELEASE(buffer);
|
||||
}
|
||||
else
|
||||
error = "pSample is NULL";
|
||||
|
@@ -3,13 +3,15 @@
|
||||
|
||||
volatile bool MFThread::_isActive = false;
|
||||
|
||||
MFThread::MFThread():
|
||||
_localData(nullptr),
|
||||
_localDataSize(0),
|
||||
_decompress(nullptr),
|
||||
_isBusy(false),
|
||||
_semaphore(1),
|
||||
_imageResampler()
|
||||
MFThread::MFThread()
|
||||
: _localData(nullptr)
|
||||
, _localDataSize(0)
|
||||
, _decompress(nullptr)
|
||||
, _scalingFactorsCount(0)
|
||||
, _scalingFactors(nullptr)
|
||||
, _isBusy(false)
|
||||
, _semaphore(1)
|
||||
, _imageResampler()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,6 +52,7 @@ void MFThread::setup(
|
||||
_imageResampler.setCropping(cropLeft, cropRight, cropTop, cropBottom);
|
||||
_imageResampler.setHorizontalPixelDecimation(_pixelDecimation);
|
||||
_imageResampler.setVerticalPixelDecimation(_pixelDecimation);
|
||||
_imageResampler.setFlipMode(FlipMode::HORIZONTAL);
|
||||
|
||||
if (size > _localDataSize)
|
||||
{
|
||||
@@ -110,6 +113,7 @@ void MFThread::processImageMjpeg()
|
||||
{
|
||||
_decompress = tjInitDecompress();
|
||||
_scalingFactors = tjGetScalingFactors (&_scalingFactorsCount);
|
||||
tjhandle handle=NULL;
|
||||
}
|
||||
|
||||
if (tjDecompressHeader2(_decompress, _localData, _size, &_width, &_height, &_subsamp) != 0)
|
||||
@@ -167,6 +171,8 @@ void MFThread::processImageMjpeg()
|
||||
unsigned char* source = (unsigned char*)srcImage.memptr() + (y + _cropTop)*srcImage.width()*3 + _cropLeft*3;
|
||||
unsigned char* dest = (unsigned char*)destImage.memptr() + y*destImage.width()*3;
|
||||
memcpy(dest, source, destImage.width()*3);
|
||||
free(source);
|
||||
free(dest);
|
||||
}
|
||||
|
||||
// emit
|
||||
|
@@ -10,23 +10,10 @@ ImageResampler::ImageResampler()
|
||||
, _cropTop(0)
|
||||
, _cropBottom(0)
|
||||
, _videoMode(VideoMode::VIDEO_2D)
|
||||
, _flipMode(FlipMode::NO_CHANGE)
|
||||
{
|
||||
}
|
||||
|
||||
ImageResampler::~ImageResampler()
|
||||
{
|
||||
}
|
||||
|
||||
void ImageResampler::setHorizontalPixelDecimation(int decimator)
|
||||
{
|
||||
_horizontalDecimation = decimator;
|
||||
}
|
||||
|
||||
void ImageResampler::setVerticalPixelDecimation(int decimator)
|
||||
{
|
||||
_verticalDecimation = decimator;
|
||||
}
|
||||
|
||||
void ImageResampler::setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom)
|
||||
{
|
||||
_cropLeft = cropLeft;
|
||||
@@ -35,15 +22,12 @@ void ImageResampler::setCropping(int cropLeft, int cropRight, int cropTop, int c
|
||||
_cropBottom = cropBottom;
|
||||
}
|
||||
|
||||
void ImageResampler::setVideoMode(VideoMode mode)
|
||||
{
|
||||
_videoMode = mode;
|
||||
}
|
||||
|
||||
void ImageResampler::processImage(const uint8_t * data, int width, int height, int lineLength, PixelFormat pixelFormat, Image<ColorRgb> &outputImage) const
|
||||
{
|
||||
int cropRight = _cropRight;
|
||||
int cropBottom = _cropBottom;
|
||||
int xDestFlip = 0, yDestFlip = 0;
|
||||
int uOffset, vOffset;
|
||||
|
||||
// handle 3D mode
|
||||
switch (_videoMode)
|
||||
@@ -67,11 +51,40 @@ void ImageResampler::processImage(const uint8_t * data, int width, int height, i
|
||||
for (int yDest = 0, ySource = _cropTop + (_verticalDecimation >> 1); yDest < outputHeight; ySource += _verticalDecimation, ++yDest)
|
||||
{
|
||||
int yOffset = lineLength * ySource;
|
||||
if (pixelFormat == PixelFormat::NV12)
|
||||
{
|
||||
uOffset = (height + ySource / 2) * lineLength;
|
||||
}
|
||||
else if (pixelFormat == PixelFormat::I420)
|
||||
{
|
||||
uOffset = height * lineLength + ((ySource * lineLength) / 4);
|
||||
vOffset = ((5 * height * lineLength) * 4) + ((ySource * lineLength) / 4);
|
||||
}
|
||||
|
||||
for (int xDest = 0, xSource = _cropLeft + (_horizontalDecimation >> 1); xDest < outputWidth; xSource += _horizontalDecimation, ++xDest)
|
||||
{
|
||||
ColorRgb & rgb = outputImage(xDest, yDest);
|
||||
switch (_flipMode)
|
||||
{
|
||||
case FlipMode::HORIZONTAL:
|
||||
|
||||
xDestFlip = xDest;
|
||||
yDestFlip = outputHeight-yDest-1;
|
||||
break;
|
||||
case FlipMode::VERTICAL:
|
||||
xDestFlip = outputWidth-xDest-1;
|
||||
yDestFlip = yDest;
|
||||
break;
|
||||
case FlipMode::BOTH:
|
||||
xDestFlip = outputWidth-xDest-1;
|
||||
yDestFlip = outputHeight-yDest-1;
|
||||
break;
|
||||
case FlipMode::NO_CHANGE:
|
||||
xDestFlip = xDest;
|
||||
yDestFlip = yDest;
|
||||
break;
|
||||
}
|
||||
|
||||
ColorRgb &rgb = outputImage(xDestFlip, yDestFlip);
|
||||
switch (pixelFormat)
|
||||
{
|
||||
case PixelFormat::UYVY:
|
||||
@@ -124,6 +137,25 @@ void ImageResampler::processImage(const uint8_t * data, int width, int height, i
|
||||
rgb.red = data[index+2];
|
||||
}
|
||||
break;
|
||||
case PixelFormat::NV12:
|
||||
{
|
||||
int index = yOffset + xSource;
|
||||
uint8_t y = data[index];
|
||||
uint8_t u = data[uOffset + ((xSource >> 1) << 1)];
|
||||
uint8_t v = data[uOffset + ((xSource >> 1) << 1) + 1];
|
||||
ColorSys::yuv2rgb(y, u, v, rgb.red, rgb.green, rgb.blue);
|
||||
}
|
||||
break;
|
||||
case PixelFormat::I420:
|
||||
{
|
||||
int index = yOffset + xSource;
|
||||
uint8_t y = data[index];
|
||||
uint8_t u = data[uOffset + (xSource >> 1)];
|
||||
uint8_t v = data[vOffset + (xSource >> 1)];
|
||||
ColorSys::yuv2rgb(y, u, v, rgb.red, rgb.green, rgb.blue);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_JPEG_DECODER
|
||||
case PixelFormat::MJPEG:
|
||||
break;
|
||||
|
Reference in New Issue
Block a user