r600g: advertise 32 fragment shaders inputs, not 34
[mesa.git] / src / gallium / state_trackers / vdpau / decode.c
index d618fff1784577a9389c8a8a83e0889f622a54d5..61b10e0db335d614bb7f779f87bcf11f7c220370 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"
 
 /**
@@ -50,8 +52,6 @@ vlVdpDecoderCreate(VdpDevice device,
    VdpStatus ret;
    bool supported;
 
-   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating decoder\n");
-
    if (!decoder)
       return VDP_STATUS_INVALID_POINTER;
    *decoder = 0;
@@ -67,20 +67,27 @@ vlVdpDecoderCreate(VdpDevice device,
    if (!dev)
       return VDP_STATUS_INVALID_HANDLE;
 
-   pipe = dev->context->pipe;
+   pipe = dev->context;
    screen = dev->vscreen->pscreen;
+
+   pipe_mutex_lock(dev->mutex);
+
    supported = screen->get_video_param
    (
       screen,
       p_profile,
       PIPE_VIDEO_CAP_SUPPORTED
    );
-   if (!supported)
+   if (!supported) {
+      pipe_mutex_unlock(dev->mutex);
       return VDP_STATUS_INVALID_DECODER_PROFILE;
+   }
 
    vldecoder = CALLOC(1,sizeof(vlVdpDecoder));
-   if (!vldecoder)
+   if (!vldecoder) {
+      pipe_mutex_unlock(dev->mutex);
       return VDP_STATUS_RESOURCES;
+   }
 
    vldecoder->device = dev;
 
@@ -103,16 +110,15 @@ vlVdpDecoderCreate(VdpDevice device,
       ret = VDP_STATUS_ERROR;
       goto error_handle;
    }
-
-   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoder created succesfully\n");
+   pipe_mutex_unlock(dev->mutex);
 
    return VDP_STATUS_OK;
 
 error_handle:
-
    vldecoder->decoder->destroy(vldecoder->decoder);
 
 error_decoder:
+   pipe_mutex_unlock(dev->mutex);
    FREE(vldecoder);
    return ret;
 }
@@ -125,13 +131,13 @@ vlVdpDecoderDestroy(VdpDecoder decoder)
 {
    vlVdpDecoder *vldecoder;
 
-   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying decoder\n");
-
    vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
    if (!vldecoder)
       return VDP_STATUS_INVALID_HANDLE;
 
+   pipe_mutex_lock(vldecoder->device->mutex);
    vldecoder->decoder->destroy(vldecoder->decoder);
+   pipe_mutex_unlock(vldecoder->device->mutex);
 
    FREE(vldecoder);
 
@@ -149,8 +155,6 @@ vlVdpDecoderGetParameters(VdpDecoder decoder,
 {
    vlVdpDecoder *vldecoder;
 
-   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoder get parameters called\n");
-
    vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
    if (!vldecoder)
       return VDP_STATUS_INVALID_HANDLE;
@@ -376,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.
  */
@@ -386,12 +420,14 @@ 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;
+   struct pipe_screen *screen;
    struct pipe_video_decoder *dec;
+   bool buffer_support[2];
    unsigned i;
    union {
       struct pipe_picture_desc base;
@@ -401,8 +437,6 @@ vlVdpDecoderRender(VdpDecoder decoder,
       struct pipe_h264_picture_desc h264;
    } desc;
 
-   VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding\n");
-
    if (!(picture_info && bitstream_buffers))
       return VDP_STATUS_INVALID_POINTER;
 
@@ -410,6 +444,7 @@ vlVdpDecoderRender(VdpDecoder decoder,
    if (!vldecoder)
       return VDP_STATUS_INVALID_HANDLE;
    dec = vldecoder->decoder;
+   screen = dec->context->screen;
 
    vlsurf = (vlVdpSurface *)vlGetDataHTAB(target);
    if (!vlsurf)
@@ -418,10 +453,45 @@ vlVdpDecoderRender(VdpDecoder decoder,
    if (vlsurf->device != vldecoder->device)
       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
 
-   if (vlsurf->video_buffer->chroma_format != dec->chroma_format)
+   if (vlsurf->video_buffer != NULL && vlsurf->video_buffer->chroma_format != dec->chroma_format)
       // TODO: Recreate decoder with correct chroma
       return VDP_STATUS_INVALID_CHROMA_TYPE;
 
+   pipe_mutex_lock(vlsurf->device->mutex);
+
+   buffer_support[0] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE);
+   buffer_support[1] = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_SUPPORTS_INTERLACED);
+
+   if (vlsurf->video_buffer == NULL ||
+       !screen->is_video_format_supported(screen, vlsurf->video_buffer->buffer_format, dec->profile) ||
+       !buffer_support[vlsurf->video_buffer->interlaced]) {
+
+      /* destroy the old one */
+      if (vlsurf->video_buffer)
+         vlsurf->video_buffer->destroy(vlsurf->video_buffer);
+
+      /* set the buffer format to the prefered one */
+      vlsurf->templat.buffer_format = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_PREFERED_FORMAT);
+
+      /* also set interlacing to decoders preferences */
+      vlsurf->templat.interlaced = screen->get_video_param(screen, dec->profile, PIPE_VIDEO_CAP_PREFERS_INTERLACED);
+
+      /* and recreate the video buffer */
+      vlsurf->video_buffer = dec->context->create_video_buffer(dec->context, &vlsurf->templat);
+
+      /* still no luck? get me out of here... */
+      if (!vlsurf->video_buffer) {
+         pipe_mutex_unlock(vlsurf->device->mutex);
+         return VDP_STATUS_NO_IMPLEMENTATION;
+      }
+      vlVdpVideoSurfaceClear(vlsurf);
+   }
+
+   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)) {
@@ -432,24 +502,26 @@ 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:
       ret = vlVdpDecoderRenderH264(&desc.h264, (VdpPictureInfoH264 *)picture_info);
       break;
    default:
+      pipe_mutex_unlock(vlsurf->device->mutex);
       return VDP_STATUS_INVALID_DECODER_PROFILE;
    }
-   if (ret != VDP_STATUS_OK)
-      return ret;
 
-   for (i = 0; i < bitstream_buffer_count; ++i) {
-      buffers[i] = bitstream_buffers[i].bitstream;
-      sizes[i] = bitstream_buffers[i].bitstream_bytes;
+   if (ret != VDP_STATUS_OK) {
+      pipe_mutex_unlock(vlsurf->device->mutex);
+      return ret;
    }
 
    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);
+   pipe_mutex_unlock(vlsurf->device->mutex);
    return ret;
 }