SDL视频覆盖闪烁与SDL_Flip
SDL video overlay flickers with SDL_Flip
我在Linux下使用c++中的SDL和libav在屏幕上绘制视频。我的大部分视频打开代码都是基于本教程,但我改变了一些不推荐的函数。我这样初始化SDL:
SDL_Init(SDL_INIT_EVERYTHING);
const SDL_VideoInfo * info = SDL_GetVideoInfo();
screen = SDL_SetVideoMode(info->current_w, info->current_h, 0, SDL_SWSURFACE | SDL_FULLSCREEN);
我不打算张贴整个代码,因为它是相当大的,但以下显示了我如何尝试显示视频覆盖。请注意,一些变量是来自我的Video类的类成员,如formatCtx
和packet
。
void Video::GetOverlay(SDL_Overlay * overlay) {
int frameFinished;
while (av_read_frame(formatCtx, &packet) >= 0) {
if (packet.stream_index == videoStream) {
avcodec_decode_video2(codecCtx, frame, &frameFinished, &packet);
if (frameFinished) {
SDL_LockYUVOverlay(overlay);
AVPicture pict;
pict.data[0] = overlay->pixels[0];
pict.data[1] = overlay->pixels[2];
pict.data[2] = overlay->pixels[1];
pict.linesize[0] = overlay->pitches[0];
pict.linesize[1] = overlay->pitches[2];
pict.linesize[2] = overlay->pitches[1];
SwsContext * ctx = sws_getContext (codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
codecCtx->width, codecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
sws_scale(ctx, frame->data, frame->linesize, 0, codecCtx->height, pict.data, pict.linesize);
sws_freeContext(ctx);
SDL_UnlockYUVOverlay(overlay);
++frameIndex;
return;
}
}
av_free_packet(&packet);
}
}
然后在mainloop中:
SDL_Overlay * overlay = SDL_CreateYUVOverlay(video->GetWidth(), video->GetHeight(), SDL_YV12_OVERLAY, screen);
while (true) {
video->GetOverlay(overlay);
SDL_Rect rect = { 400, 200, video->GetWidth(), video->GetHeight() };
SDL_DisplayYUVOverlay(overlay, &rect);
SDL_Flip(screen);
}
这工作,视频播放,但它闪烁很多。比如它试图在每一帧的同一个地方画一个图像。当我移除呼叫SDL_Flip(screen)
时,视频播放良好。太快了,我还没有解决视频计时问题,但是当我添加一个临时的SDL_Delay(10)
时,它看起来很好。但是当我删除SDL_Flip
来显示我的视频时,我不能在屏幕上画任何其他东西。SDL_BlitSurface
和SDL_FillRect
都无法在屏幕上绘制任何内容。我已经尝试将SDL_DOUBLEBUF
添加到标志中,但这并没有改变这种情况。
如果需要的话,我可以提供更多的代码,但我认为问题是在我发布的代码中的某个地方,因为其他一切都工作正常(绘制图像,或显示没有SDL_Flip
的视频)。
我做错了什么?
由于您使用SWSURFACE不使用SDL_Flip(屏幕)使用sdl_updat竖立。你不需要设置SDL_DOUBLEBUF
http://sdl.beuc.net/sdl.wiki/SDL_UpdateRect这就是我所做的,我没有闪烁。
我把屏幕设置成这样
screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE | SDL_FULLSCREEN);
在主循环中我调用
SDL_UpdateRect(screen, 0, 0, 0, 0);
应该使用双缓冲来防止闪烁。
screen = SDL_SetVideoMode(info->current_w, info->current_h, 0, SDL_SWSURFACE | SDL_FULLSCREEN | SDL_DOUBLEBUF);
我仍然认为这不是最好的解决方案,但我发现了一些工作!命令SDL_UpdateRect(screen, 0, 0, 0, 0);
将更新整个屏幕。如果我只更新屏幕上没有视频的部分,视频就不会再闪烁了。我认为这可能与SDL_Overlays的处理方式不同于普通表面有关。
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- SDL 窗口不会弹出
- SDL 操纵杆按钮按下/C++
- VSCode IntelliSense无法识别SDL框架的SDL_image扩展库
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- SDL 映像:无法打开映像,仅显示错误消息
- 如何在 3D OpenGL 场景上绘制 SDL 2D 矩形?
- "Undefined symbols for architecture x86_64" 在 SDL 2 (macOS) 中
- 为什么 SDL 在 Mac 上比 Linux 慢得多?
- 在 OSX 上打开 SDL 窗口时不要打开终端窗口
- SDL + OpenGL ES 2.0 使用着色器显示纹理
- SDL GPU 为什么将两个图像分成两个单独的循环更快?
- 在 cmake 中找不到 SDL 库
- SDL/C++: 如何平滑但随机地移动矩形?
- 如何与 SDL 库链接?
- 为什么我的C++代码不呈现 SDL 矩形?
- 为什么要在初始化SDL之前在SDL中声明指针
- C++/SDL 如何覆盖数组?
- 在 SDL 中水平减小静态图像进度条