Workaround for mpeg2 FFMpeg+VA-API+Intel GPU hung.

This commit is contained in:
Johns 2012-01-31 20:45:09 +01:00
parent 364cc04736
commit bd84e3f3b9
3 changed files with 90 additions and 2 deletions

View File

@ -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

View File

@ -487,6 +487,48 @@ static void VideoNextPacket(int codec_id)
avpkt->dts = AV_NOPTS_VALUE;
}
/**
** 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.
*/
@ -561,7 +603,33 @@ int VideoDecode(void)
avpkt->size = avpkt->stream_index;
avpkt->stream_index = 0;
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;

18
video.c
View File

@ -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"));
}
}
}
}