radeon/vcn: add common encode part
authorBoyuan Zhang <boyuan.zhang@amd.com>
Wed, 8 Nov 2017 16:17:15 +0000 (11:17 -0500)
committerLeo Liu <leo.liu@amd.com>
Fri, 17 Nov 2017 17:25:47 +0000 (12:25 -0500)
Add a skeleton pipe video interface and encode ib interface for video encode
on vcn hardware. Add function defines and structures for vcn encode. Update
Makefile.sources and meson.build with newly added files.

Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
src/gallium/drivers/radeon/Makefile.sources
src/gallium/drivers/radeon/meson.build
src/gallium/drivers/radeon/radeon_vcn_enc.c [new file with mode: 0644]
src/gallium/drivers/radeon/radeon_vcn_enc.h
src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c [new file with mode: 0644]

index 22de12973815b81b37d9757ba1210a4f9e77baa7..ebb194ccf974c3f486ecf8c245781f073154e8a3 100644 (file)
@@ -13,6 +13,9 @@ C_SOURCES := \
        radeon_uvd.h \
        radeon_vcn_dec.c \
        radeon_vcn_dec.h \
+       radeon_vcn_enc_1_2.c \
+       radeon_vcn_enc.c \
+       radeon_vcn_enc.h \
        radeon_vce_40_2_2.c \
        radeon_vce_50.c \
        radeon_vce_52.c \
index f378b12e8e8509fa66d86e530bead86ef51d2cd0..561fd286319145347c5e93897f07fc0ebdbb4480 100644 (file)
@@ -31,6 +31,9 @@ files_libradeon = files(
   'r600_texture.c',
   'radeon_uvd.c',
   'radeon_uvd.h',
+  'radeon_vcn_enc_1_2.c',
+  'radeon_vcn_enc.c',
+  'radeon_vcn_enc.h',
   'radeon_vcn_dec.c',
   'radeon_vcn_dec.h',
   'radeon_vce_40_2_2.c',
diff --git a/src/gallium/drivers/radeon/radeon_vcn_enc.c b/src/gallium/drivers/radeon/radeon_vcn_enc.c
new file mode 100644 (file)
index 0000000..48ff8db
--- /dev/null
@@ -0,0 +1,164 @@
+/**************************************************************************
+ *
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+
+#include "pipe/p_video_codec.h"
+
+#include "util/u_video.h"
+#include "util/u_memory.h"
+
+#include "vl/vl_video_buffer.h"
+
+#include "r600_pipe_common.h"
+#include "radeon_video.h"
+#include "radeon_vcn_enc.h"
+
+static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_h264_enc_picture_desc *pic)
+{
+       enc->enc_pic.picture_type = pic->picture_type;
+       enc->enc_pic.frame_num = pic->frame_num;
+       enc->enc_pic.pic_order_cnt = pic->pic_order_cnt;
+       enc->enc_pic.pic_order_cnt_type = pic->pic_order_cnt_type;
+       enc->enc_pic.ref_idx_l0 = pic->ref_idx_l0;
+       enc->enc_pic.ref_idx_l1 = pic->ref_idx_l1;
+       enc->enc_pic.not_referenced = pic->not_referenced;
+       enc->enc_pic.is_idr = pic->is_idr;
+       enc->enc_pic.crop_left = 0;
+       enc->enc_pic.crop_right = (align(enc->base.width, 16) - enc->base.width) / 2;
+       enc->enc_pic.crop_top = 0;
+       enc->enc_pic.crop_bottom = (align(enc->base.height, 16) - enc->base.height) / 2;
+}
+
+static void flush(struct radeon_encoder *enc)
+{
+       enc->ws->cs_flush(enc->cs, RADEON_FLUSH_ASYNC, NULL);
+}
+
+static void radeon_enc_flush(struct pipe_video_codec *encoder)
+{
+       struct radeon_encoder *enc = (struct radeon_encoder*)encoder;
+       flush(enc);
+}
+
+static void radeon_enc_cs_flush(void *ctx, unsigned flags,
+                                                               struct pipe_fence_handle **fence)
+{
+       // just ignored
+}
+
+static unsigned get_cpb_num(struct radeon_encoder *enc)
+{
+       unsigned w = align(enc->base.width, 16) / 16;
+       unsigned h = align(enc->base.height, 16) / 16;
+       unsigned dpb;
+
+       switch (enc->base.level) {
+       case 10:
+               dpb = 396;
+               break;
+       case 11:
+               dpb = 900;
+               break;
+       case 12:
+       case 13:
+       case 20:
+               dpb = 2376;
+               break;
+       case 21:
+               dpb = 4752;
+               break;
+       case 22:
+       case 30:
+               dpb = 8100;
+               break;
+       case 31:
+               dpb = 18000;
+               break;
+       case 32:
+               dpb = 20480;
+               break;
+       case 40:
+       case 41:
+               dpb = 32768;
+               break;
+       case 42:
+               dpb = 34816;
+               break;
+       case 50:
+               dpb = 110400;
+               break;
+       default:
+       case 51:
+       case 52:
+               dpb = 184320;
+               break;
+       }
+
+       return MIN2(dpb / (w * h), 16);
+}
+
+static void radeon_enc_begin_frame(struct pipe_video_codec *encoder,
+                                                        struct pipe_video_buffer *source,
+                                                        struct pipe_picture_desc *picture)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_encode_bitstream(struct pipe_video_codec *encoder,
+                                                                 struct pipe_video_buffer *source,
+                                                                 struct pipe_resource *destination,
+                                                                 void **fb)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_end_frame(struct pipe_video_codec *encoder,
+                                                  struct pipe_video_buffer *source,
+                                                  struct pipe_picture_desc *picture)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_destroy(struct pipe_video_codec *encoder)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_get_feedback(struct pipe_video_codec *encoder,
+                                                         void *feedback, unsigned *size)
+{
+       /* TODO*/
+}
+
+struct pipe_video_codec *radeon_create_encoder(struct pipe_context *context,
+               const struct pipe_video_codec *templ,
+               struct radeon_winsys* ws,
+               radeon_enc_get_buffer get_buffer)
+{
+       /* TODO*/
+}
index f9fa16877d4593975da7375ee84a4c7c86a3189d..fe61419e301014aa46403a29602e05e8fd30d07c 100644 (file)
@@ -322,4 +322,86 @@ typedef struct rvcn_enc_feedback_buffer_s
     uint32_t   feedback_data_size;
 } rvcn_enc_feedback_buffer_t;
 
