sad*_*tsu 3 windows multithreading c++11 sdl-2
我正在使用C++ 11,MinGW和Windows API进行屏幕捕获程序.我正在尝试使用SDL2来观看我的屏幕捕获程序如何实时工作.
窗口打开很好,程序似乎运行良好,只要我只做移动鼠标光标.但是如果我单击窗口,窗口外的菜单栏或按任意键,SDL窗口会冻结.
我已经为事件设置了一些日志记录来弄清楚发生了什么.我从来没有收到比其他任何事件SDL_WINDOW_FOCUS_GAINED,SDL_TEXTEDITING以及SDL_WINDOWEVENT_SHOWN按照这个顺序.所有这些都是在一开始就收到的.
我试图找到有关SDL事件处理的教程,因为这是我对问题根源的最佳猜测.我发现只需要基本的事件处理SDL_QUIT,基本的鼠标和键盘事件,以及一个SDL_WINDOWEVENT似乎没有帮助的事件.我没有深入了解事件的意义和处理它们的最佳实践.这可能无关紧要,因为这可能不是问题的根源.据我所知,SDL正在投入适合,因为还有其他线程正在运行.
任何人都可以看到我的代码挂起的任何原因,并提供如何解决它的解释?
我的程序结构的快速解释是为了涵盖我省略的代码.在Captor课程开始并运行一个线程来抓取截图传递给Encoder.的Encoder开始从接收的屏幕截图线程的数目可变Captor,编码截图,随后将编码的Screen.传递机制是SynchronousQueue<T>提供配对方法put(const T&)并T get()允许生产者和消费者使用资源进行同步的类; 这些方法超时以允许系统响应杀死消息.
现在为源文件(希望没有太多的膨胀). 虽然我很感激有关如何提高应用程序性能的任何意见,但我的重点是使程序具有响应性.
main.cpp中
#include "RTSC.hpp"
int main(int argc, char** argv) {
RTSC rtsc {
(uint32_t) stoi(argv[1]),
(uint32_t) stoi(argv[2]),
(uint32_t) stoi(argv[3]),
(uint32_t) stoi(argv[4]),
(uint32_t) stoi(argv[5]),
(uint32_t) stoi(argv[6])
};
while (rtsc.isRunning()) {
SwitchToThread();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
RTSC.hpp
#ifndef RTSC_HPP
#define RTSC_HPP
#include "Captor.hpp"
#include "Encoder.hpp"
#include "Screen.hpp"
#include <iostream>
using namespace std;
class RTSC {
private:
Captor *captor;
Encoder *encoder;
SynchronousQueue<uint8_t*> imageQueue {1};
SynchronousQueue<RegionList> regionQueue {1};
Screen *screen;
public:
RTSC(
uint32_t width,
uint32_t height,
uint32_t maxRegionCount,
uint32_t threadCount,
uint32_t divisionsAlongThreadWidth,
uint32_t divisionsAlongThreadHeight
) {
captor = new Captor(width, height, imageQueue);
encoder = new Encoder(
width,
height,
maxRegionCount,
threadCount,
divisionsAlongThreadWidth,
divisionsAlongThreadHeight,
imageQueue,
regionQueue
);
screen = new Screen(
width,
height,
width >> 1,
height >> 1,
regionQueue
);
captor->start();
}
~RTSC() {
delete screen;
delete encoder;
delete captor;
}
bool isRunning() const {
return screen->isRunning();
}
};
#endif
Run Code Online (Sandbox Code Playgroud)
Screen.hpp
#ifndef SCREEN_HPP
#define SCREEN_HPP
#include <atomic>
#include <SDL.h>
#include <windows.h>
#include "Region.hpp"
#include "SynchronousQueue.hpp"
using namespace std;
class Screen {
private:
atomic_bool running {false};
HANDLE thread;
SynchronousQueue<RegionList>* inputQueue;
uint32_t inputHeight;
uint32_t inputWidth;
uint32_t screenHeight;
uint32_t screenWidth;
SDL_Renderer* renderer;
SDL_Surface* surface;
SDL_Texture* texture;
SDL_Window* window;
void run() {
SDL_Event event;
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_CLOSE:
running = false;
break;
default:
break;
}
}
try {
RegionList rl = inputQueue->get();
SDL_RenderClear(renderer);
SDL_LockSurface(surface);
SDL_FillRect(surface, nullptr, 0);
for (uint32_t i = 0; i < rl.count; ++i) {
Region &r = rl.regions[i];
SDL_Rect rect {
(int) r.getX(),
(int) r.getY(),
(int) r.getWidth(),
(int) r.getHeight()
};
uint32_t color =
(r.getRed() << 16) +
(r.getGreen() << 8) +
r.getBlue();
SDL_FillRect(surface, &rect, color);
}
SDL_UnlockSurface(surface);
SDL_UpdateTexture(
texture,
nullptr,
surface->pixels,
surface->pitch
);
SDL_RenderCopyEx(
renderer,
texture,
nullptr,
nullptr,
0,
nullptr,
SDL_FLIP_VERTICAL
);
} catch (exception &e) {}
SDL_RenderPresent(renderer);
SwitchToThread();
}
}
static DWORD startThread(LPVOID self) {
((Screen*) self)->run();
return (DWORD) 0;
}
public:
Screen(
uint32_t inputWidth,
uint32_t inputHeight,
uint32_t windowWidth,
uint32_t windowHeight,
SynchronousQueue<RegionList> &inputQueue
): inputQueue {&inputQueue}, inputHeight {inputHeight} {
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(
"RTSC",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
windowWidth,
windowHeight,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS
);
renderer = SDL_CreateRenderer(window, -1, 0);
surface = SDL_CreateRGBSurface(
0,
inputWidth,
inputHeight,
24,
0xFF << 16,
0xFF << 8,
0xFF,
0
);
texture = SDL_CreateTexture(
renderer,
surface->format->format,
SDL_TEXTUREACCESS_STREAMING,
inputWidth,
inputHeight
);
running = true;
thread = CreateThread(nullptr, 0, startThread, this, 0, nullptr);
}
~Screen() {
running = false;
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
SDL_FreeSurface(surface);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
bool isRunning() const {
return running;
}
};
#endif
Run Code Online (Sandbox Code Playgroud)
我没有在多线程环境中使用SDL API的经验,但这不是一个大问题,您将在后面看到.我检查了你的代码,至少有一件事我应该改变一下.
在主线程上完成大部分任务还有另一个好处:它使您的代码更容易移植到任何平台.可选地,如果您编写代码以便它可以在单线程模式下执行,那么它可以在许多情况下使调试更容易,然后您还有一个"参考构建"来将多线程构建与性能进行比较.
| 归档时间: |
|
| 查看次数: |
2202 次 |
| 最近记录: |