st/vdpau: add VC-1 startcode if none is found in the stream
authorChristian König <deathsimple@vodafone.de>
Thu, 15 Mar 2012 10:58:37 +0000 (11:58 +0100)
committerChristian König <deathsimple@vodafone.de>
Thu, 22 Mar 2012 08:47:04 +0000 (09:47 +0100)
v2: only advanced profile needs that.

Signed-off-by: Christian König <deathsimple@vodafone.de>
src/gallium/state_trackers/vdpau/decode.c

index 56a171fcd8748f604951aeb1f51c3b5c8586b923..0802f28e5cc36cc9ae7228672e30a170e2a53ac4 100644 (file)
@@ -30,6 +30,8 @@
 #include "util/u_debug.h"
 #include "util/u_video.h"
 
+#include "vl/vl_vlc.h"
+
 #include "vdpau_private.h"
 
 /**
@@ -378,6 +380,36 @@ vlVdpDecoderRenderH264(struct pipe_h264_picture_desc *picture,
    return VDP_STATUS_OK;
 }
 
+static void
+vlVdpDecoderFixVC1Startcode(uint32_t *num_buffers, const void *buffers[], unsigned sizes[])
+{
+   static const uint8_t vc1_startcode[] = { 0x00, 0x00, 0x01, 0x0D };
+   struct vl_vlc vlc;
+   unsigned i;
+
+   /* search the first 64 bytes for a startcode */
+   vl_vlc_init(&vlc, *num_buffers, buffers, sizes);
+   for (i = 0; i < 64 && vl_vlc_bits_left(&vlc) >= 32; ++i) {
+      uint32_t value = vl_vlc_peekbits(&vlc, 32);
+      if (value == 0x0000010D ||
+          value == 0x0000010C ||
+          value == 0x0000010B)
+         return;
+      vl_vlc_eatbits(&vlc, 8);
+      vl_vlc_fillbits(&vlc);
+   }
+
+   /* none found, ok add one manually */
+   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Manually adding VC-1 startcode\n");
+   for (i = *num_buffers; i > 0; --i) {
+      buffers[i] = buffers[i - 1];
+      sizes[i] = sizes[i - 1];
+   }
+   ++(*num_buffers);
+   buffers[0] = vc1_startcode;
+   sizes[0] = 4;
+}
+
 /**
  * Decode a compressed field/frame and render the result into a VdpVideoSurface.
  */
@@ -388,8 +420,8 @@ vlVdpDecoderRender(VdpDecoder decoder,
                    uint32_t bitstream_buffer_count,
                    VdpBitstreamBuffer const *bitstream_buffers)
 {
-   const void * buffers[bitstream_buffer_count];
-   unsigned sizes[bitstream_buffer_count];
+   const void * buffers[bitstream_buffer_count + 1];
+   unsigned sizes[bitstream_buffer_count + 1];
    vlVdpDecoder *vldecoder;
    vlVdpSurface *vlsurf;
    VdpStatus ret;
@@ -454,6 +486,11 @@ vlVdpDecoderRender(VdpDecoder decoder,
       }
    }
 
+   for (i = 0; i < bitstream_buffer_count; ++i) {
+      buffers[i] = bitstream_buffers[i].bitstream;
+      sizes[i] = bitstream_buffers[i].bitstream_bytes;
+   }
+
    memset(&desc, 0, sizeof(desc));
    desc.base.profile = dec->profile;
    switch (u_reduce_video_profile(dec->profile)) {
@@ -464,6 +501,8 @@ vlVdpDecoderRender(VdpDecoder decoder,
       ret = vlVdpDecoderRenderMpeg4(&desc.mpeg4, (VdpPictureInfoMPEG4Part2 *)picture_info);
       break;
    case PIPE_VIDEO_CODEC_VC1:
+      if (dec->profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED)
+         vlVdpDecoderFixVC1Startcode(&bitstream_buffer_count, buffers, sizes);
       ret = vlVdpDecoderRenderVC1(&desc.vc1, (VdpPictureInfoVC1 *)picture_info);
       break;
    case PIPE_VIDEO_CODEC_MPEG4_AVC:
@@ -473,16 +512,12 @@ vlVdpDecoderRender(VdpDecoder decoder,
       pipe_mutex_unlock(vlsurf->device->mutex);
       return VDP_STATUS_INVALID_DECODER_PROFILE;
    }
+
    if (ret != VDP_STATUS_OK) {
       pipe_mutex_unlock(vlsurf->device->mutex);
       return ret;
    }
 
-   for (i = 0; i < bitstream_buffer_count; ++i) {
-      buffers[i] = bitstream_buffers[i].bitstream;
-      sizes[i] = bitstream_buffers[i].bitstream_bytes;
-   }
-
    dec->begin_frame(dec, vlsurf->video_buffer, &desc.base);
    dec->decode_bitstream(dec, vlsurf->video_buffer, &desc.base, bitstream_buffer_count, buffers, sizes);
    dec->end_frame(dec, vlsurf->video_buffer, &desc.base);