+typedef void (*radeon_enc_get_buffer)(struct pipe_resource *resource,
+               struct pb_buffer **handle,
+               struct radeon_surf **surface);
+
+struct pipe_video_codec *radeon_create_encoder(struct pipe_context *context,
+               const struct pipe_video_codec *templat,
+               struct radeon_winsys* ws,
+               radeon_enc_get_buffer get_buffer);
+
+struct radeon_enc_h264_enc_pic {
+       enum    pipe_h264_enc_picture_type picture_type;
+
+       unsigned        frame_num;
+       unsigned        pic_order_cnt;
+       unsigned        pic_order_cnt_type;
+       unsigned        ref_idx_l0;
+       unsigned        ref_idx_l1;
+       unsigned        crop_left;
+       unsigned        crop_right;
+       unsigned        crop_top;
+       unsigned        crop_bottom;
+
+       bool    not_referenced;
+       bool    is_idr;
+
+       rvcn_enc_task_info_t    task_info;
+       rvcn_enc_session_init_t session_init;
+       rvcn_enc_layer_control_t        layer_ctrl;
+       rvcn_enc_layer_select_t layer_sel;
+       rvcn_enc_h264_slice_control_t   slice_ctrl;
+       rvcn_enc_h264_spec_misc_t       spec_misc;
+       rvcn_enc_rate_ctl_session_init_t        rc_session_init;
+       rvcn_enc_rate_ctl_layer_init_t  rc_layer_init;
+       rvcn_enc_h264_encode_params_t   h264_enc_params;
+       rvcn_enc_h264_deblocking_filter_t       h264_deblock;
+       rvcn_enc_rate_ctl_per_picture_t rc_per_pic;
+       rvcn_enc_quality_params_t       quality_params;
+       rvcn_enc_encode_context_buffer_t        ctx_buf;
+       rvcn_enc_video_bitstream_buffer_t       bit_buf;
+       rvcn_enc_feedback_buffer_t      fb_buf;
+       rvcn_enc_intra_refresh_t        intra_ref;
+       rvcn_enc_encode_params_t        enc_params;
+};
+
+struct radeon_encoder {
+       struct pipe_video_codec         base;
+
+       void (*begin)(struct radeon_encoder *enc, struct pipe_h264_enc_picture_desc *pic);
+       void (*encode)(struct radeon_encoder *enc);
+       void (*destroy)(struct radeon_encoder *enc);
+
+       unsigned                        stream_handle;
+
+       struct pipe_screen              *screen;
+       struct radeon_winsys*           ws;
+       struct radeon_winsys_cs*        cs;
+
+       radeon_enc_get_buffer                   get_buffer;
+
+       struct pb_buffer*       handle;
+       struct radeon_surf*             luma;
+       struct radeon_surf*             chroma;
+
+       struct pb_buffer*       bs_handle;
+       unsigned                        bs_size;
+
+       unsigned                        cpb_num;
+
+       struct rvid_buffer              *si;
+       struct rvid_buffer              *fb;
+       struct rvid_buffer              cpb;
+       struct radeon_enc_h264_enc_pic  enc_pic;
+
+       unsigned                        alignment;
+       uint32_t                        total_task_size;
+       uint32_t*                       p_task_size;
+
+       bool                            need_feedback;
+};
+
+void radeon_enc_1_2_init(struct radeon_encoder *enc);
+
 #endif  // _RADEON_VCN_ENC_H
