Modify Convert to scale as well

This commit is contained in:
hax0kartik 2020-03-28 15:17:19 -07:00
parent ba8d9ee768
commit 6886b2b375
4 changed files with 47 additions and 77 deletions

View File

@ -1,11 +1,7 @@
#include "zm.h" #include "zm.h"
#include "zm_signal.h" #include "zm_signal.h"
#include "zm_libvnc_camera.h" #include "zm_libvnc_camera.h"
extern "C" { #include "zm_swscale.h"
#include <libavutil/imgutils.h>
#include <libavutil/parseutils.h>
#include <libswscale/swscale.h>
}
#if HAVE_LIBVNC #if HAVE_LIBVNC
@ -25,6 +21,7 @@ static char* GetPasswordCallback(rfbClient* cl){
static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){ static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
rfbCredential *c = (rfbCredential *)malloc(sizeof(rfbCredential)); rfbCredential *c = (rfbCredential *)malloc(sizeof(rfbCredential));
if ( credentialType != rfbCredentialTypeUser ) { if ( credentialType != rfbCredentialTypeUser ) {
free(c);
return NULL; return NULL;
} }
@ -68,6 +65,23 @@ VncCamera::VncCamera(
mPass(pass) mPass(pass)
{ {
Debug(2, "Host:%s Port: %s User: %s Pass:%s", mHost.c_str(), mPort.c_str(), mUser.c_str(), mPass.c_str()); Debug(2, "Host:%s Port: %s User: %s Pass:%s", mHost.c_str(), mPort.c_str(), mUser.c_str(), mPass.c_str());
if ( colours == ZM_COLOUR_RGB32 ) {
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
mImgPixFmt = AV_PIX_FMT_RGBA;
mBpp = 4;
} else if ( colours == ZM_COLOUR_RGB24 ) {
subpixelorder = ZM_SUBPIX_ORDER_RGB;
mImgPixFmt = AV_PIX_FMT_RGB24;
mBpp = 3;
} else if ( colours == ZM_COLOUR_GRAY8 ) {
subpixelorder = ZM_SUBPIX_ORDER_NONE;
mImgPixFmt = AV_PIX_FMT_GRAY8;
mBpp = 1;
} else {
Panic("Unexpected colours: %d", colours);
}
if ( capture ) if ( capture )
Initialise(); Initialise();
} }
@ -94,6 +108,7 @@ void VncCamera::Initialise() {
mRfb->serverHost = strdup(mHost.c_str()); mRfb->serverHost = strdup(mHost.c_str());
mRfb->serverPort = atoi(mPort.c_str()); mRfb->serverPort = atoi(mPort.c_str());
rfbInitClient(mRfb, 0, nullptr); rfbInitClient(mRfb, 0, nullptr);
scale.init();
} }
void VncCamera::Terminate() { void VncCamera::Terminate() {
@ -102,65 +117,20 @@ void VncCamera::Terminate() {
int VncCamera::PrimeCapture() { int VncCamera::PrimeCapture() {
Info("Priming capture from %s", mHost.c_str()); Info("Priming capture from %s", mHost.c_str());
if ( mRfb->si.framebufferWidth != width || mRfb->si.framebufferHeight != height ) {
Info("Expected screen resolution (%dx%d) does not match the provided resolution (%dx%d), using scaling",
width, height, mRfb->si.framebufferWidth, mRfb->si.framebufferHeight);
mScale = true;
sws = sws_getContext(
mRfb->si.framebufferWidth, mRfb->si.framebufferHeight, AV_PIX_FMT_RGBA,
width, height, AV_PIX_FMT_RGBA, SWS_BICUBIC,
NULL, NULL, NULL);
if ( !sws ) {
Error("Could not scale image");
return -1;
}
}
return 0; return 0;
} }
int VncCamera::PreCapture() { int VncCamera::PreCapture() {
Debug(2, "PreCapture"); Debug(2, "PreCapture");
WaitForMessage(mRfb, 500); WaitForMessage(mRfb, 500);
Debug(2, "After Wait ");
rfbBool res = HandleRFBServerMessage(mRfb); rfbBool res = HandleRFBServerMessage(mRfb);
Debug(2, "After Handle ");
return res == TRUE ? 1 : -1 ; return res == TRUE ? 1 : -1 ;
} }
int VncCamera::Capture(Image &image) { int VncCamera::Capture(Image &image) {
Debug(2, "Capturing"); Debug(2, "Capturing");
int srcLineSize[4]; uint8_t *directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
int dstLineSize[4]; scale.Convert(mVncData.buffer, mRfb->si.framebufferHeight * mRfb->si.framebufferWidth * 4, directbuffer, width * height * mBpp, AV_PIX_FMT_RGBA, mImgPixFmt, mRfb->si.framebufferWidth, mRfb->si.framebufferHeight, width, height);
int dstSize;
if ( mScale ) {
uint8_t* directbuffer;
/* Request a writeable buffer of the target image */
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
if ( directbuffer == NULL ) {
Error("Failed requesting writeable buffer for the captured image.");
return -1;
}
if ( av_image_fill_arrays(dstbuf, dstLineSize, directbuffer, AV_PIX_FMT_RGBA,
width, height, 16) < 0) {
Error("Could not allocate dst image. Scaling failed");
return -1;
}
if ( av_image_fill_arrays(srcbuf, srcLineSize, mVncData.buffer, AV_PIX_FMT_RGBA,
mRfb->si.framebufferWidth, mRfb->si.framebufferHeight, 16) < 0) {
Error("Could not allocate source image. Scaling failed");
return -1;
}
sws_scale(sws, (const uint8_t* const*)srcbuf, srcLineSize, 0, mRfb->si.framebufferHeight,
dstbuf, dstLineSize);
} else {
image.Assign(width, height, colours, subpixelorder, mVncData.buffer, width * height * 4);
}
return 1; return 1;
} }
@ -173,15 +143,6 @@ int VncCamera::CaptureAndRecord(Image &image, timeval recording, char* event_dir
} }
int VncCamera::Close() { int VncCamera::Close() {
#if HAVE_LIBSWSCALE
if ( mScale ) {
av_freep(&srcbuf[0]);
av_freep(&dstbuf[0]);
sws_freeContext(sws);
sws = NULL;
}
#endif
rfbClientCleanup(mRfb); rfbClientCleanup(mRfb);
return 0; return 0;
} }

View File

@ -5,10 +5,17 @@
#include "zm_buffer.h" #include "zm_buffer.h"
#include "zm_camera.h" #include "zm_camera.h"
#include "zm_thread.h" #include "zm_thread.h"
#include "zm_swscale.h"
#if HAVE_LIBVNC #if HAVE_LIBVNC
#include <rfb/rfbclient.h> #include <rfb/rfbclient.h>
extern "C" {
#include <libavutil/imgutils.h>
#include <libavutil/parseutils.h>
#include <libswscale/swscale.h>
}
// Used by vnc callbacks // Used by vnc callbacks
struct VncPrivateData struct VncPrivateData
{ {
@ -22,11 +29,8 @@ protected:
rfbClient *mRfb; rfbClient *mRfb;
VncPrivateData mVncData; VncPrivateData mVncData;
int mBpp; int mBpp;
int mSpp; SWScale scale;
int mBps; AVPixelFormat mImgPixFmt;
bool mScale;
uint8_t *srcbuf[4], *dstbuf[4];
struct SwsContext *sws;
std::string mHost; std::string mHost;
std::string mPort; std::string mPort;
std::string mUser; std::string mUser;

View File

@ -84,7 +84,7 @@ int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf,
return 0; return 0;
} }
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) { int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height, unsigned int new_width, unsigned int new_height) {
/* Parameter checking */ /* Parameter checking */
if(in_buffer == NULL || out_buffer == NULL) { if(in_buffer == NULL || out_buffer == NULL) {
Error("NULL Input or output buffer"); Error("NULL Input or output buffer");
@ -94,7 +94,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
// Error("Invalid input or output pixel formats"); // Error("Invalid input or output pixel formats");
// return -2; // return -2;
// } // }
if (!width || !height) { if (!width || !height || !new_height || !new_width) {
Error("Invalid width or height"); Error("Invalid width or height");
return -3; return -3;
} }
@ -111,7 +111,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
/* Check the buffer sizes */ /* Check the buffer sizes */
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t insize = av_image_get_buffer_size(in_pf, width, height,1); size_t insize = av_image_get_buffer_size(in_pf, width, height, 1);
#else #else
size_t insize = avpicture_get_size(in_pf, width, height); size_t insize = avpicture_get_size(in_pf, width, height);
#endif #endif
@ -120,9 +120,9 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
return -4; return -4;
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t outsize = av_image_get_buffer_size(out_pf, width, height,1); size_t outsize = av_image_get_buffer_size(out_pf, new_width, new_height, 1);
#else #else
size_t outsize = avpicture_get_size(out_pf, width, height); size_t outsize = avpicture_get_size(out_pf, new_width, new_height);
#endif #endif
if(outsize < out_buffer_size) { if(outsize < out_buffer_size) {
@ -131,7 +131,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
} }
/* Get the context */ /* Get the context */
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, width, height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL ); swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, new_width, new_height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
if(swscale_ctx == NULL) { if(swscale_ctx == NULL) {
Error("Failed getting swscale context"); Error("Failed getting swscale context");
return -6; return -6;
@ -150,10 +150,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
} }
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize, if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
out_buffer, out_pf, width, height, 1) <= 0) { out_buffer, out_pf, new_width, new_height, 1) <= 0) {
#else #else
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, width, if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, new_width,
height) <= 0) { new_height) <= 0) {
#endif #endif
Error("Failed filling output frame with output buffer"); Error("Failed filling output frame with output buffer");
return -8; return -8;
@ -168,6 +168,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
return 0; return 0;
} }
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
return Convert(in_buffer, in_buffer_size, out_buffer, out_buffer_size, in_pf, out_pf, width, height, width, height);
}
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) { int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
if(img->Width() != width) { if(img->Width() != width) {
Error("Source image width differs. Source: %d Output: %d",img->Width(), width); Error("Source image width differs. Source: %d Output: %d",img->Width(), width);

View File

@ -10,13 +10,14 @@ class SWScale {
public: public:
SWScale(); SWScale();
~SWScale(); ~SWScale();
bool init(); bool init();
int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size); int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size);
int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size); int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size);
int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height, unsigned int new_width, unsigned int new_height);
protected: protected:
bool gotdefaults; bool gotdefaults;
struct SwsContext* swscale_ctx; struct SwsContext* swscale_ctx;