radeon/uvd: reconstruct MJPEG bitstream
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 <leo.liu@amd.com> Acked-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
@@ -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), &pic->quantization_table.quantiser_table, 64);
|
||||
size += 64;
|
||||
}
|
||||
|
||||
bs = (uint16_t*)&buf[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), &pic->huffman_table.table[i].num_dc_codes, 16);
|
||||
size += 16;
|
||||
memcpy((buf + size), &pic->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), &pic->huffman_table.table[i].num_ac_codes, 16);
|
||||
size += 16;
|
||||
memcpy((buf + size), &pic->huffman_table.table[i].ac_values, 162);
|
||||
size += 162;
|
||||
}
|
||||
|
||||
bs = (uint16_t*)&buf[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*)&buf[size++];
|
||||
*bs = util_bswap16(pic->picture_parameter.picture_height);
|
||||
size++;
|
||||
|
||||
bs = (uint16_t*)&buf[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*)&buf[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*)&buf[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 < num_buffers; ++i) {
|
||||
struct rvid_buffer *buf = &dec->bs_buffers[dec->cur_buffer];
|
||||
unsigned new_size = dec->bs_size + sizes[i];
|
||||
|
||||
if (format == PIPE_VIDEO_FORMAT_JPEG)
|
||||
new_size += 2; /* save for EOI */
|
||||
|
||||
if (new_size > buf->res->buf->size) {
|
||||
dec->ws->buffer_unmap(buf->res->buf);
|
||||
if (!rvid_resize_buffer(dec->screen, dec->cs, buf, new_size)) {
|
||||
@@ -1055,6 +1184,13 @@ static void ruvd_decode_bitstream(struct pipe_video_codec *decoder,
|
||||
dec->bs_size += sizes[i];
|
||||
dec->bs_ptr += sizes[i];
|
||||
}
|
||||
|
||||
if (format == PIPE_VIDEO_FORMAT_JPEG) {
|
||||
((uint8_t *)dec->bs_ptr)[0] = 0xff; /* EOI */
|
||||
((uint8_t *)dec->bs_ptr)[1] = 0xd9;
|
||||
dec->bs_size += 2;
|
||||
dec->bs_ptr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user