[07/13] st/va: get mjpeg slice header

Submitted by Zhang, Boyuan on Aug. 16, 2018, 8:56 p.m.

Details

Message ID 1534453013-20098-2-git-send-email-boyuan.zhang@amd.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Mesa

Not browsing as part of any series.

Commit Message

Zhang, Boyuan Aug. 16, 2018, 8:56 p.m.
From: Boyuan Zhang <boyuan.zhang@amd.com>

Move the previous get_mjpeg_slice_heaeder function and eoi from
"radeon/vcn" to "st/va".

Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com>
---
 src/gallium/state_trackers/va/picture.c       |  13 ++-
 src/gallium/state_trackers/va/picture_mjpeg.c | 132 ++++++++++++++++++++++++++
 src/gallium/state_trackers/va/va_private.h    |  11 +++
 3 files changed, 154 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/gallium/state_trackers/va/picture.c b/src/gallium/state_trackers/va/picture.c
index f2e9ba8..af136fb 100644
--- a/src/gallium/state_trackers/va/picture.c
+++ b/src/gallium/state_trackers/va/picture.c
@@ -251,11 +251,12 @@  handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
 {
    enum pipe_video_format format;
    unsigned num_buffers = 0;
-   void * const *buffers[2];
-   unsigned sizes[2];
+   void * const *buffers[3];
+   unsigned sizes[3];
    static const uint8_t start_code_h264[] = { 0x00, 0x00, 0x01 };
    static const uint8_t start_code_h265[] = { 0x00, 0x00, 0x01 };
    static const uint8_t start_code_vc1[] = { 0x00, 0x00, 0x01, 0x0d };
+   static const uint8_t eoi_jpeg[] = { 0xff, 0xd9 };
 
    format = u_reduce_video_profile(context->templat.profile);
    switch (format) {
@@ -293,6 +294,9 @@  handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
       sizes[num_buffers++] = context->mpeg4.start_code_size;
       break;
    case PIPE_VIDEO_FORMAT_JPEG:
+      vlVaGetJpegSliceHeader(context);
+      buffers[num_buffers] = (void *)context->mjpeg.slice_header;
+      sizes[num_buffers++] = context->mjpeg.slice_header_size;
       break;
    default:
       break;
@@ -302,6 +306,11 @@  handleVASliceDataBufferType(vlVaContext *context, vlVaBuffer *buf)
    sizes[num_buffers] = buf->size;
    ++num_buffers;
 
+   if (format == PIPE_VIDEO_FORMAT_JPEG) {
+      buffers[num_buffers] = (void *const)&eoi_jpeg;
+      sizes[num_buffers++] = sizeof(eoi_jpeg);
+   }
+
    if (context->needs_begin_frame) {
       context->decoder->begin_frame(context->decoder, context->target,
          &context->desc.base);
diff --git a/src/gallium/state_trackers/va/picture_mjpeg.c b/src/gallium/state_trackers/va/picture_mjpeg.c
index 396b743..f1292ea 100644
--- a/src/gallium/state_trackers/va/picture_mjpeg.c
+++ b/src/gallium/state_trackers/va/picture_mjpeg.c
@@ -114,3 +114,135 @@  void vlVaHandleSliceParameterBufferMJPEG(vlVaContext *context, vlVaBuffer *buf)
    context->desc.mjpeg.slice_parameter.restart_interval = mjpeg->restart_interval;
    context->desc.mjpeg.slice_parameter.num_mcus = mjpeg->num_mcus;
 }
+
+void vlVaGetJpegSliceHeader(vlVaContext *context)
+{
+   int size = 0, saved_size, len_pos, i;
+   uint16_t *bs;
+   uint8_t *p = context->mjpeg.slice_header;
+
+   /* SOI */
+   p[size++] = 0xff;
+   p[size++] = 0xd8;
+
+   /* DQT */
+   p[size++] = 0xff;
+   p[size++] = 0xdb;
+
+   len_pos = size++;
+   size++;
+
+   for (i = 0; i < 4; ++i) {
+      if (context->desc.mjpeg.quantization_table.load_quantiser_table[i] == 0)
+         continue;
+
+      p[size++] = i;
+      memcpy((p + size), &context->desc.mjpeg.quantization_table.quantiser_table[i], 64);
+      size += 64;
+   }
+
+   bs = (uint16_t*)&p[len_pos];
+   *bs = util_bswap16(size - 4);
+
+   saved_size = size;
+
+   /* DHT */
+   p[size++] = 0xff;
+   p[size++] = 0xc4;
+
+   len_pos = size++;
+   size++;
+
+   for (i = 0; i < 2; ++i) {
+      if (context->desc.mjpeg.huffman_table.load_huffman_table[i] == 0)
+         continue;
+
+      p[size++] = 0x00 | i;
+      memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].num_dc_codes, 16);
+      size += 16;
+      memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].dc_values, 12);
+      size += 12;
+   }
+
+   for (i = 0; i < 2; ++i) {
+      if (context->desc.mjpeg.huffman_table.load_huffman_table[i] == 0)
+         continue;
+
+      p[size++] = 0x10 | i;
+      memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].num_ac_codes, 16);
+      size += 16;
+      memcpy((p + size), &context->desc.mjpeg.huffman_table.table[i].ac_values, 162);
+      size += 162;
+   }
+
+   bs = (uint16_t*)&p[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   saved_size = size;
+
+   /* DRI */
+   if (context->desc.mjpeg.slice_parameter.restart_interval) {
+      p[size++] = 0xff;
+      p[size++] = 0xdd;
+      p[size++] = 0x00;
+      p[size++] = 0x04;
+      bs = (uint16_t*)&p[size++];
+      *bs = util_bswap16(context->desc.mjpeg.slice_parameter.restart_interval);
+      saved_size = ++size;
+   }
+
+   /* SOF */
+   p[size++] = 0xff;
+   p[size++] = 0xc0;
+
+   len_pos = size++;
+   size++;
+
+   p[size++] = 0x08;
+
+   bs = (uint16_t*)&p[size++];
+   *bs = util_bswap16(context->desc.mjpeg.picture_parameter.picture_height);
+   size++;
+
+   bs = (uint16_t*)&p[size++];
+   *bs = util_bswap16(context->desc.mjpeg.picture_parameter.picture_width);
+   size++;
+
+   p[size++] = context->desc.mjpeg.picture_parameter.num_components;
+
+   for (i = 0; i < context->desc.mjpeg.picture_parameter.num_components; ++i) {
+      p[size++] = context->desc.mjpeg.picture_parameter.components[i].component_id;
+      p[size++] = context->desc.mjpeg.picture_parameter.components[i].h_sampling_factor << 4 |
+                 context->desc.mjpeg.picture_parameter.components[i].v_sampling_factor;
+      p[size++] = context->desc.mjpeg.picture_parameter.components[i].quantiser_table_selector;
+   }
+
+   bs = (uint16_t*)&p[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   saved_size = size;
+
+   /* SOS */
+   p[size++] = 0xff;
+   p[size++] = 0xda;
+
+   len_pos = size++;
+   size++;
+
+   p[size++] = context->desc.mjpeg.slice_parameter.num_components;
+
+   for (i = 0; i < context->desc.mjpeg.slice_parameter.num_components; ++i) {
+      p[size++] = context->desc.mjpeg.slice_parameter.components[i].component_selector;
+      p[size++] = context->desc.mjpeg.slice_parameter.components[i].dc_table_selector << 4 |
+                 context->desc.mjpeg.slice_parameter.components[i].ac_table_selector;
+   }
+
+   p[size++] = 0x00;
+   p[size++] = 0x3f;
+   p[size++] = 0x00;
+
+   bs = (uint16_t*)&p[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   context->mjpeg.slice_header_size = size;
+}
diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h
index 4396abb..75a74b2 100644
--- a/src/gallium/state_trackers/va/va_private.h
+++ b/src/gallium/state_trackers/va/va_private.h
@@ -55,6 +55,14 @@ 
 #define UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
 #define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
 
+#define SOI 2
+#define DQT (4 + 4 * 65)
+#define DHT (4 + 2 * 29 + 2 * 179)
+#define DRI 6
+#define SOF (10 + 255 * 3)
+#define SOS (8 + 4 * 2)
+#define MAX_MJPEG_SLICE_HEADER_SIZE (SOI + DQT + DHT + DRI + SOF + SOS)
+
 static inline unsigned handle_hash(void *key)
 {
     return PTR_TO_UINT(key);
@@ -285,6 +293,8 @@  typedef struct {
 
    struct {
       unsigned sampling_factor;
+      uint8_t slice_header[MAX_MJPEG_SLICE_HEADER_SIZE];
+      unsigned int slice_header_size;
    } mjpeg;
 
    struct vl_deint_filter *deint;
@@ -421,6 +431,7 @@  void vlVaHandlePictureParameterBufferMPEG4(vlVaDriver *drv, vlVaContext *context
 void vlVaHandleIQMatrixBufferMPEG4(vlVaContext *context, vlVaBuffer *buf);
 void vlVaHandleSliceParameterBufferMPEG4(vlVaContext *context, vlVaBuffer *buf);
 void vlVaDecoderFixMPEG4Startcode(vlVaContext *context);
+void vlVaGetJpegSliceHeader(vlVaContext *context);
 void vlVaHandlePictureParameterBufferHEVC(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf);
 void vlVaHandleIQMatrixBufferHEVC(vlVaContext *context, vlVaBuffer *buf);
 void vlVaHandleSliceParameterBufferHEVC(vlVaContext *context, vlVaBuffer *buf);