From: Boyuan Zhang <boyuan.zh...@amd.com> Signed-off-by: Boyuan Zhang <boyuan.zh...@amd.com> --- src/gallium/drivers/radeon/radeon_vcn_jpeg.c | 286 ++++++++++++++++++++++++++- 1 file changed, 281 insertions(+), 5 deletions(-)
diff --git a/src/gallium/drivers/radeon/radeon_vcn_jpeg.c b/src/gallium/drivers/radeon/radeon_vcn_jpeg.c index c078131..72dff57 100644 --- a/src/gallium/drivers/radeon/radeon_vcn_jpeg.c +++ b/src/gallium/drivers/radeon/radeon_vcn_jpeg.c @@ -63,12 +63,195 @@ struct radeon_jpeg_decoder { unsigned dt_chroma_top_offset; }; +static void radeon_jpeg_destroy_associated_data(void *data) +{ + /* NOOP, since we only use an intptr */ +} + +static struct pb_buffer *radeon_jpeg_get_decode_param(struct radeon_jpeg_decoder *dec, + struct pipe_video_buffer *target, + struct pipe_picture_desc *picture) +{ + struct r600_texture *luma = (struct r600_texture *) + ((struct vl_video_buffer *)target)->resources[0]; + struct r600_texture *chroma = (struct r600_texture *) + ((struct vl_video_buffer *)target)->resources[1]; + + dec->bsd_size = align(dec->bs_size, 128); + dec->dt_luma_top_offset = luma->surface.u.gfx9.surf_offset; + if (target->buffer_format == PIPE_FORMAT_NV12) { + dec->dt_chroma_top_offset = chroma->surface.u.gfx9.surf_offset; + dec->dt_pitch = luma->surface.u.gfx9.surf_pitch * luma->surface.blk_w; + } + else if (target->buffer_format == PIPE_FORMAT_YUYV) + dec->dt_pitch = luma->surface.u.gfx9.surf_pitch; + dec->dt_uv_pitch = dec->dt_pitch / 2; + + return luma->resource.buf; +} + +static void get_mjpeg_slice_header(struct radeon_jpeg_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[i], 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; + + /* DRI */ + if (pic->slice_parameter.restart_interval) { + buf[size++] = 0xff; + buf[size++] = 0xdd; + buf[size++] = 0x00; + buf[size++] = 0x04; + bs = (uint16_t*)&buf[size++]; + *bs = util_bswap16(pic->slice_parameter.restart_interval); + 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; +} + /* flush IB to the hardware */ static int flush(struct radeon_jpeg_decoder *dec, unsigned flags) { return dec->ws->cs_flush(dec->cs, flags, NULL); } +/* add a new set register command to the IB */ +static void set_reg_jpeg(struct radeon_jpeg_decoder *dec, unsigned reg, + unsigned cond, unsigned type, uint32_t val) +{ + /* TODO */ +} + +/* send a bitstream buffer command */ +static void send_cmd_bitstream(struct radeon_jpeg_decoder *dec, + struct pb_buffer* buf, uint32_t off, + enum radeon_bo_usage usage, enum radeon_bo_domain domain) +{ + /* TODO */ +} + +/* send a target buffer command */ +static void send_cmd_target(struct radeon_jpeg_decoder *dec, + struct pb_buffer* buf, uint32_t off, + enum radeon_bo_usage usage, enum radeon_bo_domain domain) +{ + /* TODO */ +} + /* cycle to the next set of buffers */ static void next_buffer(struct radeon_jpeg_decoder *dec) { @@ -81,7 +264,20 @@ static void next_buffer(struct radeon_jpeg_decoder *dec) */ static void radeon_jpeg_destroy(struct pipe_video_codec *decoder) { - /* TODO */ + struct radeon_jpeg_decoder *dec = (struct radeon_jpeg_decoder*)decoder; + unsigned i; + + assert(decoder); + + flush(dec, 0); + + dec->ws->cs_destroy(dec->cs); + + for (i = 0; i < NUM_BUFFERS; ++i) { + si_vid_destroy_buffer(&dec->bs_buffers[i]); + } + + FREE(dec); } /** @@ -91,7 +287,19 @@ static void radeon_jpeg_begin_frame(struct pipe_video_codec *decoder, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) { - /* TODO */ + struct radeon_jpeg_decoder *dec = (struct radeon_jpeg_decoder*)decoder; + uintptr_t frame; + + assert(decoder); + + frame = ++dec->frame_number; + vl_video_buffer_set_associated_data(target, decoder, (void *)frame, + &radeon_jpeg_destroy_associated_data); + + dec->bs_size = 0; + dec->bs_ptr = dec->ws->buffer_map( + dec->bs_buffers[dec->cur_buffer].res->buf, + dec->cs, PIPE_TRANSFER_WRITE); } /** @@ -103,7 +311,8 @@ static void radeon_jpeg_decode_macroblock(struct pipe_video_codec *decoder, const struct pipe_macroblock *macroblocks, unsigned num_macroblocks) { - /* TODO */ + /* not supported (yet) */ + assert(0); } /** @@ -116,7 +325,51 @@ static void radeon_jpeg_decode_bitstream(struct pipe_video_codec *decoder, const void * const *buffers, const unsigned *sizes) { - /* TODO */ + struct radeon_jpeg_decoder *dec = (struct radeon_jpeg_decoder*)decoder; + enum pipe_video_format format = u_reduce_video_profile(picture->profile); + unsigned i; + + assert(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 (!si_vid_resize_buffer(dec->screen, dec->cs, buf, new_size)) { + RVID_ERR("Can't resize bitstream buffer!"); + return; + } + + dec->bs_ptr = dec->ws->buffer_map(buf->res->buf, dec->cs, + PIPE_TRANSFER_WRITE); + if (!dec->bs_ptr) + return; + + dec->bs_ptr += dec->bs_size; + } + + memcpy(dec->bs_ptr, buffers[i], sizes[i]); + 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; + } } /** @@ -126,7 +379,30 @@ static void radeon_jpeg_end_frame(struct pipe_video_codec *decoder, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) { - /* TODO */ + struct radeon_jpeg_decoder *dec = (struct radeon_jpeg_decoder*)decoder; + struct pb_buffer *dt; + struct rvid_buffer *bs_buf; + + assert(decoder); + + if (!dec->bs_ptr) + return; + + bs_buf = &dec->bs_buffers[dec->cur_buffer]; + + memset(dec->bs_ptr, 0, align(dec->bs_size, 128) - dec->bs_size); + dec->ws->buffer_unmap(bs_buf->res->buf); + + dt = radeon_jpeg_get_decode_param(dec, target, picture); + + send_cmd_bitstream(dec, bs_buf->res->buf, + 0, RADEON_USAGE_READ, RADEON_DOMAIN_GTT); + send_cmd_target(dec, dt, 0, + RADEON_USAGE_WRITE, RADEON_DOMAIN_VRAM); + + flush(dec, PIPE_FLUSH_ASYNC); + + next_buffer(dec); } /** -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev