Merge branch 'master' into fix_out_of_files_in_encoding
This commit is contained in:
commit
ccc4d4af54
|
@ -3,7 +3,8 @@ target_compile_options(zm-warning-interface
|
||||||
-Wall
|
-Wall
|
||||||
-Wextra
|
-Wextra
|
||||||
-Wimplicit-fallthrough
|
-Wimplicit-fallthrough
|
||||||
-Wno-unused-parameter)
|
-Wno-unused-parameter
|
||||||
|
-Wvla)
|
||||||
|
|
||||||
if(ENABLE_WERROR)
|
if(ENABLE_WERROR)
|
||||||
target_compile_options(zm-warning-interface
|
target_compile_options(zm-warning-interface
|
||||||
|
|
|
@ -7,7 +7,8 @@ target_compile_options(zm-warning-interface
|
||||||
-Wno-cast-function-type
|
-Wno-cast-function-type
|
||||||
$<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>:-Wno-clobbered>
|
$<$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>:-Wno-clobbered>
|
||||||
-Wno-unused-parameter
|
-Wno-unused-parameter
|
||||||
-Woverloaded-virtual)
|
-Woverloaded-virtual
|
||||||
|
-Wvla)
|
||||||
|
|
||||||
if(ENABLE_WERROR)
|
if(ENABLE_WERROR)
|
||||||
target_compile_options(zm-warning-interface
|
target_compile_options(zm-warning-interface
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
int ZM::CommsBase::readV(int iovcnt, /* const void *, int, */ ...) {
|
int ZM::CommsBase::readV(int iovcnt, /* const void *, int, */ ...) {
|
||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
iovec iov[iovcnt];
|
std::vector<iovec> iov(iovcnt);
|
||||||
|
|
||||||
va_start(arg_ptr, iovcnt);
|
va_start(arg_ptr, iovcnt);
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
|
@ -45,7 +45,7 @@ int ZM::CommsBase::readV(int iovcnt, /* const void *, int, */ ...) {
|
||||||
}
|
}
|
||||||
va_end(arg_ptr);
|
va_end(arg_ptr);
|
||||||
|
|
||||||
int nBytes = ::readv(mRd, iov, iovcnt);
|
int nBytes = ::readv(mRd, iov.data(), iovcnt);
|
||||||
if (nBytes < 0) {
|
if (nBytes < 0) {
|
||||||
Debug(1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno));
|
Debug(1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ int ZM::CommsBase::readV(int iovcnt, /* const void *, int, */ ...) {
|
||||||
|
|
||||||
int ZM::CommsBase::writeV(int iovcnt, /* const void *, int, */ ...) {
|
int ZM::CommsBase::writeV(int iovcnt, /* const void *, int, */ ...) {
|
||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
iovec iov[iovcnt];
|
std::vector<iovec> iov(iovcnt);
|
||||||
|
|
||||||
va_start(arg_ptr, iovcnt);
|
va_start(arg_ptr, iovcnt);
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
|
@ -63,7 +63,7 @@ int ZM::CommsBase::writeV(int iovcnt, /* const void *, int, */ ...) {
|
||||||
}
|
}
|
||||||
va_end(arg_ptr);
|
va_end(arg_ptr);
|
||||||
|
|
||||||
ssize_t nBytes = ::writev(mWd, iov, iovcnt);
|
ssize_t nBytes = ::writev(mWd, iov.data(), iovcnt);
|
||||||
if (nBytes < 0) {
|
if (nBytes < 0) {
|
||||||
Debug(1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno));
|
Debug(1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,27 +243,27 @@ class Socket : public CommsBase {
|
||||||
return nBytes;
|
return nBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int recv(std::string &msg) const {
|
virtual ssize_t recv(std::string &msg) const {
|
||||||
char buffer[msg.capacity()];
|
std::vector<char> buffer(msg.capacity());
|
||||||
int nBytes = 0;
|
ssize_t nBytes;
|
||||||
if ((nBytes = ::recv(mSd, buffer, sizeof(buffer), 0)) < 0) {
|
if ((nBytes = ::recv(mSd, buffer.data(), buffer.size(), 0)) < 0) {
|
||||||
Debug(1, "Recv of %zd bytes max to string on sd %d failed: %s", sizeof(buffer), mSd, strerror(errno));
|
Debug(1, "Recv of %zd bytes max to string on sd %d failed: %s", msg.size(), mSd, strerror(errno));
|
||||||
return nBytes;
|
return nBytes;
|
||||||
}
|
}
|
||||||
buffer[nBytes] = '\0';
|
buffer[nBytes] = '\0';
|
||||||
msg = buffer;
|
msg = {buffer.begin(), buffer.begin() + nBytes};
|
||||||
return nBytes;
|
return nBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int recv(std::string &msg, size_t maxLen) const {
|
virtual ssize_t recv(std::string &msg, size_t maxLen) const {
|
||||||
char buffer[maxLen];
|
std::vector<char> buffer(maxLen);
|
||||||
int nBytes = 0;
|
ssize_t nBytes;
|
||||||
if ((nBytes = ::recv(mSd, buffer, sizeof(buffer), 0)) < 0) {
|
if ((nBytes = ::recv(mSd, buffer.data(), buffer.size(), 0)) < 0) {
|
||||||
Debug(1, "Recv of %zd bytes max to string on sd %d failed: %s", maxLen, mSd, strerror(errno));
|
Debug(1, "Recv of %zd bytes max to string on sd %d failed: %s", maxLen, mSd, strerror(errno));
|
||||||
return nBytes;
|
return nBytes;
|
||||||
}
|
}
|
||||||
buffer[nBytes] = '\0';
|
buffer[nBytes] = '\0';
|
||||||
msg = buffer;
|
msg = {buffer.begin(), buffer.begin() + nBytes};
|
||||||
return nBytes;
|
return nBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
164
src/zm_image.cpp
164
src/zm_image.cpp
|
@ -2458,9 +2458,9 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
|
||||||
} // end foreach coordinate in the polygon
|
} // end foreach coordinate in the polygon
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RGB32 compatible: complete */
|
// Polygon filling is based on the Scan-line Polygon filling algorithm
|
||||||
void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
|
void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
|
||||||
if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) {
|
if (!(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32)) {
|
||||||
Panic("Attempt to fill image with unexpected colours %d", colours);
|
Panic("Attempt to fill image with unexpected colours %d", colours);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2468,119 +2468,91 @@ void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
|
||||||
colour = rgb_convert(colour, subpixelorder);
|
colour = rgb_convert(colour, subpixelorder);
|
||||||
|
|
||||||
size_t n_coords = polygon.GetVertices().size();
|
size_t n_coords = polygon.GetVertices().size();
|
||||||
int n_global_edges = 0;
|
|
||||||
Edge global_edges[n_coords];
|
std::vector<PolygonFill::Edge> global_edges;
|
||||||
|
global_edges.reserve(n_coords);
|
||||||
for (size_t j = 0, i = n_coords - 1; j < n_coords; i = j++) {
|
for (size_t j = 0, i = n_coords - 1; j < n_coords; i = j++) {
|
||||||
const Vector2 &p1 = polygon.GetVertices()[i];
|
const Vector2 &p1 = polygon.GetVertices()[i];
|
||||||
const Vector2 &p2 = polygon.GetVertices()[j];
|
const Vector2 &p2 = polygon.GetVertices()[j];
|
||||||
|
|
||||||
int x1 = p1.x_;
|
// Do not add horizontal edges to the global edge table.
|
||||||
int x2 = p2.x_;
|
if (p1.y_ == p2.y_)
|
||||||
int y1 = p1.y_;
|
|
||||||
int y2 = p2.y_;
|
|
||||||
|
|
||||||
//Debug( 9, "x1:%d,y1:%d x2:%d,y2:%d", x1, y1, x2, y2 );
|
|
||||||
if ( y1 == y2 )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
double dx = x2 - x1;
|
Vector2 d = p2 - p1;
|
||||||
double dy = y2 - y1;
|
|
||||||
|
global_edges.emplace_back(std::min(p1.y_, p2.y_),
|
||||||
|
std::max(p1.y_, p2.y_),
|
||||||
|
p1.y_ < p2.y_ ? p1.x_ : p2.x_,
|
||||||
|
d.x_ / static_cast<double>(d.y_));
|
||||||
|
|
||||||
global_edges[n_global_edges].min_y = y1<y2?y1:y2;
|
|
||||||
global_edges[n_global_edges].max_y = y1<y2?y2:y1;
|
|
||||||
global_edges[n_global_edges].min_x = y1<y2?x1:x2;
|
|
||||||
global_edges[n_global_edges]._1_m = dx/dy;
|
|
||||||
n_global_edges++;
|
|
||||||
}
|
}
|
||||||
std::sort(global_edges, global_edges + n_global_edges, Edge::CompareYX);
|
std::sort(global_edges.begin(), global_edges.end(), PolygonFill::Edge::CompareYX);
|
||||||
|
|
||||||
#ifndef ZM_DBG_OFF
|
std::vector<PolygonFill::Edge> active_edges;
|
||||||
if ( logLevel() >= Logger::DEBUG9 ) {
|
active_edges.reserve(global_edges.size());
|
||||||
for ( int i = 0; i < n_global_edges; i++ ) {
|
|
||||||
Debug(9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f",
|
|
||||||
i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int n_active_edges = 0;
|
int32 scan_line = global_edges[0].min_y;
|
||||||
Edge active_edges[n_global_edges];
|
while (!global_edges.empty() || !active_edges.empty()) {
|
||||||
int y = global_edges[0].min_y;
|
// Deactivate edges with max_y < current scan line
|
||||||
do {
|
for (auto it = active_edges.begin(); it != active_edges.end();) {
|
||||||
for ( int i = 0; i < n_global_edges; i++ ) {
|
if (scan_line >= it->max_y) {
|
||||||
if ( global_edges[i].min_y == y ) {
|
it = active_edges.erase(it);
|
||||||
Debug(9, "Moving global edge");
|
|
||||||
active_edges[n_active_edges++] = global_edges[i];
|
|
||||||
if ( i < (n_global_edges-1) ) {
|
|
||||||
memmove(&global_edges[i], &global_edges[i + 1], sizeof(*global_edges) * (n_global_edges - i - 1));
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
n_global_edges--;
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
it->min_x += it->_1_m;
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(active_edges, active_edges + n_active_edges, Edge::CompareX);
|
|
||||||
#ifndef ZM_DBG_OFF
|
// Activate edges with min_y == current scan line
|
||||||
if ( logLevel() >= Logger::DEBUG9 ) {
|
for (auto it = global_edges.begin(); it != global_edges.end();) {
|
||||||
for ( int i = 0; i < n_active_edges; i++ ) {
|
if (it->min_y == scan_line) {
|
||||||
Debug(9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f",
|
active_edges.emplace_back(*it);
|
||||||
y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m );
|
it = global_edges.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
std::sort(active_edges.begin(), active_edges.end(), PolygonFill::Edge::CompareX);
|
||||||
if ( !(y%density) ) {
|
|
||||||
//Debug( 9, "%d", y );
|
if (!(scan_line % density)) {
|
||||||
for ( int i = 0; i < n_active_edges; ) {
|
for (auto it = active_edges.begin(); it != active_edges.end(); ++it) {
|
||||||
int lo_x = int(round(active_edges[i++].min_x));
|
int32 lo_x = static_cast<int32>(it->min_x);
|
||||||
int hi_x = int(round(active_edges[i++].min_x));
|
int32 hi_x = static_cast<int32>(std::next(it)->min_x);
|
||||||
if ( colours == ZM_COLOUR_GRAY8 ) {
|
if (colours == ZM_COLOUR_GRAY8) {
|
||||||
unsigned char *p = &buffer[(y*width)+lo_x];
|
uint8 *p = &buffer[(scan_line * width) + lo_x];
|
||||||
for ( int x = lo_x; x <= hi_x; x++, p++) {
|
|
||||||
if ( !(x%density) ) {
|
for (int32 x = lo_x; x <= hi_x; x++, p++) {
|
||||||
//Debug( 9, " %d", x );
|
if (!(x % density)) {
|
||||||
*p = colour;
|
*p = colour;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ( colours == ZM_COLOUR_RGB24 ) {
|
} else if (colours == ZM_COLOUR_RGB24) {
|
||||||
unsigned char *p = &buffer[colours*((y*width)+lo_x)];
|
constexpr uint8 bytesPerPixel = 3;
|
||||||
for ( int x = lo_x; x <= hi_x; x++, p += 3) {
|
uint8 *ptr = &buffer[((scan_line * width) + lo_x) * bytesPerPixel];
|
||||||
if ( !(x%density) ) {
|
|
||||||
RED_PTR_RGBA(p) = RED_VAL_RGBA(colour);
|
|
||||||
GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour);
|
|
||||||
BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if( colours == ZM_COLOUR_RGB32 ) {
|
|
||||||
Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2];
|
|
||||||
for ( int x = lo_x; x <= hi_x; x++, p++) {
|
|
||||||
if ( !(x%density) ) {
|
|
||||||
/* Fast, copies the entire pixel in a single pass */
|
|
||||||
*p = colour;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
y++;
|
|
||||||
for ( int i = n_active_edges-1; i >= 0; i-- ) {
|
|
||||||
if ( y >= active_edges[i].max_y ) {
|
|
||||||
// Or >= as per sheets
|
|
||||||
Debug(9, "Deleting active_edge");
|
|
||||||
if ( i < (n_active_edges-1) ) {
|
|
||||||
//memcpy( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) );
|
|
||||||
memmove( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) );
|
|
||||||
}
|
|
||||||
n_active_edges--;
|
|
||||||
} else {
|
|
||||||
active_edges[i].min_x += active_edges[i]._1_m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while ( n_global_edges || n_active_edges );
|
|
||||||
}
|
|
||||||
|
|
||||||
void Image::Fill(Rgb colour, const Polygon &polygon) {
|
for (int32 x = lo_x; x <= hi_x; x++, ptr += bytesPerPixel) {
|
||||||
Fill(colour, 1, polygon);
|
if (!(x % density)) {
|
||||||
|
RED_PTR_RGBA(ptr) = RED_VAL_RGBA(colour);
|
||||||
|
GREEN_PTR_RGBA(ptr) = GREEN_VAL_RGBA(colour);
|
||||||
|
BLUE_PTR_RGBA(ptr) = BLUE_VAL_RGBA(colour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (colours == ZM_COLOUR_RGB32) {
|
||||||
|
constexpr uint8 bytesPerPixel = 4;
|
||||||
|
Rgb *ptr = reinterpret_cast<Rgb *>(&buffer[((scan_line * width) + lo_x) * bytesPerPixel]);
|
||||||
|
|
||||||
|
for (int32 x = lo_x; x <= hi_x; x++, ptr++) {
|
||||||
|
if (!(x % density)) {
|
||||||
|
*ptr = colour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scan_line++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Rotate(int angle) {
|
void Image::Rotate(int angle) {
|
||||||
|
|
|
@ -278,8 +278,8 @@ class Image {
|
||||||
void Fill( Rgb colour, const Box *limits=0 );
|
void Fill( Rgb colour, const Box *limits=0 );
|
||||||
void Fill( Rgb colour, int density, const Box *limits=0 );
|
void Fill( Rgb colour, int density, const Box *limits=0 );
|
||||||
void Outline( Rgb colour, const Polygon &polygon );
|
void Outline( Rgb colour, const Polygon &polygon );
|
||||||
void Fill( Rgb colour, const Polygon &polygon );
|
void Fill(Rgb colour, const Polygon &polygon) { Fill(colour, 1, polygon); };
|
||||||
void Fill( Rgb colour, int density, const Polygon &polygon );
|
void Fill(Rgb colour, int density, const Polygon &polygon);
|
||||||
|
|
||||||
void Rotate( int angle );
|
void Rotate( int angle );
|
||||||
void Flip( bool leftright );
|
void Flip( bool leftright );
|
||||||
|
@ -292,6 +292,31 @@ class Image {
|
||||||
void Deinterlace_4Field(const Image* next_image, unsigned int threshold);
|
void Deinterlace_4Field(const Image* next_image, unsigned int threshold);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Scan-line polygon fill algorithm
|
||||||
|
namespace PolygonFill {
|
||||||
|
class Edge {
|
||||||
|
public:
|
||||||
|
Edge() = default;
|
||||||
|
Edge(int32 min_y, int32 max_y, double min_x, double _1_m) : min_y(min_y), max_y(max_y), min_x(min_x), _1_m(_1_m) {}
|
||||||
|
|
||||||
|
static bool CompareYX(const Edge &e1, const Edge &e2) {
|
||||||
|
if (e1.min_y == e2.min_y)
|
||||||
|
return e1.min_x < e2.min_x;
|
||||||
|
return e1.min_y < e2.min_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CompareX(const Edge &e1, const Edge &e2) {
|
||||||
|
return e1.min_x < e2.min_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
int32 min_y;
|
||||||
|
int32 max_y;
|
||||||
|
double min_x;
|
||||||
|
double _1_m;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ZM_IMAGE_H
|
#endif // ZM_IMAGE_H
|
||||||
|
|
||||||
/* Blend functions */
|
/* Blend functions */
|
||||||
|
|
|
@ -381,7 +381,11 @@ LocalCamera::LocalCamera(
|
||||||
} else {
|
} else {
|
||||||
if ( capture ) {
|
if ( capture ) {
|
||||||
Info("Selected capture palette: %s (0x%02hhx%02hhx%02hhx%02hhx)",
|
Info("Selected capture palette: %s (0x%02hhx%02hhx%02hhx%02hhx)",
|
||||||
palette_desc, (palette>>24)&0xff, (palette>>16)&0xff, (palette>>8)&0xff, (palette)&0xff);
|
palette_desc,
|
||||||
|
static_cast<uint8>((palette >> 24) & 0xff),
|
||||||
|
static_cast<uint8>((palette >> 16) & 0xff),
|
||||||
|
static_cast<uint8>((palette >> 8) & 0xff),
|
||||||
|
static_cast<uint8>((palette) & 0xff));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -438,8 +442,10 @@ LocalCamera::LocalCamera(
|
||||||
} else {
|
} else {
|
||||||
if ( capture ) {
|
if ( capture ) {
|
||||||
#if HAVE_LIBSWSCALE
|
#if HAVE_LIBSWSCALE
|
||||||
Info("No direct match for the selected palette (0x%02hhx%02hhx%02hhx%02hhx) and target colorspace (%02u). Format conversion is required, performance penalty expected",
|
Info(
|
||||||
(capturePixFormat>>24)&0xff,((capturePixFormat>>16)&0xff),((capturePixFormat>>8)&0xff),((capturePixFormat)&0xff), colours);
|
"No direct match for the selected palette (%d) and target colorspace (%02u). Format conversion is required, performance penalty expected",
|
||||||
|
capturePixFormat,
|
||||||
|
colours);
|
||||||
#else
|
#else
|
||||||
Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected");
|
Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected");
|
||||||
#endif
|
#endif
|
||||||
|
@ -463,13 +469,11 @@ LocalCamera::LocalCamera(
|
||||||
if ( capture ) {
|
if ( capture ) {
|
||||||
#if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0)
|
#if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0)
|
||||||
if ( !sws_isSupportedInput(capturePixFormat) ) {
|
if ( !sws_isSupportedInput(capturePixFormat) ) {
|
||||||
Error("swscale does not support the used capture format: 0x%02hhx%02hhx%02hhx%02hhx",
|
Error("swscale does not support the used capture format: %d", capturePixFormat);
|
||||||
(capturePixFormat>>24)&0xff,((capturePixFormat>>16)&0xff),((capturePixFormat>>8)&0xff),((capturePixFormat)&0xff));
|
|
||||||
conversion_type = 2; /* Try ZM format conversions */
|
conversion_type = 2; /* Try ZM format conversions */
|
||||||
}
|
}
|
||||||
if ( !sws_isSupportedOutput(imagePixFormat) ) {
|
if ( !sws_isSupportedOutput(imagePixFormat) ) {
|
||||||
Error("swscale does not support the target format: 0x%02hhx%02hhx%02hhx%02hhx",
|
Error("swscale does not support the target format: 0x%d", imagePixFormat);
|
||||||
(imagePixFormat>>24)&0xff,((imagePixFormat>>16)&0xff),((imagePixFormat>>8)&0xff),((imagePixFormat)&0xff));
|
|
||||||
conversion_type = 2; /* Try ZM format conversions */
|
conversion_type = 2; /* Try ZM format conversions */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1214,12 +1218,12 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) {
|
||||||
fmt_fcc[nIndex] = fmtinfo.pixelformat;
|
fmt_fcc[nIndex] = fmtinfo.pixelformat;
|
||||||
|
|
||||||
Debug(3, "Got format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %d",
|
Debug(3, "Got format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %d",
|
||||||
fmt_desc[nIndex],
|
fmt_desc[nIndex],
|
||||||
(fmt_fcc[nIndex]>>24)&0xff,
|
static_cast<uint8>((fmt_fcc[nIndex] >> 24) & 0xff),
|
||||||
(fmt_fcc[nIndex]>>16)&0xff,
|
static_cast<uint8>((fmt_fcc[nIndex] >> 16) & 0xff),
|
||||||
(fmt_fcc[nIndex]>>8)&0xff,
|
static_cast<uint8>((fmt_fcc[nIndex] >> 8) & 0xff),
|
||||||
(fmt_fcc[nIndex])&0xff,
|
static_cast<uint8>((fmt_fcc[nIndex]) & 0xff),
|
||||||
nIndex);
|
nIndex);
|
||||||
|
|
||||||
/* Proceed to the next index */
|
/* Proceed to the next index */
|
||||||
memset(&fmtinfo, 0, sizeof(fmtinfo));
|
memset(&fmtinfo, 0, sizeof(fmtinfo));
|
||||||
|
@ -1248,13 +1252,23 @@ uint32_t LocalCamera::AutoSelectFormat(int p_colours) {
|
||||||
for ( unsigned int j=0; j < nIndex; j++ ) {
|
for ( unsigned int j=0; j < nIndex; j++ ) {
|
||||||
if ( preferedformats[i] == fmt_fcc[j] ) {
|
if ( preferedformats[i] == fmt_fcc[j] ) {
|
||||||
Debug(6, "Choosing format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %u",
|
Debug(6, "Choosing format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %u",
|
||||||
fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j);
|
fmt_desc[j],
|
||||||
|
static_cast<uint8>(fmt_fcc[j] & 0xff),
|
||||||
|
static_cast<uint8>((fmt_fcc[j] >> 8) & 0xff),
|
||||||
|
static_cast<uint8>((fmt_fcc[j] >> 16) & 0xff),
|
||||||
|
static_cast<uint8>((fmt_fcc[j] >> 24) & 0xff),
|
||||||
|
j);
|
||||||
/* Found a format! */
|
/* Found a format! */
|
||||||
nIndexUsed = j;
|
nIndexUsed = j;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
Debug(6, "No match for format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %u",
|
Debug(6, "No match for format: %s (0x%02hhx%02hhx%02hhx%02hhx) at index %u",
|
||||||
fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j);
|
fmt_desc[j],
|
||||||
|
static_cast<uint8>(fmt_fcc[j] & 0xff),
|
||||||
|
static_cast<uint8>((fmt_fcc[j] >> 8) & 0xff),
|
||||||
|
static_cast<uint8>((fmt_fcc[j] >> 16) & 0xff),
|
||||||
|
static_cast<uint8>((fmt_fcc[j] >> 24) & 0xff),
|
||||||
|
j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -529,15 +529,17 @@ void Logger::logPrint(bool hex, const char *filepath, int line, int level, const
|
||||||
if (level <= mDatabaseLevel) {
|
if (level <= mDatabaseLevel) {
|
||||||
if (zmDbConnected) {
|
if (zmDbConnected) {
|
||||||
int syslogSize = syslogEnd-syslogStart;
|
int syslogSize = syslogEnd-syslogStart;
|
||||||
char escapedString[(syslogSize*2)+1];
|
std::string escapedString;
|
||||||
mysql_real_escape_string(&dbconn, escapedString, syslogStart, syslogSize);
|
escapedString.reserve((syslogSize * 2) + 1);
|
||||||
|
mysql_real_escape_string(&dbconn, &escapedString[0], syslogStart, syslogSize);
|
||||||
|
escapedString.resize(std::strlen(escapedString.c_str()));
|
||||||
|
|
||||||
std::string sql_string = stringtf(
|
std::string sql_string = stringtf(
|
||||||
"INSERT INTO `Logs` "
|
"INSERT INTO `Logs` "
|
||||||
"( `TimeKey`, `Component`, `ServerId`, `Pid`, `Level`, `Code`, `Message`, `File`, `Line` )"
|
"( `TimeKey`, `Component`, `ServerId`, `Pid`, `Level`, `Code`, `Message`, `File`, `Line` )"
|
||||||
" VALUES "
|
" VALUES "
|
||||||
"( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )",
|
"( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )",
|
||||||
timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line
|
timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString.c_str(), file, line
|
||||||
);
|
);
|
||||||
dbQueue.push(std::move(sql_string));
|
dbQueue.push(std::move(sql_string));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1855,7 +1855,7 @@ bool Monitor::Analyse() {
|
||||||
|
|
||||||
/* try to stay behind the decoder. */
|
/* try to stay behind the decoder. */
|
||||||
if (decoding_enabled) {
|
if (decoding_enabled) {
|
||||||
while (!snap->image and !snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
|
while ((!snap->image or deinterlacing_value) and !snap->decoded and !zm_terminate and !analysis_thread->Stopped()) {
|
||||||
// Need to wait for the decoder thread.
|
// Need to wait for the decoder thread.
|
||||||
Debug(1, "Waiting for decode");
|
Debug(1, "Waiting for decode");
|
||||||
packet_lock->wait();
|
packet_lock->wait();
|
||||||
|
|
|
@ -42,10 +42,8 @@ ZMPacket::ZMPacket() :
|
||||||
pts(0),
|
pts(0),
|
||||||
decoded(0)
|
decoded(0)
|
||||||
{
|
{
|
||||||
Debug(1, "ZMPacket");
|
|
||||||
av_init_packet(&packet);
|
av_init_packet(&packet);
|
||||||
packet.size = 0; // So we can detect whether it has been filled.
|
packet.size = 0; // So we can detect whether it has been filled.
|
||||||
Debug(1, "ZMPacket");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZMPacket::ZMPacket(Image *i, const timeval &tv) :
|
ZMPacket::ZMPacket(Image *i, const timeval &tv) :
|
||||||
|
|
|
@ -23,23 +23,6 @@
|
||||||
#include "zm_box.h"
|
#include "zm_box.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct Edge {
|
|
||||||
int min_y;
|
|
||||||
int max_y;
|
|
||||||
double min_x;
|
|
||||||
double _1_m;
|
|
||||||
|
|
||||||
static bool CompareYX(const Edge &e1, const Edge &e2) {
|
|
||||||
if (e1.min_y == e2.min_y)
|
|
||||||
return e1.min_x < e2.min_x;
|
|
||||||
return e1.min_y < e2.min_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool CompareX(const Edge &e1, const Edge &e2) {
|
|
||||||
return e1.min_x < e2.min_x;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This class represents convex or concave non-self-intersecting polygons.
|
// This class represents convex or concave non-self-intersecting polygons.
|
||||||
class Polygon {
|
class Polygon {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -131,9 +131,9 @@ std::string Authenticator::computeDigestResponse(const std::string &method, cons
|
||||||
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT
|
||||||
// The "response" field is computed as:
|
// The "response" field is computed as:
|
||||||
// md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>))
|
// md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>))
|
||||||
size_t md5len = 16;
|
constexpr size_t md5len = 16;
|
||||||
unsigned char md5buf[md5len];
|
uint8 md5buf[md5len];
|
||||||
char md5HexBuf[md5len*2+1];
|
char md5HexBuf[md5len * 2 + 1];
|
||||||
|
|
||||||
// Step 1: md5(<username>:<realm>:<password>)
|
// Step 1: md5(<username>:<realm>:<password>)
|
||||||
std::string ha1Data = username() + ":" + realm() + ":" + password();
|
std::string ha1Data = username() + ":" + realm() + ":" + password();
|
||||||
|
|
|
@ -236,8 +236,8 @@ User *zmLoadAuthUser(const char *auth, bool use_remote_addr) {
|
||||||
}
|
}
|
||||||
char auth_key[512] = "";
|
char auth_key[512] = "";
|
||||||
char auth_md5[32+1] = "";
|
char auth_md5[32+1] = "";
|
||||||
size_t md5len = 16;
|
constexpr size_t md5len = 16;
|
||||||
unsigned char md5sum[md5len];
|
uint8 md5sum[md5len];
|
||||||
|
|
||||||
const char * hex = "0123456789abcdef";
|
const char * hex = "0123456789abcdef";
|
||||||
while ( MYSQL_ROW dbrow = mysql_fetch_row(result) ) {
|
while ( MYSQL_ROW dbrow = mysql_fetch_row(result) ) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ constexpr const T &clamp(const T &v, const T &lo, const T &hi, Compare comp) {
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
constexpr const T &clamp(const T &v, const T &lo, const T &hi) {
|
constexpr const T &clamp(const T &v, const T &lo, const T &hi) {
|
||||||
return clamp(v, lo, hi, std::less<T>{});
|
return ZM::clamp(v, lo, hi, std::less<T>{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,7 +348,6 @@ bool VideoStore::open() {
|
||||||
#else
|
#else
|
||||||
avcodec_copy_context(video_out_stream->codec, video_out_ctx);
|
avcodec_copy_context(video_out_stream->codec, video_out_ctx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
video_out_stream->time_base = video_in_stream ? video_in_stream->time_base : AV_TIME_BASE_Q;
|
video_out_stream->time_base = video_in_stream ? video_in_stream->time_base : AV_TIME_BASE_Q;
|
||||||
if (monitor->GetOptVideoWriter() == Monitor::PASSTHROUGH) {
|
if (monitor->GetOptVideoWriter() == Monitor::PASSTHROUGH) {
|
||||||
// Only set orientation if doing passthrough, otherwise the frame image will be rotated
|
// Only set orientation if doing passthrough, otherwise the frame image will be rotated
|
||||||
|
|
|
@ -224,23 +224,42 @@ TEST_CASE("ZM::UdpUnixSocket send/recv") {
|
||||||
ZM::UdpUnixSocket srv_socket;
|
ZM::UdpUnixSocket srv_socket;
|
||||||
ZM::UdpUnixSocket client_socket;
|
ZM::UdpUnixSocket client_socket;
|
||||||
|
|
||||||
std::array<char, 3> msg = {'a', 'b', 'c'};
|
SECTION("send/recv byte buffer") {
|
||||||
std::array<char, msg.size()> rcv{};
|
std::array<char, 3> msg = {'a', 'b', 'c'};
|
||||||
|
std::array<char, msg.size()> rcv{};
|
||||||
|
|
||||||
SECTION("send/recv on unbound socket") {
|
SECTION("on unbound socket") {
|
||||||
REQUIRE(client_socket.send(msg.data(), msg.size()) == -1);
|
REQUIRE(client_socket.send(msg.data(), msg.size()) == -1);
|
||||||
REQUIRE(srv_socket.recv(rcv.data(), rcv.size()) == -1);
|
REQUIRE(srv_socket.recv(rcv.data(), rcv.size()) == -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("on bound socket") {
|
||||||
|
REQUIRE(srv_socket.bind(sock_path.c_str()) == true);
|
||||||
|
REQUIRE(srv_socket.isOpen() == true);
|
||||||
|
|
||||||
|
REQUIRE(client_socket.connect(sock_path.c_str()) == true);
|
||||||
|
REQUIRE(client_socket.isConnected() == true);
|
||||||
|
|
||||||
|
REQUIRE(client_socket.send(msg.data(), msg.size()) == msg.size());
|
||||||
|
REQUIRE(srv_socket.recv(rcv.data(), rcv.size()) == msg.size());
|
||||||
|
|
||||||
|
REQUIRE(rcv == msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("send/recv") {
|
SECTION("send/recv string") {
|
||||||
|
std::string msg = "abc";
|
||||||
|
std::string rcv;
|
||||||
|
rcv.reserve(msg.length());
|
||||||
|
|
||||||
REQUIRE(srv_socket.bind(sock_path.c_str()) == true);
|
REQUIRE(srv_socket.bind(sock_path.c_str()) == true);
|
||||||
REQUIRE(srv_socket.isOpen() == true);
|
REQUIRE(srv_socket.isOpen() == true);
|
||||||
|
|
||||||
REQUIRE(client_socket.connect(sock_path.c_str()) == true);
|
REQUIRE(client_socket.connect(sock_path.c_str()) == true);
|
||||||
REQUIRE(client_socket.isConnected() == true);
|
REQUIRE(client_socket.isConnected() == true);
|
||||||
|
|
||||||
REQUIRE(client_socket.send(msg.data(), msg.size()) == msg.size());
|
REQUIRE(client_socket.send(msg) == static_cast<ssize_t>(msg.size()));
|
||||||
REQUIRE(srv_socket.recv(rcv.data(), rcv.size()) == msg.size());
|
REQUIRE(srv_socket.recv(rcv) == static_cast<ssize_t>(msg.size()));
|
||||||
|
|
||||||
REQUIRE(rcv == msg);
|
REQUIRE(rcv == msg);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue