增加扩展屏的框架

This commit is contained in:
huanglinhuan
2025-12-22 13:48:06 +08:00
parent 1bf30d3c4c
commit 065251f727
13 changed files with 834 additions and 28 deletions

View File

@@ -1,5 +1,6 @@
#include "NetworkSender.h"
#include "ScreenCapture.h"
#include "IddBridge.h"
#include "VideoEncoder.h"
#include <iostream>
#include <sstream>
@@ -7,15 +8,36 @@
#include <thread>
#include <chrono>
#include <fstream>
#include <windows.h>
int main(int argc, char* argv[]) {
std::string ipStr = "127.0.0.1";
int port = 8888;
std::string outputFileName = "";
std::string source = "screen";
int outputIndex = -1;
bool iddProducer = false;
int producerOutputIndex = -1;
if (argc > 1) ipStr = argv[1];
if (argc > 2) port = std::stoi(argv[2]);
if (argc > 3) outputFileName = argv[3];
for (int i = 4; i < argc; ++i) {
std::string arg = argv[i];
if (arg.rfind("--source=", 0) == 0) {
source = arg.substr(std::string("--source=").size());
} else if (arg.rfind("--output=", 0) == 0) {
try {
outputIndex = std::stoi(arg.substr(std::string("--output=").size()));
} catch (...) {}
} else if (arg == "--idd-producer") {
iddProducer = true;
} else if (arg.rfind("--producer-output=", 0) == 0) {
try {
producerOutputIndex = std::stoi(arg.substr(std::string("--producer-output=").size()));
} catch (...) {}
}
}
// Parse IPs
std::vector<std::string> ips;
@@ -33,9 +55,19 @@ int main(int argc, char* argv[]) {
std::cout << "Targets: ";
for (const auto& ip : ips) std::cout << ip << " ";
std::cout << ", Port: " << port << std::endl;
std::cout << "Source: " << source << std::endl;
if (source == "screen" && outputIndex >= 0) {
std::cout << "Output Index: " << outputIndex << std::endl;
}
if (!outputFileName.empty()) {
std::cout << "Output File: " << outputFileName << std::endl;
}
if (source == "idd" && iddProducer) {
std::cout << "IDD Producer enabled" << std::endl;
if (producerOutputIndex >= 0) {
std::cout << "Producer Output Index: " << producerOutputIndex << std::endl;
}
}
// Debug: Open file to save H.264 stream if filename is provided
std::ofstream outFile;
@@ -48,29 +80,96 @@ int main(int argc, char* argv[]) {
}
}
std::thread producerThread;
if (source == "idd" && iddProducer) {
producerThread = std::thread([producerOutputIndex]() {
ScreenCapture cap;
bool okCap = false;
if (producerOutputIndex >= 0) okCap = cap.InitializeWithOutputIndex(producerOutputIndex);
else okCap = cap.Initialize();
if (!okCap) return;
D3D11_TEXTURE2D_DESC desc = {};
ComPtr<ID3D11Texture2D> frame;
while (!cap.CaptureFrame(frame)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
frame->GetDesc(&desc);
cap.ReleaseFrame();
D3D11_TEXTURE2D_DESC sdesc = {};
sdesc.Width = desc.Width;
sdesc.Height = desc.Height;
sdesc.MipLevels = 1;
sdesc.ArraySize = 1;
sdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
sdesc.SampleDesc.Count = 1;
sdesc.Usage = D3D11_USAGE_STAGING;
sdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
ComPtr<ID3D11Texture2D> staging;
cap.GetDevice()->CreateTexture2D(&sdesc, nullptr, &staging);
IddProducer producer;
if (!producer.Initialize()) return;
while (true) {
ComPtr<ID3D11Texture2D> tex;
if (cap.CaptureFrame(tex)) {
cap.GetContext()->CopyResource(staging.Get(), tex.Get());
D3D11_MAPPED_SUBRESOURCE mapped = {};
if (SUCCEEDED(cap.GetContext()->Map(staging.Get(), 0, D3D11_MAP_READ, 0, &mapped))) {
producer.SubmitFrame(mapped.pData, desc.Width, desc.Height, (uint32_t)mapped.RowPitch);
cap.GetContext()->Unmap(staging.Get(), 0);
}
cap.ReleaseFrame();
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
});
}
bool ok = false;
ScreenCapture capture;
if (!capture.Initialize()) {
std::cerr << "Failed to initialize Screen Capture" << std::endl;
IddBridge idd;
bool useIdd = (source == "idd");
if (useIdd) {
ok = idd.Initialize();
} else {
if (outputIndex >= 0) {
ok = capture.InitializeWithOutputIndex(outputIndex);
} else {
ok = capture.Initialize();
}
}
if (!ok) {
std::cerr << "Failed to initialize capture source" << std::endl;
return 1;
}
// Get screen size
D3D11_TEXTURE2D_DESC desc;
ComPtr<ID3D11Texture2D> frame;
// Capture one frame to get size
std::cout << "Waiting for first frame..." << std::endl;
while (!capture.CaptureFrame(frame)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (useIdd) {
while (!idd.CaptureFrame(frame)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
} else {
while (!capture.CaptureFrame(frame)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
frame->GetDesc(&desc);
capture.ReleaseFrame();
if (useIdd) {
idd.ReleaseFrame();
} else {
capture.ReleaseFrame();
}
int width = desc.Width;
int height = desc.Height;
std::cout << "Screen Size: " << width << "x" << height << std::endl;
VideoEncoder encoder;
if (!encoder.Initialize(capture.GetDevice(), width, height, 60, 4000000)) { // 4Mbps
if (!encoder.Initialize(useIdd ? idd.GetDevice() : capture.GetDevice(), width, height, 60, 4000000)) {
std::cerr << "Failed to initialize Video Encoder" << std::endl;
return 1;
}
@@ -88,7 +187,24 @@ int main(int argc, char* argv[]) {
while (true) {
ComPtr<ID3D11Texture2D> texture;
if (capture.CaptureFrame(texture)) {
bool got = false;
if (useIdd) {
got = idd.CaptureFrame(texture);
} else {
got = capture.CaptureFrame(texture);
}
if (got) {
D3D11_TEXTURE2D_DESC tdesc = {};
texture->GetDesc(&tdesc);
if (tdesc.Width != (UINT)width || tdesc.Height != (UINT)height) {
std::cout << "Resolution changed: " << width << "x" << height << " -> " << tdesc.Width << "x" << tdesc.Height << std::endl;
width = (int)tdesc.Width;
height = (int)tdesc.Height;
if (!encoder.Reinitialize(width, height, 60, 4000000)) {
std::cerr << "Failed to reinitialize encoder on resolution change" << std::endl;
break;
}
}
std::vector<uint8_t> encodedData;
bool isKeyFrame = false;
@@ -106,7 +222,11 @@ int main(int argc, char* argv[]) {
}
}
}
capture.ReleaseFrame();
if (useIdd) {
idd.ReleaseFrame();
} else {
capture.ReleaseFrame();
}
frameCount++;
}