rewrite packets to send in jpeg form
This commit is contained in:
parent
c85581749b
commit
ea952e1981
27
client.cpp
27
client.cpp
@ -4,13 +4,15 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <packets/ImagePacket.h>
|
||||
#include "transfer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
cv::VideoCapture cap = cv::VideoCapture(0);
|
||||
// create video capture
|
||||
//cv::VideoCapture cap = cv::VideoCapture(0);
|
||||
|
||||
// create socket
|
||||
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
// specifying address
|
||||
@ -19,26 +21,19 @@ int main() {
|
||||
serverAddress.sin_port = htons(8080);
|
||||
serverAddress.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
cv::Mat image = cv::Mat::zeros(cv::Size(640, 480), CV_8UC3);
|
||||
ImagePacket packet = ImagePacket(&image, 0);
|
||||
cv::Mat image = cv::Mat(cv::Size(640, 480), CV_8UC3, cv::Scalar(255, 0, 0));
|
||||
|
||||
// sending connection request
|
||||
connect(clientSocket, (struct sockaddr*)&serverAddress,
|
||||
connect(clientSocket, reinterpret_cast<sockaddr *>(&serverAddress),
|
||||
sizeof(serverAddress));
|
||||
|
||||
unsigned long pos = 0;
|
||||
unsigned long len = image.total() * image.elemSize();
|
||||
char buffer[IMAGEPACKET_SIZE];
|
||||
|
||||
cout << "Image length " << len << endl;
|
||||
// create buffer for serialization
|
||||
vector<uchar> imgbuf;
|
||||
|
||||
while (true) {
|
||||
cap.read(image);
|
||||
packet = ImagePacket(&image, pos);
|
||||
packet.serialize(buffer);
|
||||
send(clientSocket, buffer, sizeof(buffer), 0);
|
||||
cout << "Sent packet with index " << pos << endl;
|
||||
pos = (pos + SLICE_SIZE) % len;
|
||||
//cap.read(image);
|
||||
cout << "Sending image" << endl;
|
||||
sendImage(clientSocket, image, imgbuf);
|
||||
}
|
||||
|
||||
close(clientSocket);
|
||||
|
@ -13,7 +13,7 @@ opencv = dependency('opencv4', version : '>=4.0.0')
|
||||
# SOURCE FILES
|
||||
#=======================================================================================================================
|
||||
# common files between client / server
|
||||
common = ['packets/ImagePacket.cpp', 'packets/ImagePacket.h']
|
||||
common = ['transfer.h']
|
||||
# client-only files
|
||||
client = common + ['client.cpp']
|
||||
# server-only files
|
||||
|
@ -1,56 +0,0 @@
|
||||
#include "ImagePacket.h"
|
||||
|
||||
/*
|
||||
* Construct a packet from a raw array of unsigned chars, and a beginning index. It will take PACKET_SIZE bytes from the
|
||||
* start and add it to its slice. This will be more useful for embedded scenarios where OpenCV will likely not be used.
|
||||
*/
|
||||
ImagePacket::ImagePacket(const uchar *image, const int begin) {
|
||||
this->begin = begin;
|
||||
this->slice = new uchar[SLICE_SIZE];
|
||||
const uchar *target = &image[begin];
|
||||
// TODO: handle out of index cases, pad with zeroes. probably also instantiate our byte array with zeroes
|
||||
for (int i = 0; i < SLICE_SIZE; i++) {
|
||||
this->slice[i] = target[begin + i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* destructor frees memory
|
||||
*/
|
||||
ImagePacket::~ImagePacket() = default;
|
||||
|
||||
unsigned long ImagePacket::getBegin() const {
|
||||
return this->begin;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Apply the packet to an OpenCV Mat.
|
||||
*/
|
||||
int ImagePacket::apply(const cv::Mat *image) const {
|
||||
uchar *target = &image->data[this->begin];
|
||||
// TODO: handle out of index cases
|
||||
for (int i = 0; i < SLICE_SIZE; i++) {
|
||||
target[this->begin + i] = this->slice[i];
|
||||
}
|
||||
// TODO: return the actual written size of the packet
|
||||
return SLICE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize the object into a byte array
|
||||
*/
|
||||
void ImagePacket::serialize(char* buffer) const {
|
||||
// TODO: keep the endianness consistent between systems
|
||||
std::memcpy(buffer, &this->begin, sizeof(this->begin));
|
||||
std::memcpy(buffer + sizeof(this->begin), &this->slice, SLICE_SIZE * sizeof(uchar));
|
||||
}
|
||||
|
||||
/*
|
||||
* Deserialize the object from a byte array
|
||||
*/
|
||||
void ImagePacket::deserialize(char* buffer) {
|
||||
// TODO: keep the endianness consistent between systems
|
||||
std::memcpy(&this->begin, buffer, sizeof(this->begin));
|
||||
std::memcpy(this->slice, buffer + sizeof(this->begin), SLICE_SIZE * sizeof(uchar));
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#ifndef IMAGEPACKET_H
|
||||
#define IMAGEPACKET_H
|
||||
#include <opencv2/core/mat.hpp>
|
||||
|
||||
#define SLICE_SIZE 768
|
||||
#define IMAGEPACKET_SIZE sizeof(int) + (SLICE_SIZE * sizeof(uchar))
|
||||
|
||||
class ImagePacket {
|
||||
public:
|
||||
ImagePacket(const cv::Mat *image, int begin) : ImagePacket(image->data, begin) {}
|
||||
ImagePacket(const uchar *image, int begin);
|
||||
~ImagePacket();
|
||||
|
||||
unsigned long getBegin() const;
|
||||
int apply(const cv::Mat *image) const;
|
||||
|
||||
void serialize(char* buffer) const;
|
||||
void deserialize(char* buffer);
|
||||
private:
|
||||
unsigned long begin;
|
||||
uchar *slice;
|
||||
};
|
||||
|
||||
#endif //IMAGEPACKET_H
|
22
server.cpp
22
server.cpp
@ -5,7 +5,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <packets/ImagePacket.h>
|
||||
#include "transfer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -21,7 +21,7 @@ int main() {
|
||||
serverAddress.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
// binding socket.
|
||||
bind(serverSocket, (struct sockaddr*)&serverAddress,
|
||||
bind(serverSocket, reinterpret_cast<sockaddr *>(&serverAddress),
|
||||
sizeof(serverAddress));
|
||||
|
||||
// listening to the assigned socket
|
||||
@ -32,21 +32,21 @@ int main() {
|
||||
= accept(serverSocket, nullptr, nullptr);
|
||||
|
||||
// TODO: handle multiple images
|
||||
cv::Mat image = cv::Mat::zeros(480, 640, CV_8UC3);
|
||||
|
||||
// setup packet buffer
|
||||
char buffer[IMAGEPACKET_SIZE] = { 0 };
|
||||
ImagePacket packet = ImagePacket(&image, 0);
|
||||
cv::Mat image = cv::Mat::zeros(cv::Size(640, 480), CV_8UC3);
|
||||
|
||||
bool running = true;
|
||||
// TODO: make this asynchronous. probably do that in tandem with setting up networking
|
||||
while (running) {
|
||||
// receive data
|
||||
recv(clientSocket, buffer, sizeof(buffer), 0);
|
||||
packet.deserialize(buffer);
|
||||
cout << "received packet with index " << packet.getBegin() << endl;
|
||||
packet.apply(&image);
|
||||
vector<uchar> buffer;
|
||||
|
||||
cout << "Receiving image" << endl;
|
||||
recvImage(clientSocket, buffer);
|
||||
|
||||
cout << "Applying image" << endl;
|
||||
applyImage(image, &buffer);
|
||||
|
||||
cout << "Displaying image" << endl;
|
||||
imshow("image", image);
|
||||
running = cv::waitKey(30) != 27;
|
||||
}
|
||||
|
71
transfer.h
Normal file
71
transfer.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef TRANSFER_H
|
||||
#define TRANSFER_H
|
||||
|
||||
#include <opencv2/core/mat.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <sys/socket.h>
|
||||
#include <iostream>
|
||||
|
||||
inline void serializeImage(const cv::Mat& image, std::vector<uchar>& buffer) {
|
||||
cv::imencode(".jpg", image, buffer);
|
||||
}
|
||||
|
||||
int sendImage(int socket, const cv::Mat& image, std::vector<uchar>& buffer) {
|
||||
serializeImage(image, buffer);
|
||||
size_t totalSent = 0;
|
||||
|
||||
// first send the size of the serialized image
|
||||
const size_t size = buffer.size();
|
||||
std::cout << "Buffer size: " << size << std::endl;
|
||||
if (const ssize_t sent = send(socket, &size, sizeof(size), 0); sent == -1) {
|
||||
perror("Error sending data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// then start sending the serialized image
|
||||
while (totalSent < size) {
|
||||
const ssize_t sent = send(socket, buffer.data() + totalSent, size - totalSent, 0);
|
||||
if (sent == -1) {
|
||||
perror("Error sending data");
|
||||
return -1;
|
||||
}
|
||||
totalSent += sent;
|
||||
std::cout << "Packet sent (" << sent << " bytes, total " << totalSent << " bytes)" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int recvImage(int socket, std::vector<uchar>& buffer) {
|
||||
size_t dataSize;
|
||||
|
||||
// first receive the size of the image
|
||||
ssize_t sizeReceived = recv(socket, &dataSize, sizeof(size_t), 0);
|
||||
if (sizeReceived <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Buffer size: " << dataSize << std::endl;
|
||||
|
||||
// resize the buffer to fit the whole image
|
||||
buffer.resize(dataSize);
|
||||
|
||||
// start receiving the image until the whole thing arrives
|
||||
size_t totalReceived = 0;
|
||||
while (totalReceived < dataSize) {
|
||||
ssize_t bytesReceived = recv(socket, buffer.data() + totalReceived, dataSize, 0);
|
||||
if (bytesReceived <= 0) {
|
||||
buffer.clear();
|
||||
return -1;
|
||||
}
|
||||
totalReceived += bytesReceived;
|
||||
std::cout << "Packet received (" << bytesReceived << " bytes, total " << totalReceived << " bytes)" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool applyImage(cv::Mat& image, std::vector<uchar> *src) {
|
||||
// decode the image into an OpenCV Mat
|
||||
cv::imdecode(*src, 0, &image);
|
||||
return true;
|
||||
}
|
||||
#endif //TRANSFER_H
|
Loading…
x
Reference in New Issue
Block a user