Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
a76cde97bf |
4 changed files with 192 additions and 38 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,6 +1,10 @@
|
|||
/target
|
||||
|
||||
# for gods sakes visual studio
|
||||
/agent/*.sdf
|
||||
/agent/x64
|
||||
/agent/**/x64
|
||||
/agent/ipch
|
||||
/agent/**/Release
|
||||
/agent/**/Debug
|
||||
/agent/*.suo
|
|
@ -97,13 +97,12 @@ class cStreamClient {
|
|||
send(tcpSocket, (const char*)&resize, sizeof(resize), 0);
|
||||
}
|
||||
|
||||
void SendData(const unique_buffer<u32>& data, u32 width, u32 height, const std::vector<tileRect>& tiles) {
|
||||
void SendData(cSurface& surface, const std::vector<tRect>& tiles) {
|
||||
tMessageHeader header;
|
||||
header.type = MessageType::Data;
|
||||
// header.datalen = data.get_size() * sizeof(UINT32);
|
||||
header.datalen = sizeof(tDataMessage);
|
||||
|
||||
auto* pData = data.data();
|
||||
|
||||
// send tile header
|
||||
bool sendFull = false;
|
||||
|
@ -122,6 +121,57 @@ class cStreamClient {
|
|||
|
||||
// send each tile
|
||||
if(!sendFull) {
|
||||
#if 0
|
||||
std::vector<std::unique_ptr<cSurface>> surfs;
|
||||
|
||||
for(auto& tile : tiles) {
|
||||
surfs.push_back(surface.ClonePiece(tile));
|
||||
}
|
||||
|
||||
for(usize i = 0; i < surfs.size(); ++i) {
|
||||
// things we want!
|
||||
auto& tile_rect = tiles[i];
|
||||
auto& surf = surfs[i];
|
||||
//const auto& siz
|
||||
auto* data = surf->Memory();
|
||||
|
||||
tTile tile_wire { tile_rect.x, tile_rect.y, tile_rect.width, tile_rect.height };
|
||||
|
||||
send(tcpSocket, (const char*)&tile_wire, (int)sizeof(tile_wire), 0);
|
||||
send(tcpSocket, (const char*)&data[0], (int)((tile_rect.width * tile_rect.height) * 4), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<u32> data;
|
||||
|
||||
for(auto& tile : tiles) {
|
||||
auto* pData = surface.Memory();
|
||||
|
||||
tTile tile_wire { tile.x, tile.y, tile.width, tile.height };
|
||||
|
||||
|
||||
data.resize(tile.width * tile.height * 4);
|
||||
|
||||
for (u32 y = 0; y < tile.height; ++y) {
|
||||
auto* pTileLineStart = &pData[(tile.y + y) * surface.Stride() + tile.x];
|
||||
memcpy(&data[y * tile.width], pTileLineStart, tile.width * sizeof(u32));
|
||||
}
|
||||
|
||||
// send header
|
||||
send(tcpSocket, (const char*)&tile_wire, (int)sizeof(tile_wire), 0);
|
||||
send(tcpSocket, (const char*)&data[0], (int)data.size(), 0);
|
||||
|
||||
|
||||
/*
|
||||
send(tcpSocket, (const char*)&tile_wire, (int)sizeof(tile_wire), 0);
|
||||
|
||||
|
||||
for(u32 y = 0; y < tile.height; ++y) {
|
||||
auto* pTileLineStart = &pData[(tile.y + y) * surface.Stride() + tile.x];
|
||||
send(tcpSocket, (const char*)&pTileLineStart[0], tile.width * sizeof(u32), 0);
|
||||
}*/
|
||||
}
|
||||
#if 0
|
||||
for(auto& tile : tiles) {
|
||||
tTile tile_wire { tile.x, tile.y, tile.width, tile.height };
|
||||
|
||||
|
@ -143,11 +193,19 @@ class cStreamClient {
|
|||
send(tcpSocket, (const char*)pTileLineStart, tile.width * sizeof(UINT32), 0);
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
tTile tDummyTile { 0, 0, width, height };
|
||||
auto& size = surface.Size();
|
||||
tTile tDummyTile { 0, 0, size.width, size.height };
|
||||
|
||||
send(tcpSocket, (const char*)&tDummyTile, sizeof(tDummyTile), 0);
|
||||
send(tcpSocket, (const char*)&data.data()[0], (i32)(data.get_size() * sizeof(u32)), 0);
|
||||
|
||||
for(auto y = 0; y < size.height; ++y) {
|
||||
auto* line = &surface.Memory()[y * surface.Stride()];
|
||||
send(tcpSocket, (const char*)&line[0], (i32)(size.width * sizeof(u32)), 0);
|
||||
}
|
||||
|
||||
//send(tcpSocket, (const char*)&data.data()[0], (i32)(data.get_size() * sizeof(u32)), 0);
|
||||
}
|
||||
|
||||
// send(tcpSocket, (const char*)&data.data()[0], data.get_size() * sizeof(UINT32), 0);
|
||||
|
@ -207,13 +265,13 @@ bool nvfbcCreate() {
|
|||
|
||||
int main(int argc, char** argv) {
|
||||
WSADATA data;
|
||||
if(WSAStartup(MAKEWORD(2, 2), &data) != NO_ERROR) {
|
||||
if (WSAStartup(MAKEWORD(2, 2), &data) != NO_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
cStreamClient* client = new cStreamClient();
|
||||
|
||||
if(!client->Connect("192.168.1.149", 9438)) {
|
||||
if (!client->Connect("192.168.1.149", 9438)) {
|
||||
printf("conn failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -221,12 +279,12 @@ int main(int argc, char** argv) {
|
|||
nvfbcLibrary = new NvFBCLibrary();
|
||||
|
||||
//! Load NvFBC
|
||||
if(!nvfbcLibrary->load()) {
|
||||
if (!nvfbcLibrary->load()) {
|
||||
fprintf(stderr, "Unable to load the NvFBC library\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!nvfbcCreate()) {
|
||||
if (!nvfbcCreate()) {
|
||||
fprintf(stderr, "Unable to create an instance of NvFBC\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -239,15 +297,15 @@ int main(int argc, char** argv) {
|
|||
BOOL bRecoveryDone = FALSE;
|
||||
|
||||
NvFBCFrameGrabInfo grabInfo;
|
||||
unique_buffer<u32> buffer;
|
||||
//unique_buffer<u32> buffer;
|
||||
|
||||
if(nvfbcSetup()) {
|
||||
if (nvfbcSetup()) {
|
||||
// Sleep so that ToSysSetUp forces a framebuffer update
|
||||
Sleep(100);
|
||||
|
||||
NVFBC_TOSYS_GRAB_FRAME_PARAMS fbcSysGrabParams = { 0 };
|
||||
|
||||
std::vector<tileRect> tiles {};
|
||||
std::vector<tRect> tiles{};
|
||||
|
||||
// set up grab parameters
|
||||
fbcSysGrabParams.dwVersion = NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER;
|
||||
|
@ -260,41 +318,45 @@ int main(int argc, char** argv) {
|
|||
fbcSysGrabParams.pNvFBCFrameGrabInfo = &grabInfo;
|
||||
fbcSysGrabParams.dwWaitTime = 16;
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
// Grab the frame
|
||||
status = nvfbcToSys->NvFBCToSysGrabFrame(&fbcSysGrabParams);
|
||||
if(status == NVFBC_SUCCESS) {
|
||||
if (status == NVFBC_SUCCESS) {
|
||||
bRecoveryDone = FALSE;
|
||||
|
||||
// handle resizing the buffer
|
||||
if(width != grabInfo.dwWidth || height != grabInfo.dwHeight) {
|
||||
if (width != grabInfo.dwWidth || height != grabInfo.dwHeight) {
|
||||
width = grabInfo.dwWidth;
|
||||
height = grabInfo.dwHeight;
|
||||
|
||||
buffer.resize(grabInfo.dwWidth * grabInfo.dwHeight);
|
||||
//buffer.resize(grabInfo.dwWidth * grabInfo.dwHeight);
|
||||
|
||||
firstFrame = true;
|
||||
client->SendResize(tResizeMessage { width, height });
|
||||
client->SendResize(tResizeMessage{ width, height });
|
||||
}
|
||||
|
||||
cSurface surf((u32*)frameBuffer, { width, height }, grabInfo.dwBufferWidth);
|
||||
|
||||
#if 0
|
||||
// splat the data into an unpadded buffer
|
||||
// REMOVE THIS
|
||||
for(u32 y = 0; y < grabInfo.dwHeight; ++y) {
|
||||
memcpy(&buffer.data()[y * grabInfo.dwWidth], &frameBuffer[(y * grabInfo.dwBufferWidth) * 4], grabInfo.dwWidth * 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
tiles.clear();
|
||||
|
||||
// diffmap
|
||||
if(firstFrame == false) {
|
||||
if (firstFrame == false) {
|
||||
u32 dwDiffMapWidth = (u32)ceil((f32)width / 32);
|
||||
u32 dwDiffMapHeight = (u32)ceil((f32)height / 32);
|
||||
|
||||
for(u32 y = 0; y < dwDiffMapHeight; ++y) {
|
||||
for(u32 x = 0; x < dwDiffMapWidth; ++x) {
|
||||
for (u32 y = 0; y < dwDiffMapHeight; ++y) {
|
||||
for (u32 x = 0; x < dwDiffMapWidth; ++x) {
|
||||
auto& bl = diffMap[y * dwDiffMapWidth + x];
|
||||
if(bl != 0) {
|
||||
tiles.push_back(tileRect {
|
||||
if (bl != 0) {
|
||||
tiles.push_back(tRect{
|
||||
x * (width / dwDiffMapWidth), // x
|
||||
y * (height / dwDiffMapHeight), // y
|
||||
width / dwDiffMapWidth, // width
|
||||
|
@ -303,36 +365,45 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// don't send a frame, just wait
|
||||
if (tiles.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
// send that to the server
|
||||
client->SendData(buffer, width, height, tiles);
|
||||
|
||||
if(firstFrame)
|
||||
|
||||
// send that to the server
|
||||
//client->SendData(buffer, width, height, tiles);
|
||||
client->SendData(surf, tiles);
|
||||
|
||||
if (firstFrame)
|
||||
firstFrame = false;
|
||||
} else {
|
||||
if(bRecoveryDone == TRUE) {
|
||||
}
|
||||
else {
|
||||
if (bRecoveryDone == TRUE) {
|
||||
fprintf(stderr, "Unable to recover from NvFBC Frame grab failure.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(status == NVFBC_ERROR_DYNAMIC_DISABLE) {
|
||||
if (status == NVFBC_ERROR_DYNAMIC_DISABLE) {
|
||||
fprintf(stderr, "NvFBC disabled. Quitting\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Try to recover the session
|
||||
if(status == NVFBC_ERROR_INVALIDATED_SESSION) {
|
||||
if (status == NVFBC_ERROR_INVALIDATED_SESSION) {
|
||||
fprintf(stderr, "Session Invalidated. Attempting recovery\n");
|
||||
|
||||
if(!nvfbcCreate()) {
|
||||
if (!nvfbcCreate()) {
|
||||
fprintf(stderr, "Unable to re-create NvFBC\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(nvfbcSetup()) {
|
||||
if (nvfbcSetup()) {
|
||||
bRecoveryDone = TRUE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Unable to recover from NvFBC Frame grab failure.\n");
|
||||
break;
|
||||
}
|
||||
|
@ -341,7 +412,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if(status != NVFBC_SUCCESS) {
|
||||
if (status != NVFBC_SUCCESS) {
|
||||
fprintf(stderr, "Unable to setup frame grab.\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
// common types
|
||||
using u8 = std::uint8_t;
|
||||
|
@ -15,6 +17,83 @@ using usize = std::size_t;
|
|||
using f32 = float;
|
||||
using f64 = double;
|
||||
|
||||
struct tSize {
|
||||
u32 width;
|
||||
u32 height;
|
||||
};
|
||||
|
||||
struct tRect {
|
||||
u32 x;
|
||||
u32 y;
|
||||
u32 width;
|
||||
u32 height;
|
||||
};
|
||||
|
||||
struct cSurface {
|
||||
private:
|
||||
u32* pBuffer;
|
||||
tSize size;
|
||||
u32 stride;
|
||||
bool owned { false };
|
||||
|
||||
struct OwnedTag {};
|
||||
|
||||
public:
|
||||
cSurface(u32* pBuffer, const tSize& size, u32 stride = -1) {
|
||||
if(stride == -1) {
|
||||
this->stride = size.width;
|
||||
} else {
|
||||
this->stride = stride;
|
||||
}
|
||||
|
||||
this->size = size;
|
||||
this->pBuffer = pBuffer;
|
||||
this->owned = false;
|
||||
}
|
||||
|
||||
cSurface(u32* pBuffer, const tSize& size, OwnedTag) {
|
||||
this->pBuffer = pBuffer;
|
||||
this->size = size;
|
||||
owned = true;
|
||||
}
|
||||
|
||||
~cSurface() {
|
||||
if(owned) {
|
||||
delete[] pBuffer;
|
||||
this->pBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
cSurface(const cSurface&) = delete;
|
||||
cSurface(cSurface&& move) {
|
||||
this->pBuffer = move.pBuffer;
|
||||
move.pBuffer = nullptr;
|
||||
this->size = {};
|
||||
this->stride = -1;
|
||||
this->owned = move.owned;
|
||||
move.owned = false;
|
||||
}
|
||||
|
||||
u32 Stride() const { return stride; }
|
||||
u32 StrideBytes() const { return stride * sizeof(u32); }
|
||||
|
||||
const tSize& Size() const { return size; }
|
||||
|
||||
u32* Memory() { return &this->pBuffer[0]; }
|
||||
|
||||
// creates a new owned cSurface which owns this memory
|
||||
std::unique_ptr<cSurface> ClonePiece(const tRect& rect) {
|
||||
auto* pSurfaceMemory = new u32[rect.width * rect.height * sizeof(u32)];
|
||||
|
||||
for(u32 y = 0; y < rect.height; ++y) {
|
||||
auto* pTileLineStart = &pBuffer[(rect.y + y) * this->stride + rect.x];
|
||||
memcpy(&pSurfaceMemory[y * rect.width], pTileLineStart, rect.width * sizeof(u32));
|
||||
}
|
||||
|
||||
return std::unique_ptr<cSurface>(new cSurface(pSurfaceMemory, { rect.width, rect.height }, OwnedTag {}));
|
||||
}
|
||||
};
|
||||
|
||||
/// like vector<T> but doesn't grow on its own
|
||||
template <class T>
|
||||
struct unique_buffer {
|
||||
|
|
|
@ -37,7 +37,7 @@ fn read_message(stream: &mut TcpStream, argb_buffer: &mut Vec<u32>, width: u32)
|
|||
MESSAGETYPE_DATA => {
|
||||
let tile_count = stream.read_u32::<LittleEndian>().expect("fuck");
|
||||
|
||||
println!("{tile_count} tiles");
|
||||
// println!("{tile_count} tiles");
|
||||
|
||||
for i in 0..tile_count {
|
||||
// tile rect
|
||||
|
|
Loading…
Reference in a new issue