2024-11-20 21:29:22 -05:00
|
|
|
// clang-format off
|
2024-11-20 21:26:35 -05:00
|
|
|
#pragma comment(lib, "ws2_32.lib")
|
|
|
|
#include <WinSock2.h>
|
|
|
|
#include <ws2tcpip.h>
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
#include "capture.hpp"
|
2024-11-20 21:26:35 -05:00
|
|
|
#include "Utils.hpp"
|
2024-11-20 21:29:22 -05:00
|
|
|
// clang-format on
|
2024-11-20 21:26:35 -05:00
|
|
|
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
enum class MessageType : u32 {
|
|
|
|
Resize, // tResizeMessage
|
2024-11-20 21:29:22 -05:00
|
|
|
Data, // tDataMessage
|
2024-11-20 21:26:35 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
struct tMessageHeader {
|
|
|
|
MessageType type;
|
|
|
|
u32 datalen;
|
|
|
|
// data
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tResizeMessage {
|
|
|
|
u32 width;
|
|
|
|
u32 height;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tTile {
|
|
|
|
u32 tile_x;
|
|
|
|
u32 tile_y;
|
|
|
|
|
|
|
|
u32 tile_width;
|
|
|
|
u32 tile_height;
|
|
|
|
|
|
|
|
// u32 tile_rgba[tile_width*tile_height]
|
|
|
|
};
|
|
|
|
|
|
|
|
struct tDataMessage {
|
|
|
|
u32 tileCount;
|
|
|
|
};
|
|
|
|
|
|
|
|
#pragma pack(pop)
|
|
|
|
|
|
|
|
struct tileRect {
|
|
|
|
u32 x, y, width, height;
|
|
|
|
};
|
|
|
|
|
|
|
|
// client for streamserver
|
|
|
|
class cStreamClient {
|
2024-11-20 21:29:22 -05:00
|
|
|
SOCKET tcpSocket { -1 };
|
|
|
|
|
|
|
|
public:
|
2024-11-20 21:26:35 -05:00
|
|
|
cStreamClient() = default;
|
|
|
|
|
|
|
|
~cStreamClient() {
|
2024-11-20 21:29:22 -05:00
|
|
|
if(tcpSocket != -1) {
|
2024-11-20 21:26:35 -05:00
|
|
|
closesocket(tcpSocket);
|
|
|
|
tcpSocket = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Connect(const char* address, int port) {
|
|
|
|
tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
2024-11-20 21:29:22 -05:00
|
|
|
if(tcpSocket == -1) {
|
2024-11-20 21:26:35 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
sockaddr_in clientSvc {};
|
2024-11-20 21:26:35 -05:00
|
|
|
clientSvc.sin_family = AF_INET;
|
|
|
|
inet_pton(AF_INET, address, &clientSvc.sin_addr.s_addr);
|
|
|
|
clientSvc.sin_port = htons(port);
|
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
if(connect(tcpSocket, (SOCKADDR*)&clientSvc, sizeof(clientSvc)) == SOCKET_ERROR) {
|
2024-11-20 21:26:35 -05:00
|
|
|
printf("No connection socket. Fuck you\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// disable Nagle's alrogithm
|
|
|
|
int nodelay = 1;
|
|
|
|
setsockopt(tcpSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&nodelay, sizeof(nodelay));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SendResize(const tResizeMessage& resize) {
|
|
|
|
tMessageHeader header;
|
|
|
|
header.type = MessageType::Resize;
|
|
|
|
header.datalen = sizeof(tResizeMessage);
|
|
|
|
|
|
|
|
send(tcpSocket, (const char*)&header, sizeof(header), 0);
|
|
|
|
send(tcpSocket, (const char*)&resize, sizeof(resize), 0);
|
|
|
|
}
|
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
void SendData(const u32* pData, u32 width, u32 height, const std::vector<tileRect>& tiles) {
|
2024-11-20 21:26:35 -05:00
|
|
|
tMessageHeader header;
|
|
|
|
header.type = MessageType::Data;
|
2024-11-20 21:29:22 -05:00
|
|
|
// header.datalen = data.get_size() * sizeof(UINT32);
|
2024-11-20 21:26:35 -05:00
|
|
|
header.datalen = sizeof(tDataMessage);
|
|
|
|
|
|
|
|
|
|
|
|
// send tile header
|
|
|
|
bool sendFull = false;
|
|
|
|
tDataMessage dm;
|
2024-11-23 21:29:59 -05:00
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
if(tiles.empty()) {
|
2024-11-23 21:29:59 -05:00
|
|
|
// Send the full screen as a "tile"
|
2024-11-20 21:26:35 -05:00
|
|
|
dm.tileCount = 1;
|
|
|
|
sendFull = true;
|
2024-11-20 21:29:22 -05:00
|
|
|
} else {
|
2024-11-20 21:26:35 -05:00
|
|
|
dm.tileCount = (u32)tiles.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
// we have writev() at home
|
|
|
|
// writev() at home:
|
|
|
|
send(tcpSocket, (const char*)&header, sizeof(header), 0);
|
|
|
|
send(tcpSocket, (const char*)&dm, sizeof(dm), 0);
|
|
|
|
|
|
|
|
// send each tile
|
2024-11-20 21:29:22 -05:00
|
|
|
if(!sendFull) {
|
|
|
|
for(auto& tile : tiles) {
|
|
|
|
tTile tile_wire { tile.x, tile.y, tile.width, tile.height };
|
2024-11-20 21:26:35 -05:00
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
std::vector<u32> tileData;
|
|
|
|
tileData.resize(tile.width * tile.height);
|
2024-11-20 21:26:35 -05:00
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
for(u32 y = 0; y < tile.height; ++y) {
|
2024-11-20 21:26:35 -05:00
|
|
|
auto* pTileLineStart = &pData[(tile.y + y) * width + tile.x];
|
2024-11-23 21:29:59 -05:00
|
|
|
memcpy(&tileData[y * tile.width], pTileLineStart, tile.width * sizeof(u32));
|
2024-11-20 21:26:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// send header
|
2024-11-23 21:31:15 -05:00
|
|
|
send(tcpSocket, (const char*)&tile_wire, (i32)sizeof(tile_wire), 0);
|
|
|
|
send(tcpSocket, (const char*)&tileData[0], (i32)tileData.size() * 4, 0);
|
2024-11-20 21:26:35 -05:00
|
|
|
|
|
|
|
// send data now
|
|
|
|
/*for (auto y = tile.y; y < tile.y + tile.height; ++y) {
|
|
|
|
auto* pTileLineStart = &pData[y * width + tile.x];
|
|
|
|
send(tcpSocket, (const char*)pTileLineStart, tile.width * sizeof(UINT32), 0);
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
} else {
|
2024-11-20 21:29:22 -05:00
|
|
|
tTile tDummyTile { 0, 0, width, height };
|
2024-11-20 21:26:35 -05:00
|
|
|
send(tcpSocket, (const char*)&tDummyTile, sizeof(tDummyTile), 0);
|
2024-11-23 21:29:59 -05:00
|
|
|
send(tcpSocket, (const char*)&pData[0], (i32)((width * height) * sizeof(u32)), 0);
|
2024-11-20 21:26:35 -05:00
|
|
|
}
|
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
// send(tcpSocket, (const char*)&data.data()[0], data.get_size() * sizeof(UINT32), 0);
|
2024-11-20 21:26:35 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
WSADATA data;
|
2024-11-20 21:29:22 -05:00
|
|
|
if(WSAStartup(MAKEWORD(2, 2), &data) != NO_ERROR) {
|
2024-11-20 21:26:35 -05:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
cStreamClient client;
|
2024-11-20 21:26:35 -05:00
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
if(!client.Connect("192.168.1.149", 9438)) {
|
2024-11-20 21:26:35 -05:00
|
|
|
printf("conn failed\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
// Create a capture interface
|
|
|
|
auto capture = hazelnut::CreateFramebufferCapture(hazelnut::GuessBestCaptureInterface());
|
|
|
|
if (!capture) {
|
|
|
|
printf("Failed to create a capture interface\n");
|
2024-11-20 21:26:35 -05:00
|
|
|
}
|
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
printf("Successfully created a framebuffer capture interface\n");
|
2024-11-20 21:26:35 -05:00
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
if(capture->Initialize()) {
|
|
|
|
// Sleep
|
2024-11-20 21:26:35 -05:00
|
|
|
Sleep(100);
|
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
bool firstFrame = true;
|
2024-11-20 21:29:22 -05:00
|
|
|
std::vector<tileRect> tiles {};
|
2024-11-23 21:29:59 -05:00
|
|
|
hazelnut::FramebufferInformation framebuffer{};
|
|
|
|
hazelnut::DiffInformation diff{};
|
2024-11-20 21:26:35 -05:00
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
while(true) {
|
2024-11-23 21:29:59 -05:00
|
|
|
auto result = capture->CaptureFrame();
|
|
|
|
if (result == hazelnut::DisplayCaptureResult::Ok || result == hazelnut::DisplayCaptureResult::OkButResized) {
|
|
|
|
// Check for resize.
|
|
|
|
if (result == hazelnut::DisplayCaptureResult::OkButResized) {
|
|
|
|
framebuffer = capture->GetFramebufferInformation();
|
|
|
|
diff = capture->GetDiffInformation();
|
2024-11-20 21:26:35 -05:00
|
|
|
firstFrame = true;
|
|
|
|
|
2024-11-23 21:29:59 -05:00
|
|
|
client.SendResize({ framebuffer.width, framebuffer.height });
|
2024-11-20 21:26:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
tiles.clear();
|
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
if(firstFrame == false) {
|
2024-11-23 21:29:59 -05:00
|
|
|
for(u32 y = 0; y < diff.diffMapHeight; ++y) {
|
|
|
|
for(u32 x = 0; x < diff.diffmapWidth; ++x) {
|
|
|
|
auto& bl = diff.pDiffMap[y * diff.diffmapWidth + x];
|
2024-11-20 21:29:22 -05:00
|
|
|
if(bl != 0) {
|
|
|
|
tiles.push_back(tileRect {
|
2024-11-23 21:29:59 -05:00
|
|
|
x * (framebuffer.width / diff.diffmapWidth), // x
|
|
|
|
y * (framebuffer.height / diff.diffMapHeight), // y
|
|
|
|
framebuffer.width / diff.diffmapWidth, // width
|
|
|
|
framebuffer.height / diff.diffMapHeight // height
|
2024-11-20 21:26:35 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// send that to the server
|
2024-11-23 21:29:59 -05:00
|
|
|
client.SendData(framebuffer.pFramebuffer, framebuffer.width, framebuffer.height, tiles);
|
2024-11-20 21:26:35 -05:00
|
|
|
|
2024-11-20 21:29:22 -05:00
|
|
|
if(firstFrame)
|
2024-11-20 21:26:35 -05:00
|
|
|
firstFrame = false;
|
|
|
|
} else {
|
2024-11-23 21:29:59 -05:00
|
|
|
printf("Failed to capture\n");
|
|
|
|
break;
|
2024-11-20 21:26:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|