我正在实现游戏的客户端程序,其中服务器将游戏的编码帧发送到客户端(通过 UDP),而客户端将它们解码(通过 FFMPEG)并将它们显示在GLFW窗口中。我的程序有两个线程:
- 线程 1:渲染 uint8_t* 变量的内容
dataToRender
- 线程2:不断从服务器获取帧,解码并
dataToRender
相应更新
线程 1 在 while 循环中执行 GLFW 窗口的典型渲染。我已经尝试显示一些虚拟帧数据(一个完全红色的帧)并且它有效:
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
...
glBindTexture(GL_TEXTURE_2D, tex_handle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window_width, window_height, 0, GL_RGB, GL_UNSIGNED_BYTE, dataToRender);
...
glfwSwapBuffers(window);
}
线程 2 是我遇到麻烦的地方。我无法将解码的帧正确存储到我的dataToRender
变量中。最重要的是,帧数据原本是 YUV 格式,需要转成 RGB。我为此使用 FFMPEG sws_scale
,这也给了我bad dst image pointers
控制台中的错误输出。这是负责该部分的代码片段:
size_t data_size = frameBuffer.size(); // frameBuffer is a std::vector where I accumulate the frame data chunks
uint8_t* data = frameBuffer.data(); // convert the vector to a pointer
picture->format = AV_PIX_FMT_RGB24;
av_frame_get_buffer(picture, 1);
while (data_size > 0) {
int ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size,
data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
fprintf(stderr, "Error while parsing\n");
exit(1);
}
data += ret;
data_size -= ret;
if (pkt->size) {
swsContext = sws_getContext(
c->width, c->height,
AV_PIX_FMT_YUV420P, c->width, c->height,
AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL
);
uint8_t* rgb24[1] = { data };
int rgb24_stride[1] = { 3 * c->width };
sws_scale(swsContext, rgb24, rgb24_stride, 0, c->height, picture->data, picture->linesize);
decode(c, picture, pkt, outname);
// TODO: copy content of picture->data[0] to "dataToRender" maybe?
}
}
我已经尝试过另一个 sws_scale 将内容复制到dataToRender
,但我无法摆脱bad dst image pointers
错误。任何关于该问题的建议或解决方案都将不胜感激,因为我已经为此困扰了好几天。