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