gpt4 book ai didi

c++ - 使用 ffmpeg 从 C++ 内存中的多个图像流式传输 RTSP

转载 作者:行者123 更新时间:2023-12-04 23:01:22 28 4
gpt4 key购买 nike

我正在编写一个在屏幕上显示文本的应用程序。我希望能够通过 RTSP 流式传输屏幕(带有文本),以便像 OBS/vMix 或 VLC 这样的程序可以捕获它。我要做的是每 N 毫秒(比如每 100 毫秒)截取一次屏幕截图,将其保存到内存中(而不是磁盘),然后将其写入到 ffmpeg 的管道中。 .然后ffmpeg获取这些图像并从中生成 RTSP 流。我已经实现了每 N 毫秒截取一次屏幕截图并将其写入管道的部分(类似于 this 问题,不同之处在于我将图像保存在内存中,而不是磁盘上)。现在的问题是我对 ffmpeg 了解不多(我已经按照 this 问题的答案设置了参数,但是当我尝试通过 VLC 或其他程序播放流时,屏幕上什么也看不到)。我可以看到很多Successfully sent a screenshot在日志中,但在实际流中没有。你能告诉我我做错了什么吗?
您可以找到整个项目here
这是(部分)我的代码:

bool RTSP_SERVER_SHOULD_START = false;
tthread::mutex rtsp_server_mutex;
tthread::mutex screenshot_mutex;
tthread::thread* rtsp;
FILE *pPipe;
bool send_screenshot = false;

int main(int argc, char *argv[]) {
// OpenGL stuff...
rtsp_server_mutex.lock();
if (RTSP_SERVER_SHOULD_START) {
RTSP_SERVER_SHOULD_START = false;
rtsp = new tthread::thread(rtspScreenShotToPipe, 0);
if( (pPipe = _popen( "ffmpeg -re -f image2pipe -vcodec mjpeg -i - -vcodec h264 -r 10 -f mpegts udp://127.0.0.1:1234", "wb")) == NULL ) {
cerr << "Error: Could not open ffmpeg" << endl;
_pclose(pPipe);
exit(1);
}
}
rtsp_server_mutex.unlock();

while (!glfwWindowShouldClose(WINDOW)) {
// More OpenGL stuff
screenshot_mutex.lock();
if(send_screenshot) {
send_screenshot = false;
// Make the BYTE array, factor of 3 because it's RBG.
BYTE* pixels = new BYTE[3 * DEFAULT_MONITOR.maxResolution.width * DEFAULT_MONITOR.maxResolution.height];

glReadPixels(0, 0, DEFAULT_MONITOR.maxResolution.width, DEFAULT_MONITOR.maxResolution.height, GL_RGB, GL_UNSIGNED_BYTE, pixels);

// Convert to FreeImage format & save to file
FIBITMAP* image = FreeImage_ConvertFromRawBits(pixels, DEFAULT_MONITOR.maxResolution.width, DEFAULT_MONITOR.maxResolution.height, 3 * DEFAULT_MONITOR.maxResolution.width, 24, 0x0000FF, 0xFF0000, 0x00FF00, false);

FreeImageIO io;
SetDefaultIO(&io);

bool success = FreeImage_SaveToHandle(FIF_JPEG, image, &io, (fi_handle)pPipe);
fflush(pPipe);
if(success) {
cout << "Successfully sent a screenshot" << endl;
}

// Free resources
FreeImage_Unload(image);
delete [] pixels;
}
screenshot_mutex.unlock();
}
printf("%d", glGetError());

glfwTerminate();
return 0;
}

void rtspScreenShotToPipe(void * aArg) {
while(true) {
rtsp_server_mutex.try_lock();
if(!RTSP_SERVER_STARTED) {
break;
}
rtsp_server_mutex.unlock();
tthread::this_thread::sleep_for(tthread::chrono::milliseconds(100));
screenshot_mutex.try_lock();
send_screenshot = true;
screenshot_mutex.unlock();
}
}

// I've copied those function from FreeImage in my code

void SetDefaultIO(FreeImageIO *io) {
io->read_proc = _ReadProc;
io->seek_proc = _SeekProc;
io->tell_proc = _TellProc;
io->write_proc = _WriteProc;
}

unsigned DLL_CALLCONV _ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
return (unsigned)fread(buffer, size, count, (FILE *)handle);
}

unsigned DLL_CALLCONV _WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
return (unsigned)fwrite(buffer, size, count, (FILE *)handle);
}

int DLL_CALLCONV _SeekProc(fi_handle handle, long offset, int origin) {
return fseek((FILE *)handle, offset, origin);
}

long DLL_CALLCONV _TellProc(fi_handle handle) {
return ftell((FILE *)handle);
}

最佳答案

您没有使用 RTSP,而是通过 UDP 发送 MPEG-TS。
在 VLC 中确保您监听正确的网络流:udp://@127.0.0.1:1234在 FFmpeg 方面,您需要指定有效负载大小:-f mpegts udp://127.0.0.1:1234?pkt_size=1316FFmpeg 有一个可以直接从 C++ 使用的 API,因此您不必通过管道连接到进程。

关于c++ - 使用 ffmpeg 从 C++ 内存中的多个图像流式传输 RTSP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69966744/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com