Я использую SDL и libav в C++ для рисования видео на экране в Linux. Большая часть моего кода для открытия видео основана на this tutorial, но я изменил некоторые функции, которые были устаревшими. Я инициализация SDL как это:SDL видео наложения мерцает с SDL_Flip
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);
}
}
А потом в моем основном цикле:
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
).
Что я делаю неправильно?
По-видимому, существует несколько платформ или ситуаций (таких как настройки драйвера ATI/nVidia), которые могут привести к отключению или отсутствию vsync в SDL_Flip; предлагаю вам немного поискать «sdl_flip vsync». Вы могли бы поразить любую из этих вещей. – leander