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);
コードは非常に大きいため、コード全体を掲載するつもりはありませんが、ビデオ オーバーレイを表示する方法を以下に示します。formatCtx
一部の変数は、やなど、私の Video クラスのクラスメンバーであることに注意してください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
.
私は何を間違っていますか?