[Mesa-dev] [PATCH] st/va: add mpeg4 startcode workaround

Leo Liu leo.liu at amd.com
Thu Nov 5 13:00:21 PST 2015


From: Boyuan Zhang <boyuan.zhang at amd.com>

Signed-off-by: Boyuan Zhang <boyuan.zhang at amd.com>
Reviewed-by: Christian König <christian.koenig at amd.com>
---
 src/gallium/state_trackers/va/buffer.c     |  24 +++++-
 src/gallium/state_trackers/va/context.c    |   7 ++
 src/gallium/state_trackers/va/picture.c    | 117 +++++++++++++++++------------
 src/gallium/state_trackers/va/va_private.h |   3 +
 4 files changed, 102 insertions(+), 49 deletions(-)

diff --git a/src/gallium/state_trackers/va/buffer.c b/src/gallium/state_trackers/va/buffer.c
index 71a6503..e1f4c31 100644
--- a/src/gallium/state_trackers/va/buffer.c
+++ b/src/gallium/state_trackers/va/buffer.c
@@ -30,6 +30,7 @@
 #include "state_tracker/drm_driver.h"
 #include "util/u_memory.h"
 #include "util/u_handle_table.h"
+#include "util/u_video.h"
 #include "util/u_transfer.h"
 #include "vl/vl_winsys.h"
 
@@ -41,10 +42,20 @@ vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,
                  VABufferID *buf_id)
 {
    vlVaBuffer *buf;
+   vlVaDriver *drv;
+   vlVaContext *pContext;
 
    if (!ctx)
       return VA_STATUS_ERROR_INVALID_CONTEXT;
 
+   drv = VL_VA_DRIVER(ctx);
+   if (!drv)
+      return VA_STATUS_ERROR_INVALID_CONTEXT;
+
+   pContext = handle_table_get(drv->htab, context);
+   if (!pContext)
+      return VA_STATUS_ERROR_INVALID_CONTEXT;
+
    buf = CALLOC(1, sizeof(vlVaBuffer));
    if (!buf)
       return VA_STATUS_ERROR_ALLOCATION_FAILED;
@@ -59,8 +70,17 @@ vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,
       return VA_STATUS_ERROR_ALLOCATION_FAILED;
    }
 
-   if (data)
-      memcpy(buf->data, data, size * num_elements);
+   uint8_t* pExternalData = (uint8_t*) data;
+   if (data) {
+      if ((u_reduce_video_profile(pContext->desc.base.profile) == PIPE_VIDEO_FORMAT_MPEG4)
+            && (pContext->mpeg4.vaapi_mpeg4_workaround == true)
+            && (buf->type == VASliceDataBufferType)) {
+         memcpy(pContext->mpeg4.extra_data,
+                pExternalData - VL_VA_MPEG4_BYTES_FOR_LOOKUP,
+                VL_VA_MPEG4_BYTES_FOR_LOOKUP);
+      }
+      memcpy(buf->data, pExternalData, buf->size * buf->num_elements);
+   }
 
    *buf_id = handle_table_add(VL_VA_DRIVER(ctx)->htab, buf);
 
diff --git a/src/gallium/state_trackers/va/context.c b/src/gallium/state_trackers/va/context.c
index 845b547..45240f5 100644
--- a/src/gallium/state_trackers/va/context.c
+++ b/src/gallium/state_trackers/va/context.c
@@ -35,6 +35,8 @@
 
 #include "va_private.h"
 
+DEBUG_GET_ONCE_BOOL_OPTION(mpeg4, "VAAPI_MPEG4_WORKAROUND", FALSE);
+
 #include <va/va_drmcommon.h>
 
 static struct VADriverVTable vtable =
@@ -275,6 +277,11 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width,
             return VA_STATUS_ERROR_ALLOCATION_FAILED;
          }
       }
+
+      if (u_reduce_video_profile(context->decoder->profile) ==
+            PIPE_VIDEO_FORMAT_MPEG4) {
+         context->mpeg4.vaapi_mpeg4_workaround = debug_get_option_mpeg4();
+      }
    }
 
    context->desc.base.profile = config_id;
diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c
index e850689..1f1b427 100644
--- a/src/gallium/state_trackers/va/picture.c
+++ b/src/gallium/state_trackers/va/picture.c
@@ -584,60 +584,83 @@ vlVaDecoderFixMPEG4Startcode(vlVaContext *context)
    int mod_time;
    unsigned int vop_size;
    unsigned int vop_coding_type = context->desc.mpeg4.vop_coding_type;
+   bool startcode_available = false;
 
    context->mpeg4.start_code_size = 0;
    memset(context->mpeg4.start_code, 0, sizeof(context->mpeg4.start_code));
-   if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_I) {
-      unsigned int vop_time = context->mpeg4.frame_num/
-            context->desc.mpeg4.vop_time_increment_resolution;
-      unsigned int vop_hour = vop_time / 3600;
-      unsigned int vop_minute = (vop_time / 60) % 60;
-      unsigned int vop_second = vop_time % 60;
-      uint8_t group_of_vop[] = { 0x00, 0x00, 0x01, 0xb3, 0x00, 0x00, 0x00 };
-      struct bit_stream bs_gvop = {group_of_vop, sizeof(group_of_vop)*8, 32};
-
-      write_bits(&bs_gvop, vop_hour, 5);
-      write_bits(&bs_gvop, vop_minute, 6);
-      write_bit(&bs_gvop, 1); /* marker_bit */
-      write_bits(&bs_gvop, vop_second, 6);
-      write_bit(&bs_gvop, 0); /* closed_gov */ /* TODO replace magic */
-      write_bit(&bs_gvop, 0); /* broken_link */
-      write_bit(&bs_gvop, 0); /* padding */
-      write_bits(&bs_gvop, 7, 3); /* padding */
-
-      memcpy(context->mpeg4.start_code, group_of_vop, sizeof(group_of_vop));
-      context->mpeg4.start_code_size += sizeof(group_of_vop);
+   if (context->mpeg4.vaapi_mpeg4_workaround == true) {
+      uint8_t* p = (uint8_t*) context->mpeg4.extra_data;
+      const uint8_t start_code[] = { 0x00, 0x00, 0x01, 0xb6 };
+      int extraSize = 0;
+      bool found = false;
+      for (int i = 0 ; i < VL_VA_MPEG4_BYTES_FOR_LOOKUP ; i++) {
+         if (memcmp (p, start_code, sizeof(start_code)) == 0) {
+            found = true;
+            break;
+         }
+         p += 1;
+         extraSize += 1;
+      }
+      if (found) {
+         startcode_available = true;
+         vop_size = VL_VA_MPEG4_BYTES_FOR_LOOKUP - extraSize;
+         for (int i = 0 ; i < vop_size ; i++)
+            vop[i] = *(p + i);
+      }
    }
+   if (startcode_available == false) {
+      if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_I) {
+         unsigned int vop_time = context->mpeg4.frame_num/
+               context->desc.mpeg4.vop_time_increment_resolution;
+         unsigned int vop_hour = vop_time / 3600;
+         unsigned int vop_minute = (vop_time / 60) % 60;
+         unsigned int vop_second = vop_time % 60;
+         uint8_t group_of_vop[] = { 0x00, 0x00, 0x01, 0xb3, 0x00, 0x00, 0x00 };
+         struct bit_stream bs_gvop = {group_of_vop, sizeof(group_of_vop)*8, 32};
+
+         write_bits(&bs_gvop, vop_hour, 5);
+         write_bits(&bs_gvop, vop_minute, 6);
+         write_bit(&bs_gvop, 1); /* marker_bit */
+         write_bits(&bs_gvop, vop_second, 6);
+         write_bit(&bs_gvop, 0); /* closed_gov */ /* TODO replace magic */
+         write_bit(&bs_gvop, 0); /* broken_link */
+         write_bit(&bs_gvop, 0); /* padding */
+         write_bits(&bs_gvop, 7, 3); /* padding */
+
+         memcpy(context->mpeg4.start_code, group_of_vop, sizeof(group_of_vop));
+         context->mpeg4.start_code_size += sizeof(group_of_vop);
+      }
 
-   write_bits(&bs_vop, vop_coding_type, 2);
-   mod_time = context->mpeg4.frame_num %
-         context->desc.mpeg4.vop_time_increment_resolution == 0 &&
-         vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I;
-   while (mod_time--)
-      write_bit(&bs_vop, 1); /* modulo_time_base */
-   write_bit(&bs_vop, 0); /* modulo_time_base */
-
-   write_bit(&bs_vop, 1); /* marker_bit */
-   vop_time_inc = context->mpeg4.frame_num %
-         context->desc.mpeg4.vop_time_increment_resolution;
-   write_bits(&bs_vop, vop_time_inc, context->mpeg4.vti_bits);
-   write_bit(&bs_vop, 1); /* marker_bit */
-   write_bit(&bs_vop, 1); /* vop_coded */
-   if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_P)
-      write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.vop_rounding_type);
-   write_bits(&bs_vop, context->mpeg4.pps.vop_fields.bits.intra_dc_vlc_thr, 3);
-   if (context->mpeg4.pps.vol_fields.bits.interlaced) {
-      write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.top_field_first);
-      write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.alternate_vertical_scan_flag);
-   }
+      write_bits(&bs_vop, vop_coding_type, 2);
+      mod_time = context->mpeg4.frame_num %
+            context->desc.mpeg4.vop_time_increment_resolution == 0 &&
+            vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I;
+      while (mod_time--)
+         write_bit(&bs_vop, 1); /* modulo_time_base */
+      write_bit(&bs_vop, 0); /* modulo_time_base */
 
