[Mesa-dev] [PATCH 13/20] radeon/uvd: reconstruct MJPEG bitstream

2017-08-16 Thread Leo Liu
The current tier 1 mjpeg firmware only supports at the bitstream
level, the later tier 2 support will be at the buffers level with
newer hardware.

Signed-off-by: Leo Liu 
Acked-by: Christian König 
---
 src/gallium/drivers/radeon/radeon_uvd.c | 136 
 1 file changed, 136 insertions(+)

diff --git a/src/gallium/drivers/radeon/radeon_uvd.c 
b/src/gallium/drivers/radeon/radeon_uvd.c
index b140f4ca79..b6106c6e1f 100644
--- a/src/gallium/drivers/radeon/radeon_uvd.c
+++ b/src/gallium/drivers/radeon/radeon_uvd.c
@@ -947,6 +947,128 @@ static struct ruvd_mpeg4 get_mpeg4_msg(struct 
ruvd_decoder *dec,
return result;
 }
 
+static void get_mjpeg_slice_header(struct ruvd_decoder *dec, struct 
pipe_mjpeg_picture_desc *pic)
+{
+   int size = 0, saved_size, len_pos, i;
+   uint16_t *bs;
+   uint8_t *buf = dec->bs_ptr;
+
+   /* SOI */
+   buf[size++] = 0xff;
+   buf[size++] = 0xd8;
+
+   /* DQT */
+   buf[size++] = 0xff;
+   buf[size++] = 0xdb;
+
+   len_pos = size++;
+   size++;
+
+   for (i = 0; i < 4; ++i) {
+   if (pic->quantization_table.load_quantiser_table[i] == 0)
+   continue;
+
+   buf[size++] = i;
+   memcpy((buf + size), >quantization_table.quantiser_table, 
64);
+   size += 64;
+   }
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - 4);
+
+   saved_size = size;
+
+   /* DHT */
+   buf[size++] = 0xff;
+   buf[size++] = 0xc4;
+
+   len_pos = size++;
+   size++;
+
+   for (i = 0; i < 2; ++i) {
+   if (pic->huffman_table.load_huffman_table[i] == 0)
+   continue;
+
+   buf[size++] = 0x00 | i;
+   memcpy((buf + size), >huffman_table.table[i].num_dc_codes, 
16);
+   size += 16;
+   memcpy((buf + size), >huffman_table.table[i].dc_values, 
12);
+   size += 12;
+   }
+
+   for (i = 0; i < 2; ++i) {
+   if (pic->huffman_table.load_huffman_table[i] == 0)
+   continue;
+
+   buf[size++] = 0x10 | i;
+   memcpy((buf + size), >huffman_table.table[i].num_ac_codes, 
16);
+   size += 16;
+   memcpy((buf + size), >huffman_table.table[i].ac_values, 
162);
+   size += 162;
+   }
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   saved_size = size;
+
+   /* SOF */
+   buf[size++] = 0xff;
+   buf[size++] = 0xc0;
+
+   len_pos = size++;
+   size++;
+
+   buf[size++] = 0x08;
+
+   bs = (uint16_t*)[size++];
+   *bs = util_bswap16(pic->picture_parameter.picture_height);
+   size++;
+
+   bs = (uint16_t*)[size++];
+   *bs = util_bswap16(pic->picture_parameter.picture_width);
+   size++;
+
+   buf[size++] = pic->picture_parameter.num_components;
+
+   for (i = 0; i < pic->picture_parameter.num_components; ++i) {
+   buf[size++] = pic->picture_parameter.components[i].component_id;
+   buf[size++] = 
pic->picture_parameter.components[i].h_sampling_factor << 4 |
+   pic->picture_parameter.components[i].v_sampling_factor;
+   buf[size++] = 
pic->picture_parameter.components[i].quantiser_table_selector;
+   }
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   saved_size = size;
+
+   /* SOS */
+   buf[size++] = 0xff;
+   buf[size++] = 0xda;
+
+   len_pos = size++;
+   size++;
+
+   buf[size++] = pic->slice_parameter.num_components;
+
+   for (i = 0; i < pic->slice_parameter.num_components; ++i) {
+   buf[size++] = 
pic->slice_parameter.components[i].component_selector;
+   buf[size++] = 
pic->slice_parameter.components[i].dc_table_selector << 4 |
+   pic->slice_parameter.components[i].ac_table_selector;
+   }
+
+   buf[size++] = 0x00;
+   buf[size++] = 0x3f;
+   buf[size++] = 0x00;
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   dec->bs_ptr += size;
+   dec->bs_size += size;
+}
+
 /**
  * destroy this video decoder
  */
