summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2012-01-31 20:45:09 +0100
committerJohns <johns98@gmx.net>2012-01-31 20:45:09 +0100
commitbd84e3f3b90f2a938e09a08922aa260c5d4fb070 (patch)
tree8a7504b777ce876649bb9ca95fd0739f1260e24d
parent364cc04736aae34ad7f9e2685e9d54dde87e46ca (diff)
downloadvdr-plugin-softhddevice-bd84e3f3b90f2a938e09a08922aa260c5d4fb070.tar.gz
vdr-plugin-softhddevice-bd84e3f3b90f2a938e09a08922aa260c5d4fb070.tar.bz2
Workaround for mpeg2 FFMpeg+VA-API+Intel GPU hung.
-rw-r--r--ChangeLog4
-rw-r--r--softhddev.c70
-rw-r--r--video.c18
3 files changed, 90 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index df4eef2..8ede505 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,9 @@
User johns
Date:
- Fix bug: Nur schwarzes Bild bei VA-API hw decoder.
+ Workaround for mpeg2 FFMpeg + VA-API + Intel GPU hung.
+ Fix bug: Missing vaSyncSurface and vaDestroyImage.
+ Fix bug: Only black picture with VA-API hw decoder.
User HelAu
Date: Mon Jan 30 16:54:47 CET 2012
diff --git a/softhddev.c b/softhddev.c
index 317864e..6146fbe 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -488,6 +488,48 @@ static void VideoNextPacket(int codec_id)
}
/**
+** Fix packet for FFMpeg.
+**
+** Some tv-stations sends mulitple pictures in a singe PES packet.
+** Current ffmpeg 0.10 and libav-0.8 has problems with this.
+** Split the packet into single picture packets.
+*/
+void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
+{
+ uint8_t *p;
+ int n;
+ AVPacket tmp[1];
+ int first;
+
+ p = avpkt->data;
+ n = avpkt->size;
+ *tmp = *avpkt;
+
+ first = 1;
+ while (n > 4) {
+ // scan for picture header
+ if (!p[0] && !p[1] && p[2] == 0x01 && !p[3]) {
+ if (first) {
+ first = 0;
+ n -= 4;
+ p += 4;
+ continue;
+ }
+ // packet has already an picture header
+ printf("split\n");
+ tmp->size = p - tmp->data;
+ CodecVideoDecode(MyVideoDecoder, tmp);
+ tmp->data = p;
+ tmp->size = n;
+ }
+ --n;
+ ++p;
+ }
+
+ CodecVideoDecode(MyVideoDecoder, tmp);
+}
+
+/**
** Decode from PES packet ringbuffer.
*/
int VideoDecode(void)
@@ -561,7 +603,33 @@ int VideoDecode(void)
avpkt->size = avpkt->stream_index;
avpkt->stream_index = 0;
- CodecVideoDecode(MyVideoDecoder, avpkt);
+ if (0) {
+ static int done;
+
+ if (done < 2) {
+ int fildes;
+ int who_designed_this_is____;
+
+ if (done == 0)
+ fildes =
+ open("frame0.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ else if (done == 1)
+ fildes =
+ open("frame1.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ else
+ fildes =
+ open("frame2.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ done++;
+ who_designed_this_is____ = write(fildes, avpkt->data, avpkt->size);
+ close(fildes);
+ }
+ }
+
+ if (last_codec_id == CODEC_ID_MPEG2VIDEO) {
+ FixPacketForFFMpeg(MyVideoDecoder, avpkt);
+ } else {
+ CodecVideoDecode(MyVideoDecoder, avpkt);
+ }
avpkt->size = saved_size;
diff --git a/video.c b/video.c
index d10ee86..c5e3508 100644
--- a/video.c
+++ b/video.c
@@ -2167,6 +2167,7 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface,
usleep(1 * 1000);
}
}
+ usleep(1 * 1000);
}
#ifdef USE_GLX
@@ -2785,6 +2786,10 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
decoder->Image->buf) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't unmap the image!\n"));
}
+ if (vaDestroyImage(VaDisplay,
+ decoder->Image->image_id) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't destroy image!\n"));
+ }
}
// FIXME: intel didn't support put image.
if (0
@@ -2835,6 +2840,7 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: vaSyncSurface failed\n"));
}
+ usleep(1 * 1000);
}
///
@@ -3470,6 +3476,12 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
Error(_("video/vaapi: can't put image err:%d!\n"), i);
}
+ if (!decoder->PutImage
+ && vaDestroyImage(VaDisplay,
+ decoder->Image->image_id) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't destroy image!\n"));
+ }
+
VaapiQueueSurface(decoder, surface, 1);
}
@@ -3533,6 +3545,12 @@ static void VaapiAdvanceFrame(void)
if (!(decoder->FramesDisplayed % 300)) {
VaapiPrintFrames(decoder);
}
+ // wait for rendering finished
+ surface = decoder->SurfacesRb[decoder->SurfaceRead];
+ if (vaSyncSurface(decoder->VaDisplay, surface)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: vaSyncSurface failed\n"));
+ }
}
}
}