2013-05-05 1 views
0

C++에서 SDL 및 libav를 사용하여 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); 

나는 꽤 큰이기 때문에 전체 코드를 게시하지 않을거야,하지만 다음 쇼는 어떻게 비디오 오버레이를 표시하려고합니다. 일부 변수는 formatCtxpacket과 같은 내 Video 클래스의 클래스 멤버입니다.

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_BlitSurfaceSDL_FillRect 모두 화면에 아무 것도 그리지 못합니다. 이미 플래그에 SDL_DOUBLEBUF을 추가하려고 시도했지만 상황을 변경하지 않았습니다.

필요한 경우 더 많은 코드를 제공 할 수 있지만 다른 모든 문제 (그림 그리기 또는 SDL_Flip없이 비디오 표시) 때문에 게시 된 코드 어딘가에 문제가 있다고 생각합니다.

내가 뭘 잘못하고 있니?

+0

분명히 vsync가 SDL_Flip에 의해 꺼지거나 사용되지 않을 수있는 여러 가지 플랫폼이나 상황 (예 : ATI/nVidia 드라이버 설정)이 있습니다. "sdl_flip vsync"에 대한 검색을 제안하십시오. 당신은 이런 것들 중 하나를 치는 것일 수 있습니다. – leander

답변

0

난 아직도이없는 최선의 해결책이라고 생각하지만 작동 뭔가를 발견! SDL_UpdateRect(screen, 0, 0, 0, 0); 명령은 전체 화면을 업데이트합니다. 비디오가 그려지지 않은 화면 부분 만 업데이트하면 비디오가 더 이상 깜박 거리지 않습니다. SDL_Overlays가 일반 표면과 다르게 처리되는 것과 관련이있을 수 있습니다.

0

깜박임을 방지하려면 이중 버퍼링을 사용해야합니다.

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

전에 언급 했어야했지만 이미 시도했지만 아무런 효과가 없었습니다. 비디오는 여전히 깜박입니다. – Carlito

1

SWSURFACE를 사용하고 있으므로 SDL_Flip (화면)을 사용하지 않으므로 SDL_UpdateRect를 사용하십시오. 당신은 내가하는 일이고 내가 깜박임을하지 않는 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); 
+0

나는 이것을 시도했지만 작동하지 않았다. 비디오가 여전히 깜박입니다. 'SDL_Overlay'에 동영상을 그리나요? – Carlito

+0

아니요, 직접 픽셀에 씁니다.이처럼 : memcpy ((int *) screen-> pixels, image, size * 4); –

+0

질문 : 여러 스레드를 사용하고 있습니까? –

관련 문제