更新捕获视频保存到文件和更新编译方法
This commit is contained in:
@@ -1,20 +1,24 @@
|
|||||||
# Windows Sender Demo
|
# Windows Sender Demo
|
||||||
|
|
||||||
This is a simplified demo of the Windows Host sender for DisplayFlow.
|
This is a simplified demo of the Windows Host sender for DisplayFlow.
|
||||||
|
|
||||||
It demonstrates:
|
It demonstrates:
|
||||||
1. Screen Capture using Desktop Duplication API (DXGI).
|
1. Screen Capture using Desktop Duplication API (DXGI).
|
||||||
2. Hardware H.264 Encoding using Media Foundation (MF).
|
2. Hardware/Software H.264 Encoding using **FFmpeg** (switched from Media Foundation for better compatibility).
|
||||||
3. Network Transmission using UDP.
|
3. Network Transmission using UDP.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Windows 10/11
|
- Windows 10/11
|
||||||
- Visual Studio 2019 or later (with C++ Desktop Development)
|
- Visual Studio 2022 or later (with C++ Desktop Development)
|
||||||
- CMake 3.10+
|
- CMake 3.10+
|
||||||
|
- **FFmpeg Development Libraries** (Shared)
|
||||||
|
- Ensure you have the `include` and `lib` directories.
|
||||||
|
- Example path: `D:\tools\ffmpeg-8.0.1-full_build-shared`
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
1. Open a terminal (Developer Command Prompt for VS).
|
1. Open a terminal (Developer Command Prompt for VS or PowerShell).
|
||||||
2. Navigate to this directory:
|
2. Navigate to this directory:
|
||||||
```cmd
|
```cmd
|
||||||
cd demo\windows_sender
|
cd demo\windows_sender
|
||||||
@@ -24,30 +28,49 @@ It demonstrates:
|
|||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
```
|
```
|
||||||
4. Configure and Build:
|
4. Configure and Build (Replace path with your FFmpeg location):
|
||||||
```cmd
|
```cmd
|
||||||
cmake ..
|
cmake .. -DFFMPEG_ROOT="D:/tools/ffmpeg-8.0.1-full_build-shared"
|
||||||
cmake --build . --config Release
|
cmake --build . --config Release
|
||||||
```
|
```
|
||||||
|
*Note: If your FFmpeg is installed elsewhere, change the path accordingly.*
|
||||||
|
|
||||||
|
5. **Important**: Copy FFmpeg DLLs to the executable directory.
|
||||||
|
- Copy `avcodec-*.dll`, `avutil-*.dll`, `swscale-*.dll`, `avformat-*.dll` from your FFmpeg `bin` directory to `demo\windows_sender\build\Release`.
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
Run the executable with target IP and Port (optional):
|
Run the executable with optional arguments: Target IP, Port, and Output File.
|
||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
.\Release\WindowsSenderDemo.exe <TargetIP> <Port>
|
.\Release\WindowsSenderDemo.exe [TargetIP] [Port] [OutputFile]
|
||||||
```
|
```
|
||||||
|
|
||||||
Example:
|
### Examples
|
||||||
```cmd
|
|
||||||
.\Release\WindowsSenderDemo.exe 192.168.1.100 8888
|
1. **Basic Streaming** (Default: 127.0.0.1:8888):
|
||||||
```
|
```cmd
|
||||||
|
.\Release\WindowsSenderDemo.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Specify Target**:
|
||||||
|
```cmd
|
||||||
|
.\Release\WindowsSenderDemo.exe 192.168.1.100 8888
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Stream and Save to File** (for debugging):
|
||||||
|
```cmd
|
||||||
|
.\Release\WindowsSenderDemo.exe 127.0.0.1 8888 debug.h264
|
||||||
|
```
|
||||||
|
You can play the saved `debug.h264` using VLC player to verify the encoding quality.
|
||||||
|
|
||||||
## Implementation Details
|
## Implementation Details
|
||||||
|
|
||||||
- **ScreenCapture**: Uses `IDXGIOutputDuplication` to capture desktop frames.
|
- **ScreenCapture**: Uses `IDXGIOutputDuplication` to capture desktop frames.
|
||||||
- **VideoEncoder**: Uses `IMFTransform` (Media Foundation) to encode frames to H.264.
|
- **VideoEncoder**:
|
||||||
- *Note*: This demo attempts to feed RGB32 textures to the encoder. If the hardware encoder only supports NV12, conversion logic is needed (not fully implemented in this minimal demo).
|
- Uses **FFmpeg (libx264)** for encoding.
|
||||||
|
- Performs **BGRA to YUV420P** color conversion using `libswscale`.
|
||||||
|
- Configured for low latency (`zerolatency` tune, `ultrafast` preset).
|
||||||
- **NetworkSender**: Fragments the H.264 stream into UDP packets (MTU ~1400 bytes) and sends them to the target.
|
- **NetworkSender**: Fragments the H.264 stream into UDP packets (MTU ~1400 bytes) and sends them to the target.
|
||||||
|
|
||||||
## Protocol
|
## Protocol
|
||||||
|
|||||||
@@ -4,16 +4,33 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
std::string ip = "127.0.0.1";
|
std::string ip = "127.0.0.1";
|
||||||
int port = 8888;
|
int port = 8888;
|
||||||
|
std::string outputFileName = "";
|
||||||
|
|
||||||
if (argc > 1) ip = argv[1];
|
if (argc > 1) ip = argv[1];
|
||||||
if (argc > 2) port = std::stoi(argv[2]);
|
if (argc > 2) port = std::stoi(argv[2]);
|
||||||
|
if (argc > 3) outputFileName = argv[3];
|
||||||
|
|
||||||
std::cout << "Starting Windows Sender Demo..." << std::endl;
|
std::cout << "Starting Windows Sender Demo..." << std::endl;
|
||||||
std::cout << "Target: " << ip << ":" << port << std::endl;
|
std::cout << "Target: " << ip << ":" << port << std::endl;
|
||||||
|
if (!outputFileName.empty()) {
|
||||||
|
std::cout << "Output File: " << outputFileName << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug: Open file to save H.264 stream if filename is provided
|
||||||
|
std::ofstream outFile;
|
||||||
|
if (!outputFileName.empty()) {
|
||||||
|
outFile.open(outputFileName, std::ios::binary);
|
||||||
|
if (outFile.is_open()) {
|
||||||
|
std::cout << "Debug: Saving video stream to '" << outputFileName << "'" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Warning: Failed to open output file '" << outputFileName << "'" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScreenCapture capture;
|
ScreenCapture capture;
|
||||||
if (!capture.Initialize()) {
|
if (!capture.Initialize()) {
|
||||||
@@ -67,6 +84,10 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
sender.SendFrame(encodedData, timestamp, width, height, isKeyFrame);
|
sender.SendFrame(encodedData, timestamp, width, height, isKeyFrame);
|
||||||
// std::cout << "Sent frame: " << encodedData.size() << " bytes, Key: " << isKeyFrame << std::endl;
|
// std::cout << "Sent frame: " << encodedData.size() << " bytes, Key: " << isKeyFrame << std::endl;
|
||||||
|
|
||||||
|
if (outFile.is_open()) {
|
||||||
|
outFile.write(reinterpret_cast<const char*>(encodedData.data()), encodedData.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
capture.ReleaseFrame();
|
capture.ReleaseFrame();
|
||||||
|
|||||||
Reference in New Issue
Block a user