Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SDL视频叠加随着SDL_翻转而闪烁 < >我在C++中使用SDL和LIBAV在Linux上画一个视频。我的大部分视频打开代码都基于,但我更改了一些不推荐使用的函数。我像这样初始化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);_C++_Video_Sdl_Libav - Fatal编程技术网

SDL视频叠加随着SDL_翻转而闪烁 < >我在C++中使用SDL和LIBAV在Linux上画一个视频。我的大部分视频打开代码都基于,但我更改了一些不推荐使用的函数。我像这样初始化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);

SDL视频叠加随着SDL_翻转而闪烁 < >我在C++中使用SDL和LIBAV在Linux上画一个视频。我的大部分视频打开代码都基于,但我更改了一些不推荐使用的函数。我像这样初始化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);,c++,video,sdl,libav,C++,Video,Sdl,Libav,我不打算发布整个代码,因为它相当大,但下面展示了我如何尝试显示视频覆盖。请注意,有些变量是我的视频类的类成员,如formatCtx和packet void Video::GetOverlay(SDL_Overlay * overlay) { int frameFinished; while (av_read_frame(formatCtx, &packet) >= 0) { if (packet.stream_index == videoStream

我不打算发布整个代码,因为它相当大,但下面展示了我如何尝试显示视频覆盖。请注意,有些变量是我的视频类的类成员,如
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);
    }   
}
然后在我的主循环中:

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\u Flip(屏幕)
的调用时,视频播放正常。太快了,我还没有完成视频计时,但是当我添加一个临时的
SDL\u延迟(10)
时,它看起来相当不错。 但是当我移除SDL_Flip来显示我的视频时,我无法在屏幕上绘制任何其他内容。
SDL_BlitSurface
SDL_FillRect
都无法在屏幕上绘制任何内容。我已经尝试将
SDL_DOUBLEBUF
添加到标志中,但这并没有改变情况

如果需要的话,我可以提供更多的代码,但我认为问题出在我发布的代码中的某个地方,因为其他一切都正常工作(绘制图像,或者显示没有
SDL\u Flip
)的视频)


我做错了什么

应该使用双缓冲来防止闪烁

screen = SDL_SetVideoMode(info->current_w, info->current_h, 0, SDL_SWSURFACE | SDL_FULLSCREEN | SDL_DOUBLEBUF);

因为您使用的是SWSURFACE,所以不要使用SDL_Flip(屏幕)使用SDL_Update。您不需要设置SDL_DOUBLEBUF

我就是这么做的,我不会被忽悠

我把屏幕设置成这样

screen = SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE | SDL_FULLSCREEN);
在我的主循环中,我调用

SDL_UpdateRect(screen, 0, 0, 0, 0);

我仍然认为这不是最好的解决方案,但我发现了一些有效的方法!
命令
SDL_update(屏幕,0,0,0,0)将更新整个屏幕。如果我只更新屏幕上没有绘制视频的部分,视频将不再闪烁。我认为这可能与SDL_覆盖层的处理方式不同于普通表面有关。

显然,有许多平台或情况(如ATI/nVidia驱动程序设置)会导致SDL_Flip关闭或不使用vsync;建议您搜索一下“sdl_flip vsync”。你可能会碰到这些东西中的任何一个。我以前应该提到过这个,但我已经试过了,但没有效果,视频仍然闪烁。我试过了,但没有效果。视频仍在闪烁。您是否也在
SDL\u覆盖图上绘制视频?不,我直接写入像素。像这样:memcpy((int*)屏幕->像素,图像,大小*4);我仍然使用单个线程,但我计划稍后使用多个线程。您是否将视频帧加载到图像中?或者你只是加载一个图像?不确定你到底是什么意思。我读了一个targa文件,因为它的格式很容易使用,我直接写屏幕->像素。你可以尝试SDL_BlitSurface而不是memcpy,但是memcpy对我来说足够快。如果我理解正确,targa是一种图像格式。但我正在加载mp4视频,并试图在SDL_覆盖上显示视频帧。所以我认为仅仅画一幅图像,或者在覆盖图上画视频帧是有区别的,但我不确定。