-   write_bits(&bs_vop, context->mpeg4.quant_scale, context->mpeg4.pps.quant_precision);
-   if (vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I)
-      write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_forward, 3);
-   if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_B)
-      write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_backward, 3);
+      write_bit(&bs_vop, 1); /* marker_bit */
+      vop_time_inc = context->mpeg4.frame_num %
+            context->desc.mpeg4.vop_time_increment_resolution;
+      write_bits(&bs_vop, vop_time_inc, context->mpeg4.vti_bits);
+      write_bit(&bs_vop, 1); /* marker_bit */
+      write_bit(&bs_vop, 1); /* vop_coded */
+      if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_P)
+         write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.vop_rounding_type);
+      write_bits(&bs_vop, context->mpeg4.pps.vop_fields.bits.intra_dc_vlc_thr, 3);
+      if (context->mpeg4.pps.vol_fields.bits.interlaced) {
+         write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.top_field_first);
+         write_bit(&bs_vop, context->mpeg4.pps.vop_fields.bits.alternate_vertical_scan_flag);
+      }
 
-   vop_size = bs_vop.pos/8;
+      write_bits(&bs_vop, context->mpeg4.quant_scale, context->mpeg4.pps.quant_precision);
+      if (vop_coding_type+1 != PIPE_MPEG12_PICTURE_CODING_TYPE_I)
+         write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_forward, 3);
+      if (vop_coding_type+1 == PIPE_MPEG12_PICTURE_CODING_TYPE_B)
+         write_bits(&bs_vop, context->desc.mpeg4.vop_fcode_backward, 3);
+
+      vop_size = bs_vop.pos/8;
+   }
    memcpy(context->mpeg4.start_code + context->mpeg4.start_code_size, vop, vop_size);
    context->mpeg4.start_code_size += vop_size;
 }
diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h
index 2b645d0..c954950 100644
--- a/src/gallium/state_trackers/va/va_private.h
+++ b/src/gallium/state_trackers/va/va_private.h
@@ -49,6 +49,7 @@
 #define VL_VA_PSCREEN(ctx) (VL_VA_DRIVER(ctx)->vscreen->pscreen)
 
 #define VL_VA_MAX_IMAGE_FORMATS 9
+#define VL_VA_MPEG4_BYTES_FOR_LOOKUP 12
 
 static inline enum pipe_video_chroma_format
 ChromaToPipe(int format)
@@ -226,6 +227,8 @@ typedef struct {
       unsigned int quant_scale;
       VAPictureParameterBufferMPEG4 pps;
       uint8_t start_code[32];
+      uint8_t extra_data[VL_VA_MPEG4_BYTES_FOR_LOOKUP];
+      bool vaapi_mpeg4_workaround;
    } mpeg4;
 } vlVaContext;
 
-- 
1.9.1



More information about the mesa-dev mailing list