setup more proper logging and get stuff working maybe

This commit is contained in:
Camryn Thomas 2025-03-26 20:57:23 -05:00
parent ea952e1981
commit ed8c594a30
Signed by: cptlobster
GPG Key ID: 33D607425C830B4C
5 changed files with 234 additions and 25 deletions

View File

@ -10,7 +10,7 @@ using namespace std;
int main() { int main() {
// create video capture // create video capture
//cv::VideoCapture cap = cv::VideoCapture(0); cv::VideoCapture cap = cv::VideoCapture(0);
// create socket // create socket
int clientSocket = socket(AF_INET, SOCK_STREAM, 0); int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
@ -21,18 +21,20 @@ int main() {
serverAddress.sin_port = htons(8080); serverAddress.sin_port = htons(8080);
serverAddress.sin_addr.s_addr = INADDR_ANY; serverAddress.sin_addr.s_addr = INADDR_ANY;
cv::Mat image = cv::Mat(cv::Size(640, 480), CV_8UC3, cv::Scalar(255, 0, 0)); cv::Mat image = cv::Mat::zeros(cv::Size(640, 480), CV_8UC3);
info("Ready to connect.");
// sending connection request // sending connection request
connect(clientSocket, reinterpret_cast<sockaddr *>(&serverAddress), connect(clientSocket, reinterpret_cast<sockaddr *>(&serverAddress),
sizeof(serverAddress)); sizeof(serverAddress));
info("Connected.");
// create buffer for serialization // create buffer for serialization
vector<uchar> imgbuf; vector<uchar> imgbuf;
while (true) { while (true) {
//cap.read(image); cap.read(image);
cout << "Sending image" << endl; trace("Sending image");
sendImage(clientSocket, image, imgbuf); sendImage(clientSocket, image, imgbuf);
} }

178
logging.h Normal file
View File

@ -0,0 +1,178 @@
#ifndef LOGGING_H
#define LOGGING_H
#include <iostream>
#include <iomanip>
#include <chrono>
#include <ctime>
// Logging levels
#define LOG_ERROR 0
#define LOG_WARN 1
#define LOG_INFO 2
#define LOG_DEBUG 3
#define LOG_TRACE 4
// Set logging arguments
// TODO: set these by compiler arguments or env vars or something
#define LOGGING LOG_DEBUG // logging level
#define LOGGING_COLOR true // enable color
#define LOGGING_TIMESTAMP true // enable timestamp
#define LOGGING_TIMESTAMP_FMT "%Y-%m-%dT%H:%M:%S%z" // timestamp format (local time)
#define LOGGING_POSITION true // display position (only works on C++20 or newer)
// Color codes
#define ANSI_RESET "\033[0m"
#define ANSI_BLACK "\033[30m" /* Black */
#define ANSI_RED "\033[31m" /* Red */
#define ANSI_GREEN "\033[32m" /* Green */
#define ANSI_YELLOW "\033[33m" /* Yellow */
#define ANSI_BLUE "\033[34m" /* Blue */
#define ANSI_MAGENTA "\033[35m" /* Magenta */
#define ANSI_CYAN "\033[36m" /* Cyan */
#define ANSI_WHITE "\033[37m" /* White */
#define ANSI_BOLD "\033[1m" /* Bold */
template <typename T>
void print(T t) {
std::cout << t << std::endl;
}
template <typename T, typename... Args>
void print(T t, Args... args) {
std::cout << t;
print(args...);
}
inline void printTimestamp() {
#if LOGGING_TIMESTAMP
auto now = std::chrono::system_clock::now();
auto time_c = std::chrono::system_clock::to_time_t(now);
std::tm time_tm;
localtime_r(&time_c, &time_tm);
std::cout << std::put_time(&time_tm, LOGGING_TIMESTAMP_FMT) << ": ";
#endif
}
// if we're on C++20 or later, then use the source_location header and add source location to logs
#if __cplusplus >= 202002L
#include <source_location>
inline void printPosition(std::source_location& location) {
#if LOGGING_POSITION
std::cout << location.file_name() << ":" << location.function_name << ":" << ANSI_CYAN << location.line() << ANSI_RESET << ": ";
#endif
}
inline void printHeader(std::string name, std::string color, std::source_location& location) {
#if LOGGING_COLOR
std::cout << ANSI_BOLD << color << "[" << name << "] " << ANSI_RESET;
printTimestamp();
printPosition(location);
#else
printHeader(name);
#endif
}
inline void printHeader(std::string name, std::source_location& location) {
std::cout << "[" << name << "] ";
printTimestamp();
printPosition(location);
}
template <typename... Args, typename Sl = std::source_location>
void trace(Args... args, Sl location = std::source_location::current()) {
#if LOGGING >= LOG_TRACE
printHeader("TRACE", ANSI_CYAN, location);
print(args...);
#endif
}
template <typename... Args, typename Sl = std::source_location>
void debug(Args... args, Sl location = std::source_location::current()) {
#if LOGGING >= LOG_DEBUG
printHeader("DEBUG", ANSI_MAGENTA, location);
print(args...);
#endif
}
template <typename... Args, typename Sl = std::source_location>
void info(Args... args, Sl location = std::source_location::current()) {
#if LOGGING >= LOG_INFO
printHeader("INFO", ANSI_GREEN, location);
print(args...);
#endif
}
template <typename... Args, typename Sl = std::source_location>
void warn(Args... args, Sl location = std::source_location::current()) {
#if LOGGING >= LOG_WARN
printHeader("WARN", ANSI_YELLOW, location);
print(args...);
#endif
}
template <typename... Args, typename Sl = std::source_location>
void error(Args... args, Sl location = std::source_location::current()) {
#if LOGGING >= LOG_ERROR
printHeader("ERROR", ANSI_RED, location);
print(args...);
#endif
}
#else
inline void printHeader(std::string name, std::string color) {
#if LOGGING_COLOR
std::cout << ANSI_BOLD << color << "[" << name << "] " << ANSI_RESET;
printTimestamp();
#else
printHeader(name);
#endif
}
inline void printHeader(std::string name) {
std::cout << "[" << name << "] ";
printTimestamp();
}
template <typename... Args>
void trace(Args... args) {
#if LOGGING >= LOG_TRACE
printHeader("TRACE", ANSI_CYAN);
print(args...);
#endif
}
template <typename... Args>
void debug(Args... args) {
#if LOGGING >= LOG_DEBUG
printHeader("DEBUG", ANSI_MAGENTA);
print(args...);
#endif
}
template <typename... Args>
void info(Args... args) {
#if LOGGING >= LOG_INFO
printHeader("INFO", ANSI_GREEN);
print(args...);
#endif
}
template <typename... Args>
void warn(Args... args) {
#if LOGGING >= LOG_WARN
printHeader("WARN", ANSI_YELLOW);
print(args...);
#endif
}
template <typename... Args>
void error(Args... args) {
#if LOGGING >= LOG_ERROR
printHeader("ERROR", ANSI_RED);
print(args...);
#endif
}
#endif
#endif //LOGGING_H

View File

@ -1,7 +1,8 @@
#======================================================================================================================= #=======================================================================================================================
# PROJECT SETTINGS # PROJECT SETTINGS
#======================================================================================================================= #=======================================================================================================================
project('video-streaming-poc', 'cpp') project('video-streaming-poc', 'cpp', version : '0.0.1-SNAPSHOT',
default_options : ['c_std=c17', 'cpp_std=c++20'])
#======================================================================================================================= #=======================================================================================================================
# DEPENDENCIES # DEPENDENCIES
@ -13,7 +14,7 @@ opencv = dependency('opencv4', version : '>=4.0.0')
# SOURCE FILES # SOURCE FILES
#======================================================================================================================= #=======================================================================================================================
# common files between client / server # common files between client / server
common = ['transfer.h'] common = ['transfer.h', 'logging.h']
# client-only files # client-only files
client = common + ['client.cpp'] client = common + ['client.cpp']
# server-only files # server-only files

View File

@ -24,12 +24,13 @@ int main() {
bind(serverSocket, reinterpret_cast<sockaddr *>(&serverAddress), bind(serverSocket, reinterpret_cast<sockaddr *>(&serverAddress),
sizeof(serverAddress)); sizeof(serverAddress));
info("Ready to accept connections.");
// listening to the assigned socket // listening to the assigned socket
listen(serverSocket, 5); listen(serverSocket, 5);
// accepting connection request // accepting connection request
int clientSocket int clientSocket = accept(serverSocket, nullptr, nullptr);
= accept(serverSocket, nullptr, nullptr); info("Client connected.");
// TODO: handle multiple images // TODO: handle multiple images
cv::Mat image = cv::Mat::zeros(cv::Size(640, 480), CV_8UC3); cv::Mat image = cv::Mat::zeros(cv::Size(640, 480), CV_8UC3);
@ -39,14 +40,13 @@ int main() {
while (running) { while (running) {
// receive data // receive data
vector<uchar> buffer; vector<uchar> buffer;
trace("Receiving image");
cout << "Receiving image" << endl;
recvImage(clientSocket, buffer); recvImage(clientSocket, buffer);
cout << "Applying image" << endl; trace("Applying new data to image");
applyImage(image, &buffer); applyImage(image, &buffer);
cout << "Displaying image" << endl; trace("Displaying image");
imshow("image", image); imshow("image", image);
running = cv::waitKey(30) != 27; running = cv::waitKey(30) != 27;
} }

View File

@ -4,7 +4,24 @@
#include <opencv2/core/mat.hpp> #include <opencv2/core/mat.hpp>
#include <opencv2/imgcodecs.hpp> #include <opencv2/imgcodecs.hpp>
#include <sys/socket.h> #include <sys/socket.h>
#include <iostream> #include <logging.h>
using namespace std;
struct imageHeader {
size_t size;
chrono::milliseconds timestamp;
};
chrono::milliseconds getMillis() {
// Get current time
const auto now = chrono::system_clock::now();
// Get time since epoch in milliseconds
const chrono::duration ms = chrono::duration_cast<chrono::milliseconds>(now.time_since_epoch());
return chrono::milliseconds(ms.count());
}
inline void serializeImage(const cv::Mat& image, std::vector<uchar>& buffer) { inline void serializeImage(const cv::Mat& image, std::vector<uchar>& buffer) {
cv::imencode(".jpg", image, buffer); cv::imencode(".jpg", image, buffer);
@ -16,9 +33,13 @@ int sendImage(int socket, const cv::Mat& image, std::vector<uchar>& buffer) {
// first send the size of the serialized image // first send the size of the serialized image
const size_t size = buffer.size(); const size_t size = buffer.size();
std::cout << "Buffer size: " << size << std::endl; const chrono::milliseconds timestamp = getMillis();
if (const ssize_t sent = send(socket, &size, sizeof(size), 0); sent == -1) { imageHeader header;
perror("Error sending data"); header.size = size;
header.timestamp = timestamp;
trace("Buffer size: ", size);
if (const ssize_t sent = send(socket, &header, sizeof(header), 0); sent == -1) {
error("Error sending data header");
return -1; return -1;
} }
@ -26,25 +47,27 @@ int sendImage(int socket, const cv::Mat& image, std::vector<uchar>& buffer) {
while (totalSent < size) { while (totalSent < size) {
const ssize_t sent = send(socket, buffer.data() + totalSent, size - totalSent, 0); const ssize_t sent = send(socket, buffer.data() + totalSent, size - totalSent, 0);
if (sent == -1) { if (sent == -1) {
perror("Error sending data"); error("Error sending data");
return -1; return -1;
} }
totalSent += sent; totalSent += sent;
std::cout << "Packet sent (" << sent << " bytes, total " << totalSent << " bytes)" << std::endl; debug("Packet sent (", sent, " bytes, total ", totalSent, " bytes)");
} }
return 0; return 0;
} }
int recvImage(int socket, std::vector<uchar>& buffer) { int recvImage(int socket, std::vector<uchar>& buffer) {
size_t dataSize;
// first receive the size of the image // first receive the size of the image
ssize_t sizeReceived = recv(socket, &dataSize, sizeof(size_t), 0); imageHeader header;
if (sizeReceived <= 0) { if (ssize_t recvd = recv(socket, &header, sizeof(imageHeader), 0); recvd <= 0) {
error("Error receiving data header");
return -1; return -1;
} }
std::cout << "Buffer size: " << dataSize << std::endl; size_t dataSize = header.size;
chrono::milliseconds sentTime = header.timestamp;
trace("Buffer size: ", dataSize);
// resize the buffer to fit the whole image // resize the buffer to fit the whole image
buffer.resize(dataSize); buffer.resize(dataSize);
@ -54,18 +77,23 @@ int recvImage(int socket, std::vector<uchar>& buffer) {
while (totalReceived < dataSize) { while (totalReceived < dataSize) {
ssize_t bytesReceived = recv(socket, buffer.data() + totalReceived, dataSize, 0); ssize_t bytesReceived = recv(socket, buffer.data() + totalReceived, dataSize, 0);
if (bytesReceived <= 0) { if (bytesReceived <= 0) {
error("Error receiving data");
buffer.clear(); buffer.clear();
return -1; return -1;
} }
totalReceived += bytesReceived; totalReceived += bytesReceived;
std::cout << "Packet received (" << bytesReceived << " bytes, total " << totalReceived << " bytes)" << std::endl; debug("Packet received (", bytesReceived, " bytes, total ", totalReceived, " bytes)");
} }
chrono::milliseconds currentTime = getMillis();
chrono::milliseconds diff = currentTime - sentTime;
debug("Packet latency: ", diff.count(), "ms");
return 0; return 0;
} }
bool applyImage(cv::Mat& image, std::vector<uchar> *src) { bool applyImage(cv::Mat& image, std::vector<uchar> *src) {
// decode the image into an OpenCV Mat // decode the image into an OpenCV Mat
cv::imdecode(*src, 0, &image); cv::imdecode(*src, cv::IMREAD_UNCHANGED, &image);
return true; return true;
} }
#endif //TRANSFER_H #endif //TRANSFER_H