[Mesa-dev] [PATCH 1/2] st/vdpau: add VC-1 startcode if none is found in the stream

Emeric Grange emeric.grange at gmail.com
Thu Mar 15 07:13:30 PDT 2012


2012/3/15 Christian König <deathsimple at vodafone.de>

> Signed-off-by: Christian König <deathsimple at vodafone.de>
> ---
>  src/gallium/state_trackers/vdpau/decode.c |   48
> ++++++++++++++++++++++++----
>  1 files changed, 41 insertions(+), 7 deletions(-)
>
> diff --git a/src/gallium/state_trackers/vdpau/decode.c
> b/src/gallium/state_trackers/vdpau/decode.c
> index 56a171f..154ebd0 100644
> --- a/src/gallium/state_trackers/vdpau/decode.c
> +++ b/src/gallium/state_trackers/vdpau/decode.c
> @@ -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,7 @@ vlVdpDecoderRender(VdpDecoder decoder,
>       ret = vlVdpDecoderRenderMpeg4(&desc.mpeg4, (VdpPictureInfoMPEG4Part2
> *)picture_info);
>       break;
>    case PIPE_VIDEO_CODEC_VC1:
> +      vlVdpDecoderFixVC1Startcode(&bitstream_buffer_count, buffers,
> sizes);
>       ret = vlVdpDecoderRenderVC1(&desc.vc1, (VdpPictureInfoVC1
> *)picture_info);
>       break;
>    case PIPE_VIDEO_CODEC_MPEG4_AVC:
> @@ -473,16 +511,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);
> --
> 1.7.5.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>

I actually made some code that does exactly the opposite, for H.264 and
VP8, removing the start code from the first buffer containing it (so the
first buffer alltoghether or just the 3 first bytes of the first buffer). I
think the start codes, at least for H.264 are just here so the decoding
application (in this case the state tracker) can make sure the buffers are
valid video buffers, and are not used in the decoding process.

In my VP8 implementation I require a 0x9D012A start code, similar to H.264
that requires a 0x000001. I asked on the VDPAU mailing list if it was a
good idea, and what was the purpose of these start code in the first place
but I did not get an answer.

However I have no idea if a VC1 decoder requires the presence of start
codes, and your implementation is fine by me, I can still hook a
vlVdpDecoderRemoveVP8Startcode() function similar to
vlVdpDecoderFixVC1Startcode().

Emeric

diff --git a/src/gallium/state_trackers/vdpau/decode.c
b/src/gallium/state_trackers/vdpau/decode.c
index f093194..b8ef5f2 100644
--- a/src/gallium/state_trackers/vdpau/decode.c
+++ b/src/gallium/state_trackers/vdpau/decode.c
@@ -516,9 +516,41 @@ vlVdpDecoderRender(VdpDecoder decoder,
       return ret;
    }

-   for (i = 0; i < bitstream_buffer_count; ++i) {
-      buffers[i] = bitstream_buffers[i].bitstream;
-      sizes[i] = bitstream_buffers[i].bitstream_bytes;
+   // Cleanup start_code (mandatory for some codec) from bitstream buffers
+   if (u_reduce_video_profile(dec->profile) == PIPE_VIDEO_CODEC_MPEG4_AVC
||
+       u_reduce_video_profile(dec->profile) == PIPE_VIDEO_CODEC_VP8) {
+      int start_code_found = 0;
+
+      for (i = 0, j = 0; i < bitstream_buffer_count; ++i) {
+         if (!start_code_found) {
+            const uint8_t *datab = (const uint8_t
*)bitstream_buffers[i].bitstream;
+
+            if ((datab[0] == 0x9D && datab[1] == 0x01 && datab[2] == 0x2A)
||
+                (datab[0] == 0x00 && datab[1] == 0x00 && datab[2] ==
0x01)) {
+               start_code_found = 1;
+
+               if (bitstream_buffers[i].bitstream_bytes != 3) {
+                  buffers[j] = bitstream_buffers[i].bitstream + 3;
+                  sizes[j] = bitstream_buffers[i].bitstream_bytes - 3;
+                  j++;
+               }
+            } else {
+               VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Error : the first data
buffer does not contain the mandatory start_code [0x9D012A]\n");
+               return VDP_STATUS_ERROR;
+            }
+         } else {
+            buffers[j] = bitstream_buffers[i].bitstream;
+            sizes[j] = bitstream_buffers[i].bitstream_bytes;
+            j++;
+         }
+      }
+
+      bitstream_buffer_count = j;
+   } else {
+      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);
--
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20120315/b88fa8aa/attachment-0001.html>


More information about the mesa-dev mailing list