diff --git a/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c b/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c
new file mode 100644 (file)
index 0000000..ffd1155
--- /dev/null
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+
+#include "pipe/p_video_codec.h"
+
+#include "util/u_video.h"
+#include "util/u_memory.h"
+
+#include "vl/vl_video_buffer.h"
+
+#include "r600_pipe_common.h"
+#include "radeon_video.h"
+#include "radeon_vcn_enc.h"
+
+#define RADEON_ENC_CS(value) (enc->cs->current.buf[enc->cs->current.cdw++] = (value))
+#define RADEON_ENC_BEGIN(cmd) { \
+       uint32_t *begin = &enc->cs->current.buf[enc->cs->current.cdw++]; \
+RADEON_ENC_CS(cmd)
+#define RADEON_ENC_READ(buf, domain, off) radeon_enc_add_buffer(enc, (buf), RADEON_USAGE_READ, (domain), (off))
+#define RADEON_ENC_WRITE(buf, domain, off) radeon_enc_add_buffer(enc, (buf), RADEON_USAGE_WRITE, (domain), (off))
+#define RADEON_ENC_READWRITE(buf, domain, off) radeon_enc_add_buffer(enc, (buf), RADEON_USAGE_READWRITE, (domain), (off))
+#define RADEON_ENC_END() *begin = (&enc->cs->current.buf[enc->cs->current.cdw] - begin) * 4; \
+       enc->total_task_size += *begin;}
+
+static const unsigned profiles[7] = { 66, 77, 88, 100, 110, 122, 244 };
+
+static void radeon_enc_add_buffer(struct radeon_encoder *enc, struct pb_buffer *buf,
+                                                                 enum radeon_bo_usage usage, enum radeon_bo_domain domain,
+                                                                 signed offset)
+{
+       enc->ws->cs_add_buffer(enc->cs, buf, usage | RADEON_USAGE_SYNCHRONIZED,
+                                                                          domain, RADEON_PRIO_VCE);
+       uint64_t addr;
+       addr = enc->ws->buffer_get_virtual_address(buf);
+       addr = addr + offset;
+       RADEON_ENC_CS(addr >> 32);
+       RADEON_ENC_CS(addr);
+}
+
+static void radeon_enc_session_info(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_task_info(struct radeon_encoder *enc, bool need_feedback)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_session_init(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_layer_control(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_layer_select(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_slice_control(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_spec_misc(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_rc_session_init(struct radeon_encoder *enc, struct pipe_h264_enc_picture_desc *pic)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_rc_layer_init(struct radeon_encoder *enc, struct pipe_h264_enc_picture_desc *pic)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_deblocking_filter_h264(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_quality_params(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_ctx(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_bitstream(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_feedback(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_intra_refresh(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_rc_per_pic(struct radeon_encoder *enc, struct pipe_h264_enc_picture_desc *pic)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_encode_params(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+static void radeon_enc_encode_params_h264(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_op_init(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_op_close(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_op_enc(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_op_init_rc(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_op_init_rc_vbv(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void radeon_enc_op_speed(struct radeon_encoder *enc)
+{
+       /* TODO*/
+}
+
+static void begin(struct radeon_encoder *enc, struct pipe_h264_enc_picture_desc *pic)
+{
+       radeon_enc_session_info(enc);
+       enc->total_task_size = 0;
+       radeon_enc_task_info(enc, enc->need_feedback);
+       radeon_enc_op_init(enc);
+       radeon_enc_session_init(enc);
+       radeon_enc_layer_control(enc);
+       radeon_enc_slice_control(enc);
+       radeon_enc_spec_misc(enc);
+       radeon_enc_rc_session_init(enc, pic);
+       radeon_enc_deblocking_filter_h264(enc);
+       radeon_enc_quality_params(enc);
+       radeon_enc_layer_select(enc);
+       radeon_enc_rc_layer_init(enc, pic);
+       radeon_enc_layer_select(enc);
+       radeon_enc_rc_per_pic(enc, pic);
+       radeon_enc_op_init_rc(enc);
+       radeon_enc_op_init_rc_vbv(enc);
+       *enc->p_task_size = (enc->total_task_size);
+}
+
+static void encode(struct radeon_encoder *enc)
+{
+       radeon_enc_session_info(enc);
+       enc->total_task_size = 0;
+       radeon_enc_task_info(enc, enc->need_feedback);
+       radeon_enc_ctx(enc);
+       radeon_enc_bitstream(enc);
+       radeon_enc_feedback(enc);
+       radeon_enc_intra_refresh(enc);
+       radeon_enc_encode_params(enc);
+       radeon_enc_encode_params_h264(enc);
+       radeon_enc_op_speed(enc);
+       radeon_enc_op_enc(enc);
+       *enc->p_task_size = (enc->total_task_size);
+}
+
+static void destroy(struct radeon_encoder *enc)
+{
+       radeon_enc_session_info(enc);
+       enc->total_task_size = 0;
+       radeon_enc_task_info(enc, enc->need_feedback);
+       radeon_enc_op_close(enc);
+       *enc->p_task_size = (enc->total_task_size);
+}
+
+void radeon_enc_1_2_init(struct radeon_encoder *enc)
+{
+       enc->begin = begin;
+       enc->encode = encode;
+       enc->destroy = destroy;
+}