From 422c378a5e221392715e3a824f0759fea58a0f2d Mon Sep 17 00:00:00 2001 From: Johns Date: Sun, 29 Jan 2012 11:28:10 +0100 Subject: [PATCH] Add workaround for Intel VA-API MPEG GPU hung. --- ChangeLog | 5 ++++ README.txt | 2 ++ Todo | 10 ++++--- video.c | 76 +++++++++++++++++++++++++++++++++++++++++------------- 4 files changed, 72 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 34b470c..2eb324c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ User johns Date: + Add workaround for Intel VA-API MPEG GPU hung. + +User johns +Date: Sat Jan 28 13:32:12 CET 2012 + Release Version 0.4.5 Add configurable skip lines at video top and bottom. Add auto-crop tolerance configuration. diff --git a/README.txt b/README.txt index 09ca6de..aaec1c9 100644 --- a/README.txt +++ b/README.txt @@ -146,6 +146,8 @@ Setup: /etc/vdr/setup.conf if detected crop area is too small, cut max 'n' pixels at top and bottom. + softhddevice.SkipLines = 0 + skip 'n' lines at top and bottom of the video picture. softhddevice.Suspend.Close = 0 1 suspend closes x11 window, connection and audio device. diff --git a/Todo b/Todo index 03ea597..9ace52b 100644 --- a/Todo +++ b/Todo @@ -38,7 +38,9 @@ video: suspendoutput didn't show logo or black pictures (must detect video format to show image) hard channel switch - skip line not configurable from setup menu. + skip lines not configurable from setup menu. + software decoder path didn't support auto-crop + software decoder path didn't support correct 4:3 16:9 vdpau: @@ -46,7 +48,7 @@ libva: yaepghd (VaapiSetOutputPosition) support can associate only displayed part of osd grab image for va-api - still many: + still many: (workaround export NO_MPEG_HW=1) [drm:i915_hangcheck_elapsed] *ERROR* Hangcheck timer elapsed... GPU hung [drm:i915_wait_request] *ERROR* i915_wait_request returns -11 ... @@ -56,7 +58,8 @@ libva: branch vaapi-ext libva-intel-driver: 1080i does no v-sync (sometimes correct working with vaapi-ext) OSD has sometimes wrong size (workaround written) - software decoder needs UV swab + sometimes software decoder deinterlace isn't working and 1080i channels + show artefacts libva-vdpau-driver: G210/GT520 OSD update too slow (needs hardware problem workaround) @@ -85,6 +88,7 @@ audio/alsa: audio/oss: alsa oss emulation mixer "pcm" not working + oss4 mixer channel not working ring buffer overflow with alsa oss emulation HDMI/SPDIF Passthrough: diff --git a/video.c b/video.c index 7bc5234..04dbbeb 100644 --- a/video.c +++ b/video.c @@ -1561,6 +1561,7 @@ static void VaapiCleanup(VaapiDecoder * decoder) VaapiDestroyDeinterlaceImages(decoder); } + decoder->FrameCounter = 0; decoder->PTS = AV_NOPTS_VALUE; VideoDeltaPTS = 0; } @@ -1865,7 +1866,10 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder, // cleanup last context VaapiCleanup(decoder); - if (!VideoHardwareDecoder) { // hardware disabled by config + if (!VideoHardwareDecoder + || (video_ctx->codec_id == CODEC_ID_MPEG2VIDEO + && VideoHardwareDecoder == 1) + ) { // hardware disabled by config Debug(3, "codec: hardware acceleration disabled\n"); goto slow_path; } @@ -2064,6 +2068,8 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface, { unsigned type; VAStatus status; + uint32_t s; + uint32_t e; // deinterlace if (interlaced @@ -2086,6 +2092,7 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface, type = VA_FRAME_PICTURE; } + s = GetMsTicks(); xcb_flush(Connection); if ((status = vaPutSurface(decoder->VaDisplay, surface, decoder->Window, // decoder src @@ -2100,6 +2107,15 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface, Error(_("video/vaapi: vaPutSurface failed %d\n"), status); } + if (0 && vaSyncSurface(decoder->VaDisplay, surface) != VA_STATUS_SUCCESS) { + Error(_("video/vaapi: vaSyncSurface failed\n")); + } + e = GetMsTicks(); + if (e - s > 2000) { + Error(_("video/vaapi: gpu hung %d ms %d\n"), e - s, decoder->FrameCounter); + fprintf(stderr, _("video/vaapi: gpu hung %d ms %d\n"), e - s, decoder->FrameCounter); + } + if (0) { // check if surface is really ready // VDPAU backend, says always ready @@ -2133,7 +2149,6 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface, usleep(1 * 1000); } } - } #ifdef USE_GLX @@ -2792,14 +2807,16 @@ static void VaapiBlackSurface(VaapiDecoder * decoder) clock_gettime(CLOCK_REALTIME, &decoder->FrameTime); put1 = GetMsTicks(); + if (put1 - sync > 2000 ) { + Error(_("video/vaapi: gpu hung %d ms %d\n"), put1 - sync, decoder->FrameCounter); + fprintf(stderr, _("video/vaapi: gpu hung %d ms %d\n"), put1 - sync, decoder->FrameCounter); + } Debug(4, "video/vaapi: sync %2u put1 %2u\n", sync - start, put1 - sync); if (0 && vaSyncSurface(decoder->VaDisplay, decoder->BlackSurface) != VA_STATUS_SUCCESS) { Error(_("video/vaapi: vaSyncSurface failed\n")); } - - usleep(500); } /// @@ -3385,20 +3402,40 @@ static void VaapiRenderFrame(VaapiDecoder * decoder, != VA_STATUS_SUCCESS) { Error(_("video/vaapi: can't map the image!\n")); } + // crazy: intel mixes YV12 and NV12 with mpeg if (decoder->Image->format.fourcc == VA_FOURCC_NV12) { - static int warned; + int x; - // FIXME: intel NV12 convert YV12 to NV12 - if (!warned) { - warned = 1; - Error(_("video/vaapi: FIXME: yv12->nv12 not written\n")); + // intel NV12 convert YV12 to NV12 + + // copy Y + for ( i=0; iImage->offsets[0] + + decoder->Image->pitches[0] * i, + frame->data[0] + frame->linesize[0] * i, + frame->linesize[0]); + } + // copy UV + for ( i=0; i< height / 2; ++i ) { + for ( x=0; x < frame->linesize[1]; ++x ) { + ((uint8_t*)va_image_data)[decoder->Image->offsets[1] + + decoder->Image->pitches[1] * i + x * 2 + 0] + = frame->data[1][i * frame->linesize[1] + x]; + ((uint8_t*)va_image_data)[decoder->Image->offsets[1] + + decoder->Image->pitches[1] * i + x * 2 + 1] + = frame->data[2][i * frame->linesize[2] + x]; + } } } else { // FIXME: I420 vs YV12 - for (i = 0; (unsigned)i < decoder->Image->num_planes; ++i) { - picture->data[i] = va_image_data + decoder->Image->offsets[i]; - picture->linesize[i] = decoder->Image->pitches[i]; + if ( decoder->Image->num_planes == 3 ) { + picture->data[0] = va_image_data + decoder->Image->offsets[0]; + picture->linesize[0] = decoder->Image->pitches[0]; + picture->data[1] = va_image_data + decoder->Image->offsets[2]; + picture->linesize[1] = decoder->Image->pitches[2]; + picture->data[2] = va_image_data + decoder->Image->offsets[1]; + picture->linesize[2] = decoder->Image->pitches[1]; } av_picture_copy(picture, (AVPicture *) frame, video_ctx->pix_fmt, @@ -3576,10 +3613,6 @@ static void VaapiDisplayFrame(void) #endif decoder->FrameTime = nowtime; - - // fixes: [drm:i915_hangcheck_elapsed] *ERROR* Hangcheck - // timer elapsed... GPU hung - usleep(1 * 1000); } } @@ -5426,7 +5459,10 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder, Debug(3, "video: new stream format %d\n", GetMsTicks() - VideoSwitch); VdpauCleanup(decoder); - if (!VideoHardwareDecoder) { // hardware disabled by config + if (!VideoHardwareDecoder + || (video_ctx->codec_id == CODEC_ID_MPEG2VIDEO + && VideoHardwareDecoder == 1) + ) { // hardware disabled by config Debug(3, "codec: hardware acceleration disabled\n"); goto slow_path; } @@ -8518,9 +8554,13 @@ void VideoInit(const char *display_name) #endif // FIXME: make it configurable from gui - if (!getenv("NO_HW")) { + VideoHardwareDecoder = -1; + if (getenv("NO_MPEG_HW")) { VideoHardwareDecoder = 1; } + if (getenv("NO_HW")) { + VideoHardwareDecoder = 0; + } //xcb_prefetch_maximum_request_length(Connection); xcb_flush(Connection); }