DisplayFrame displays now only a single frame.

This commit is contained in:
Johns 2011-12-12 17:04:41 +01:00
parent 8853c06375
commit fa970400f1

118
video.c
View File

@ -184,7 +184,9 @@ static VideoScalingModes VideoScaling;
static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message
extern uint32_t VideoSwitch; extern uint32_t VideoSwitch; ///< ticks for channel switch
static int VideoDropNextFrame; ///< flag drop next frame
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Functions // Functions
@ -827,12 +829,18 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
Error(_("video/vaapi: can't associate subpicture\n")); Error(_("video/vaapi: can't associate subpicture\n"));
} }
} else { } else {
int i;
if (vaAssociateSubpicture(VaDisplay, VaOsdSubpicture, if (vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
decoder->SurfacesFree, decoder->SurfaceFreeN, 0, 0, decoder->SurfacesFree, decoder->SurfaceFreeN, 0, 0,
VaOsdImage.width, VaOsdImage.height, 0, 0, width, height, 0) VaOsdImage.width, VaOsdImage.height, 0, 0, width, height, 0)
!= VA_STATUS_SUCCESS) { != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't associate subpicture\n")); Error(_("video/vaapi: can't associate subpicture\n"));
} }
for (i = 0; i < decoder->SurfaceFreeN; ++i) {
Debug(3, "video/vaapi: associate %08x\n",
decoder->SurfacesFree[i]);
}
} }
} }
@ -2019,9 +2027,6 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
Error(_("video/vaapi: can't create a surface\n")); Error(_("video/vaapi: can't create a surface\n"));
return; return;
} }
}
// FIXME: no need to re associate
// full sized surface, no difference unscaled/scaled osd // full sized surface, no difference unscaled/scaled osd
if (vaAssociateSubpicture(decoder->VaDisplay, VaOsdSubpicture, if (vaAssociateSubpicture(decoder->VaDisplay, VaOsdSubpicture,
&decoder->BlackSurface, 1, 0, 0, VaOsdImage.width, &decoder->BlackSurface, 1, 0, 0, VaOsdImage.width,
@ -2029,6 +2034,9 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
0) != VA_STATUS_SUCCESS) { 0) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't associate subpicture\n")); Error(_("video/vaapi: can't associate subpicture\n"));
} }
Debug(3, "video/vaapi: associate %08x\n", decoder->BlackSurface);
// FIXME: check if intel forgets this also
}
start = GetMsTicks(); start = GetMsTicks();
if (vaSyncSurface(decoder->VaDisplay, if (vaSyncSurface(decoder->VaDisplay,
@ -2330,6 +2338,7 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
decoder->Interlaced = interlaced; decoder->Interlaced = interlaced;
decoder->TopFieldFirst = frame->top_field_first; decoder->TopFieldFirst = frame->top_field_first;
decoder->SurfaceField = 1;
} }
VaapiQueueSurface(decoder, surface, 0); VaapiQueueSurface(decoder, surface, 0);
@ -2373,6 +2382,7 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
decoder->Interlaced = frame->interlaced_frame; decoder->Interlaced = frame->interlaced_frame;
decoder->TopFieldFirst = frame->top_field_first; decoder->TopFieldFirst = frame->top_field_first;
decoder->SurfaceField = 1;
// FIXME: I hope this didn't change in the middle of the stream // FIXME: I hope this didn't change in the middle of the stream
} }
// FIXME: Need to insert software deinterlace here // FIXME: Need to insert software deinterlace here
@ -2436,13 +2446,32 @@ static void VaapiDisplayFrame(void)
decoder = VaapiDecoders[i]; decoder = VaapiDecoders[i];
filled = atomic_read(&decoder->SurfacesFilled); filled = atomic_read(&decoder->SurfacesFilled);
if (filled) { // no surface availble show black with possible osd
if (!filled) {
VaapiBlackSurface(decoder);
continue;
}
// show any frame as fast as possible // show any frame as fast as possible
// we keep always the last frame in the ring buffer // we keep always the last frame in the ring buffer
// 0 -> 1
// 1 -> 0 + advance
if (decoder->Interlaced) {
// FIXME: first frame is never shown
if (decoder->SurfaceField) {
if (filled > 1) { if (filled > 1) {
decoder->SurfaceRead = (decoder->SurfaceRead + 1) decoder->SurfaceRead = (decoder->SurfaceRead + 1)
% VIDEO_SURFACES_MAX; % VIDEO_SURFACES_MAX;
atomic_dec(&decoder->SurfacesFilled); atomic_dec(&decoder->SurfacesFilled);
decoder->SurfaceField = 0;
}
} else {
decoder->SurfaceField = 1;
}
} else if (filled > 1) {
decoder->SurfaceRead = (decoder->SurfaceRead + 1)
% VIDEO_SURFACES_MAX;
atomic_dec(&decoder->SurfacesFilled);
} }
surface = decoder->SurfacesRb[decoder->SurfaceRead]; surface = decoder->SurfacesRb[decoder->SurfaceRead];
@ -2452,48 +2481,39 @@ static void VaapiDisplayFrame(void)
Debug(4, "video/vaapi: yy video surface %#x displayed\n", surface); Debug(4, "video/vaapi: yy video surface %#x displayed\n", surface);
start = GetMsTicks(); start = GetMsTicks();
// wait for rendering finished
if (vaSyncSurface(decoder->VaDisplay, surface) if (vaSyncSurface(decoder->VaDisplay, surface)
!= VA_STATUS_SUCCESS) { != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: vaSyncSurface failed\n")); Error(_("video/vaapi: vaSyncSurface failed\n"));
} }
sync = GetMsTicks(); sync = GetMsTicks();
// deinterlace and full frame rate
if (decoder->Interlaced
// FIXME: buggy libva-driver-vdpau.
&& VaapiBuggyVdpau && VideoDeinterlace != VideoDeinterlaceWeave) {
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced, VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, 0); decoder->TopFieldFirst, 0);
put1 = GetMsTicks(); put1 = GetMsTicks();
put2 = put1;
// deinterlace and full frame rate
if (decoder->Interlaced) {
usleep(500);
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, 1);
if (0 && vaSyncSurface(decoder->VaDisplay, surface)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: vaSyncSurface failed\n"));
}
// FIXME: buggy libva-driver-vdpau.
if (VaapiBuggyVdpau
&& VideoDeinterlace != VideoDeinterlaceWeave) {
usleep(500);
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, 0);
usleep(500); usleep(500);
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced, VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, 1); decoder->TopFieldFirst, 1);
}
put2 = GetMsTicks(); put2 = GetMsTicks();
} else {
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, decoder->SurfaceField);
put1 = GetMsTicks();
put2 = put1;
} }
clock_gettime(CLOCK_REALTIME, &decoder->FrameTime); clock_gettime(CLOCK_REALTIME, &decoder->FrameTime);
// fixes: [drm:i915_hangcheck_elapsed] *ERROR* Hangcheck // fixes: [drm:i915_hangcheck_elapsed] *ERROR* Hangcheck
// timer elapsed... GPU hung // timer elapsed... GPU hung
//usleep(1 * 1000); usleep(1 * 1000);
Debug(4, "video/vaapi: sync %2u put1 %2u put2 %2u\n", sync - start, Debug(4, "video/vaapi: sync %2u put1 %2u put2 %2u\n", sync - start,
put1 - sync, put2 - put1); put1 - sync, put2 - put1);
} else {
Debug(3, "video/vaapi: no video surface ready\n");
}
} }
} }
@ -2944,6 +2964,13 @@ static void VideoEvent(void)
break; break;
case KeyPress: case KeyPress:
keysym = XLookupKeysym(&event.xkey, 0); keysym = XLookupKeysym(&event.xkey, 0);
switch (keysym) {
case XK_d:
break;
case XK_S:
VideoDropNextFrame = 1;
break;
}
if (keysym == NoSymbol) { if (keysym == NoSymbol) {
Warning(_("video: No symbol for %d\n"), event.xkey.keycode); Warning(_("video: No symbol for %d\n"), event.xkey.keycode);
} }
@ -3059,7 +3086,7 @@ static void *VideoDisplayHandlerThread(void *dummy)
&& (uint64_t) decoder->PTS != AV_NOPTS_VALUE) { && (uint64_t) decoder->PTS != AV_NOPTS_VALUE) {
video_clock = decoder->PTS - (decoder->Interlaced ? 40 : 20) * 90; video_clock = decoder->PTS - (decoder->Interlaced ? 40 : 20) * 90;
} }
// default video delay, if audio delay isn't known yet
delay = 1 * 500L * 1000 * 1000; delay = 1 * 500L * 1000 * 1000;
clock_gettime(CLOCK_REALTIME, &nowtime); clock_gettime(CLOCK_REALTIME, &nowtime);
@ -3116,11 +3143,10 @@ static void *VideoDisplayHandlerThread(void *dummy)
filled = atomic_read(&decoder->SurfacesFilled); filled = atomic_read(&decoder->SurfacesFilled);
clock_gettime(CLOCK_REALTIME, &nowtime); clock_gettime(CLOCK_REALTIME, &nowtime);
// time for one frame over, buggy for vaapi-vdpau // time for one frame over
if (filled <= 1 && (nowtime.tv_sec - decoder->FrameTime.tv_sec) if (filled <= 1 && (nowtime.tv_sec - decoder->FrameTime.tv_sec)
* 1000 * 1000 * 1000 + (nowtime.tv_nsec - * 1000 * 1000 * 1000 + (nowtime.tv_nsec -
decoder->FrameTime.tv_nsec) < decoder->FrameTime.tv_nsec) < 15 * 1000 * 1000) {
(decoder->Interlaced ? 15 : 15) * 1000 * 1000) {
continue; continue;
} }
@ -3131,9 +3157,10 @@ static void *VideoDisplayHandlerThread(void *dummy)
} else if (filled == 1 || (Fix60Hz && !(decoder->FrameCounter % 6))) { } else if (filled == 1 || (Fix60Hz && !(decoder->FrameCounter % 6))) {
decoder->FramesDuped++; decoder->FramesDuped++;
++decoder->FrameCounter; ++decoder->FrameCounter;
Warning(_("video: display buffer empty, duping frame (%d/%d)\n"),
decoder->FramesDuped, decoder->FrameCounter);
if (!(decoder->FrameCounter % 333)) { if (!(decoder->FrameCounter % 333)) {
Warning(_
("video: display buffer empty, duping frame (%d/%d)\n"),
decoder->FramesDuped, decoder->FrameCounter);
VaapiPrintFrames(decoder); VaapiPrintFrames(decoder);
} }
} }
@ -3183,6 +3210,7 @@ static void VideoThreadExit(void)
{ {
void *retval; void *retval;
Debug(3, "video: video thread canceled\n");
if (VideoThread) { if (VideoThread) {
if (pthread_cancel(VideoThread)) { if (pthread_cancel(VideoThread)) {
Error(_("video: can't queue cancel video display thread\n")); Error(_("video: can't queue cancel video display thread\n"));
@ -3378,6 +3406,7 @@ void VaapiTest(void)
void VideoRenderFrame(VideoHwDecoder * decoder, AVCodecContext * video_ctx, void VideoRenderFrame(VideoHwDecoder * decoder, AVCodecContext * video_ctx,
AVFrame * frame) AVFrame * frame)
{ {
// update video clock
decoder->Vaapi.PTS += (decoder->Vaapi.Interlaced ? 40 : 20) * 90; decoder->Vaapi.PTS += (decoder->Vaapi.Interlaced ? 40 : 20) * 90;
// libav: sets only pkt_dts // libav: sets only pkt_dts
@ -3388,11 +3417,18 @@ void VideoRenderFrame(VideoHwDecoder * decoder, AVCodecContext * video_ctx,
decoder->Vaapi.PTS = frame->pkt_dts; decoder->Vaapi.PTS = frame->pkt_dts;
} }
} }
if (!atomic_read(&decoder->Vaapi.SurfacesFilled)) { if (!atomic_read(&decoder->Vaapi.SurfacesFilled)) {
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch); Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
} }
if (VideoDropNextFrame) { // drop frame requested
VideoDropNextFrame--;
return;
}
// if video output buffer is full, wait and display surface. // if video output buffer is full, wait and display surface.
if (atomic_read(&decoder->Vaapi.SurfacesFilled) >= VIDEO_SURFACES_MAX) { // loop for interlace
while (atomic_read(&decoder->Vaapi.SurfacesFilled) >= VIDEO_SURFACES_MAX) {
struct timespec abstime; struct timespec abstime;
abstime = decoder->Vaapi.FrameTime; abstime = decoder->Vaapi.FrameTime;
@ -3580,6 +3616,22 @@ int VideoSetGeometry(const char *geometry)
return 0; return 0;
} }
/**
** Set deinterlace mode.
*/
void VideoSetDeinterlace(int mode)
{
VideoDeinterlace = mode;
}
/**
** Set scaling mode.
*/
void VideoSetScaling(int mode)
{
VideoScaling = mode;
}
/** /**
** Initialize video output module. ** Initialize video output module.
** **