mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
DisplayFrame displays now only a single frame.
This commit is contained in:
parent
8853c06375
commit
fa970400f1
184
video.c
184
video.c
@ -184,7 +184,9 @@ static VideoScalingModes VideoScaling;
|
||||
|
||||
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
|
||||
@ -827,12 +829,18 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
|
||||
Error(_("video/vaapi: can't associate subpicture\n"));
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
|
||||
if (vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
|
||||
decoder->SurfacesFree, decoder->SurfaceFreeN, 0, 0,
|
||||
VaOsdImage.width, VaOsdImage.height, 0, 0, width, height, 0)
|
||||
!= VA_STATUS_SUCCESS) {
|
||||
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,15 +2027,15 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
|
||||
Error(_("video/vaapi: can't create a surface\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// FIXME: no need to re associate
|
||||
|
||||
// full sized surface, no difference unscaled/scaled osd
|
||||
if (vaAssociateSubpicture(decoder->VaDisplay, VaOsdSubpicture,
|
||||
&decoder->BlackSurface, 1, 0, 0, VaOsdImage.width,
|
||||
VaOsdImage.height, 0, 0, VideoWindowWidth, VideoWindowHeight,
|
||||
0) != VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: can't associate subpicture\n"));
|
||||
// full sized surface, no difference unscaled/scaled osd
|
||||
if (vaAssociateSubpicture(decoder->VaDisplay, VaOsdSubpicture,
|
||||
&decoder->BlackSurface, 1, 0, 0, VaOsdImage.width,
|
||||
VaOsdImage.height, 0, 0, VideoWindowWidth, VideoWindowHeight,
|
||||
0) != VA_STATUS_SUCCESS) {
|
||||
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();
|
||||
@ -2330,6 +2338,7 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
|
||||
|
||||
decoder->Interlaced = interlaced;
|
||||
decoder->TopFieldFirst = frame->top_field_first;
|
||||
decoder->SurfaceField = 1;
|
||||
|
||||
}
|
||||
VaapiQueueSurface(decoder, surface, 0);
|
||||
@ -2373,6 +2382,7 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
|
||||
|
||||
decoder->Interlaced = frame->interlaced_frame;
|
||||
decoder->TopFieldFirst = frame->top_field_first;
|
||||
decoder->SurfaceField = 1;
|
||||
// FIXME: I hope this didn't change in the middle of the stream
|
||||
}
|
||||
// FIXME: Need to insert software deinterlace here
|
||||
@ -2436,64 +2446,74 @@ static void VaapiDisplayFrame(void)
|
||||
|
||||
decoder = VaapiDecoders[i];
|
||||
filled = atomic_read(&decoder->SurfacesFilled);
|
||||
if (filled) {
|
||||
// show any frame as fast as possible
|
||||
// we keep always the last frame in the ring buffer
|
||||
if (filled > 1) {
|
||||
decoder->SurfaceRead = (decoder->SurfaceRead + 1)
|
||||
% VIDEO_SURFACES_MAX;
|
||||
atomic_dec(&decoder->SurfacesFilled);
|
||||
}
|
||||
// no surface availble show black with possible osd
|
||||
if (!filled) {
|
||||
VaapiBlackSurface(decoder);
|
||||
continue;
|
||||
}
|
||||
// show any frame as fast as possible
|
||||
// we keep always the last frame in the ring buffer
|
||||
|
||||
surface = decoder->SurfacesRb[decoder->SurfaceRead];
|
||||
if (surface == VA_INVALID_ID) {
|
||||
printf(_("video/vaapi: invalid surface in ringbuffer\n"));
|
||||
// 0 -> 1
|
||||
// 1 -> 0 + advance
|
||||
if (decoder->Interlaced) {
|
||||
// FIXME: first frame is never shown
|
||||
if (decoder->SurfaceField) {
|
||||
if (filled > 1) {
|
||||
decoder->SurfaceRead = (decoder->SurfaceRead + 1)
|
||||
% VIDEO_SURFACES_MAX;
|
||||
atomic_dec(&decoder->SurfacesFilled);
|
||||
decoder->SurfaceField = 0;
|
||||
}
|
||||
} else {
|
||||
decoder->SurfaceField = 1;
|
||||
}
|
||||
Debug(4, "video/vaapi: yy video surface %#x displayed\n", surface);
|
||||
} else if (filled > 1) {
|
||||
decoder->SurfaceRead = (decoder->SurfaceRead + 1)
|
||||
% VIDEO_SURFACES_MAX;
|
||||
atomic_dec(&decoder->SurfacesFilled);
|
||||
}
|
||||
|
||||
start = GetMsTicks();
|
||||
if (vaSyncSurface(decoder->VaDisplay, surface)
|
||||
!= VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: vaSyncSurface failed\n"));
|
||||
}
|
||||
surface = decoder->SurfacesRb[decoder->SurfaceRead];
|
||||
if (surface == VA_INVALID_ID) {
|
||||
printf(_("video/vaapi: invalid surface in ringbuffer\n"));
|
||||
}
|
||||
Debug(4, "video/vaapi: yy video surface %#x displayed\n", surface);
|
||||
|
||||
sync = GetMsTicks();
|
||||
start = GetMsTicks();
|
||||
// wait for rendering finished
|
||||
if (vaSyncSurface(decoder->VaDisplay, surface)
|
||||
!= VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: vaSyncSurface failed\n"));
|
||||
}
|
||||
|
||||
sync = GetMsTicks();
|
||||
|
||||
// deinterlace and full frame rate
|
||||
if (decoder->Interlaced
|
||||
// FIXME: buggy libva-driver-vdpau.
|
||||
&& VaapiBuggyVdpau && VideoDeinterlace != VideoDeinterlaceWeave) {
|
||||
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
|
||||
decoder->TopFieldFirst, 0);
|
||||
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);
|
||||
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
|
||||
decoder->TopFieldFirst, 1);
|
||||
}
|
||||
put2 = GetMsTicks();
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &decoder->FrameTime);
|
||||
|
||||
// fixes: [drm:i915_hangcheck_elapsed] *ERROR* Hangcheck
|
||||
// timer elapsed... GPU hung
|
||||
//usleep(1 * 1000);
|
||||
Debug(4, "video/vaapi: sync %2u put1 %2u put2 %2u\n", sync - start,
|
||||
put1 - sync, put2 - put1);
|
||||
usleep(500);
|
||||
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
|
||||
decoder->TopFieldFirst, 1);
|
||||
put2 = GetMsTicks();
|
||||
} else {
|
||||
Debug(3, "video/vaapi: no video surface ready\n");
|
||||
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
|
||||
decoder->TopFieldFirst, decoder->SurfaceField);
|
||||
put1 = GetMsTicks();
|
||||
put2 = put1;
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &decoder->FrameTime);
|
||||
|
||||
// fixes: [drm:i915_hangcheck_elapsed] *ERROR* Hangcheck
|
||||
// timer elapsed... GPU hung
|
||||
usleep(1 * 1000);
|
||||
Debug(4, "video/vaapi: sync %2u put1 %2u put2 %2u\n", sync - start,
|
||||
put1 - sync, put2 - put1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2944,6 +2964,13 @@ static void VideoEvent(void)
|
||||
break;
|
||||
case KeyPress:
|
||||
keysym = XLookupKeysym(&event.xkey, 0);
|
||||
switch (keysym) {
|
||||
case XK_d:
|
||||
break;
|
||||
case XK_S:
|
||||
VideoDropNextFrame = 1;
|
||||
break;
|
||||
}
|
||||
if (keysym == NoSymbol) {
|
||||
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) {
|
||||
video_clock = decoder->PTS - (decoder->Interlaced ? 40 : 20) * 90;
|
||||
}
|
||||
|
||||
// default video delay, if audio delay isn't known yet
|
||||
delay = 1 * 500L * 1000 * 1000;
|
||||
clock_gettime(CLOCK_REALTIME, &nowtime);
|
||||
|
||||
@ -3116,11 +3143,10 @@ static void *VideoDisplayHandlerThread(void *dummy)
|
||||
|
||||
filled = atomic_read(&decoder->SurfacesFilled);
|
||||
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)
|
||||
* 1000 * 1000 * 1000 + (nowtime.tv_nsec -
|
||||
decoder->FrameTime.tv_nsec) <
|
||||
(decoder->Interlaced ? 15 : 15) * 1000 * 1000) {
|
||||
decoder->FrameTime.tv_nsec) < 15 * 1000 * 1000) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3131,9 +3157,10 @@ static void *VideoDisplayHandlerThread(void *dummy)
|
||||
} else if (filled == 1 || (Fix60Hz && !(decoder->FrameCounter % 6))) {
|
||||
decoder->FramesDuped++;
|
||||
++decoder->FrameCounter;
|
||||
Warning(_("video: display buffer empty, duping frame (%d/%d)\n"),
|
||||
decoder->FramesDuped, decoder->FrameCounter);
|
||||
if (!(decoder->FrameCounter % 333)) {
|
||||
Warning(_
|
||||
("video: display buffer empty, duping frame (%d/%d)\n"),
|
||||
decoder->FramesDuped, decoder->FrameCounter);
|
||||
VaapiPrintFrames(decoder);
|
||||
}
|
||||
}
|
||||
@ -3183,6 +3210,7 @@ static void VideoThreadExit(void)
|
||||
{
|
||||
void *retval;
|
||||
|
||||
Debug(3, "video: video thread canceled\n");
|
||||
if (VideoThread) {
|
||||
if (pthread_cancel(VideoThread)) {
|
||||
Error(_("video: can't queue cancel video display thread\n"));
|
||||
@ -3378,6 +3406,7 @@ void VaapiTest(void)
|
||||
void VideoRenderFrame(VideoHwDecoder * decoder, AVCodecContext * video_ctx,
|
||||
AVFrame * frame)
|
||||
{
|
||||
// update video clock
|
||||
decoder->Vaapi.PTS += (decoder->Vaapi.Interlaced ? 40 : 20) * 90;
|
||||
|
||||
// libav: sets only pkt_dts
|
||||
@ -3388,11 +3417,18 @@ void VideoRenderFrame(VideoHwDecoder * decoder, AVCodecContext * video_ctx,
|
||||
decoder->Vaapi.PTS = frame->pkt_dts;
|
||||
}
|
||||
}
|
||||
|
||||
if (!atomic_read(&decoder->Vaapi.SurfacesFilled)) {
|
||||
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
|
||||
}
|
||||
// if video output buffer is full, wait and display surface.
|
||||
if (atomic_read(&decoder->Vaapi.SurfacesFilled) >= VIDEO_SURFACES_MAX) {
|
||||
|
||||
if (VideoDropNextFrame) { // drop frame requested
|
||||
VideoDropNextFrame--;
|
||||
return;
|
||||
}
|
||||
// if video output buffer is full, wait and display surface.
|
||||
// loop for interlace
|
||||
while (atomic_read(&decoder->Vaapi.SurfacesFilled) >= VIDEO_SURFACES_MAX) {
|
||||
struct timespec abstime;
|
||||
|
||||
abstime = decoder->Vaapi.FrameTime;
|
||||
@ -3580,6 +3616,22 @@ int VideoSetGeometry(const char *geometry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set deinterlace mode.
|
||||
*/
|
||||
void VideoSetDeinterlace(int mode)
|
||||
{
|
||||
VideoDeinterlace = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set scaling mode.
|
||||
*/
|
||||
void VideoSetScaling(int mode)
|
||||
{
|
||||
VideoScaling = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize video output module.
|
||||
**
|
||||
|
Loading…
Reference in New Issue
Block a user