@@ -1025,6 +1147,7 @@ static void ruvd_decode_bitstream(struct pipe_video_codec 
*decoder,
  const unsigned *sizes)
 {
struct ruvd_decoder *dec = (struct ruvd_decoder*)decoder;
+   enum pipe_video_format format = 
u_reduce_video_profile(picture->profile);
unsigned i;
 
assert(decoder);
@@ -1032,10 +1155,16 @@ static void ruvd_decode_bitstream(struct 
pipe_video_codec *decoder,
if (!dec->bs_ptr)
return;
 
+   if (format == PIPE_VIDEO_FORMAT_JPEG)
+   get_mjpeg_slice_header(dec, (struct 
pipe_mjpeg_picture_desc*)picture);
+
for (i = 0; i < 

[Mesa-dev] [PATCH 13/20] radeon/uvd: reconstruct mjpeg bitstream

2017-08-15 Thread Leo Liu
The current tier 1 mjpeg firmware only supports at the bitstream
level, the later tier 2 support will be at the buffers level with
newer hardware.

Signed-off-by: Leo Liu 
---
 src/gallium/drivers/radeon/radeon_uvd.c | 136 
 1 file changed, 136 insertions(+)

diff --git a/src/gallium/drivers/radeon/radeon_uvd.c 
b/src/gallium/drivers/radeon/radeon_uvd.c
index 5e15f94de3..59d1f199e9 100644
--- a/src/gallium/drivers/radeon/radeon_uvd.c
+++ b/src/gallium/drivers/radeon/radeon_uvd.c
@@ -943,6 +943,128 @@ static struct ruvd_mpeg4 get_mpeg4_msg(struct 
ruvd_decoder *dec,
return result;
 }
 
+static void get_mjpeg_slice_header(struct ruvd_decoder *dec, struct 
pipe_mjpeg_picture_desc *pic)
+{
+   int size = 0, saved_size, len_pos, i;
+   uint16_t *bs;
+   uint8_t *buf = dec->bs_ptr;
+
+   /* SOI */
+   buf[size++] = 0xff;
+   buf[size++] = 0xd8;
+
+   /* DQT */
+   buf[size++] = 0xff;
+   buf[size++] = 0xdb;
+
+   len_pos = size++;
+   size++;
+
+   for (i = 0; i < 4; ++i) {
+   if (pic->quantization_table.load_quantiser_table[i] == 0)
+   continue;
+
+   buf[size++] = i;
+   memcpy((buf + size), >quantization_table.quantiser_table, 
64);
+   size += 64;
+   }
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - 4);
+
+   saved_size = size;
+
+   /* DHT */
+   buf[size++] = 0xff;
+   buf[size++] = 0xc4;
+
+   len_pos = size++;
+   size++;
+
+   for (i = 0; i < 2; ++i) {
+   if (pic->huffman_table.load_huffman_table[i] == 0)
+   continue;
+
+   buf[size++] = 0x00 | i;
+   memcpy((buf + size), >huffman_table.table[i].num_dc_codes, 
16);
+   size += 16;
+   memcpy((buf + size), >huffman_table.table[i].dc_values, 
12);
+   size += 12;
+   }
+
+   for (i = 0; i < 2; ++i) {
+   if (pic->huffman_table.load_huffman_table[i] == 0)
+   continue;
+
+   buf[size++] = 0x10 | i;
+   memcpy((buf + size), >huffman_table.table[i].num_ac_codes, 
16);
+   size += 16;
+   memcpy((buf + size), >huffman_table.table[i].ac_values, 
162);
+   size += 162;
+   }
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   saved_size = size;
+
+   /* SOF */
+   buf[size++] = 0xff;
+   buf[size++] = 0xc0;
+
+   len_pos = size++;
+   size++;
+
+   buf[size++] = 0x08;
+
+   bs = (uint16_t*)[size++];
+   *bs = util_bswap16(pic->picture_parameter.picture_height);
+   size++;
+
+   bs = (uint16_t*)[size++];
+   *bs = util_bswap16(pic->picture_parameter.picture_width);
+   size++;
+
+   buf[size++] = pic->picture_parameter.num_components;
+
+   for (i = 0; i < pic->picture_parameter.num_components; ++i) {
+   buf[size++] = pic->picture_parameter.components[i].component_id;
+   buf[size++] = 
pic->picture_parameter.components[i].h_sampling_factor << 4 |
+   pic->picture_parameter.components[i].v_sampling_factor;
+   buf[size++] = 
pic->picture_parameter.components[i].quantiser_table_selector;
+   }
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   saved_size = size;
+
+   /* SOS */
+   buf[size++] = 0xff;
+   buf[size++] = 0xda;
+
+   len_pos = size++;
+   size++;
+
+   buf[size++] = pic->slice_parameter.num_components;
+
+   for (i = 0; i < pic->slice_parameter.num_components; ++i) {
+   buf[size++] = 
pic->slice_parameter.components[i].component_selector;
+   buf[size++] = 
pic->slice_parameter.components[i].dc_table_selector << 4 |
+   pic->slice_parameter.components[i].ac_table_selector;
+   }
+
+   buf[size++] = 0x00;
+   buf[size++] = 0x3f;
+   buf[size++] = 0x00;
+
+   bs = (uint16_t*)[len_pos];
+   *bs = util_bswap16(size - saved_size - 2);
+
+   dec->bs_ptr += size;
+   dec->bs_size += size;
+}
+
 /**
  * destroy this video decoder
  */
@@ -1021,6 +1143,7 @@ static void ruvd_decode_bitstream(struct pipe_video_codec 
*decoder,
  const unsigned *sizes)
 {
struct ruvd_decoder *dec = (struct ruvd_decoder*)decoder;
+   enum pipe_video_format format = 
u_reduce_video_profile(picture->profile);
unsigned i;
 
assert(decoder);
@@ -1028,10 +1151,16 @@ static void ruvd_decode_bitstream(struct 
pipe_video_codec *decoder,
if (!dec->bs_ptr)
return;
 
+   if (format == PIPE_VIDEO_FORMAT_MJPEG)
+   get_mjpeg_slice_header(dec, (struct 
pipe_mjpeg_picture_desc*)picture);
+
for (i = 0; i < num_buffers; ++i) {
struct