From fa5caae8f446f5be4c3f82cdff699196adeef1cf Mon Sep 17 00:00:00 2001 From: Alpha Lin <Alpha.Lin@rock-chips.com> Date: Mon, 17 Nov 2014 09:48:35 +0800 Subject: [PATCH] Rockchip: add VP8 encoder library. Convert the v4l2 pixel format to VPU HW pixel format. Add rate control and keyframe setting interface. BUG=chrome-os-partner:33728 TEST=video_encode_accelerator_unittest Change-Id: Ic4344a95a70c22178eff2a20420b57a41ccc84a6 Signed-off-by: Alpha Lin <Alpha.Lin@rock-chips.com> Reviewed-on: https://chromium-review.googlesource.com/230081 Reviewed-by: Wu-cheng Li <wuchengli@chromium.org> Commit-Queue: Wu-cheng Li <wuchengli@chromium.org> Tested-by: Wu-cheng Li <wuchengli@chromium.org> --- libv4l-rockchip/Makefile.am | 19 +- libv4l-rockchip/libv4l-encplugin-rockchip.c | 30 +- libv4l-rockchip/libvpu/rk_vepu.c | 83 +- libv4l-rockchip/libvpu/rk_vepu_debug.c | 5 + libv4l-rockchip/libvpu/rk_vepu_debug.h | 28 + .../libvpu/vp8_enc/encasiccontroller.c | 907 ++++++++++++++++++ .../libvpu/vp8_enc/encasiccontroller.h | 267 ++++++ .../libvpu/vp8_enc/encasiccontroller_v2.c | 80 ++ libv4l-rockchip/libvpu/vp8_enc/enccfg.h | 190 ++++ libv4l-rockchip/libvpu/vp8_enc/enccommon.h | 43 + .../libvpu/vp8_enc/encswhwregisters.h | 527 ++++++++++ libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c | 735 ++++++++++++++ libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.h | 56 ++ libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.c | 479 +++++++++ libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.h | 50 + libv4l-rockchip/libvpu/vp8_enc/vp8encapi.c | 651 +++++++++++++ libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h | 449 +++++++++ libv4l-rockchip/libvpu/vp8_enc/vp8entropy.c | 530 ++++++++++ libv4l-rockchip/libvpu/vp8_enc/vp8entropy.h | 32 + .../libvpu/vp8_enc/vp8entropytable.h | 697 ++++++++++++++ .../libvpu/vp8_enc/vp8entropytools.h | 45 + libv4l-rockchip/libvpu/vp8_enc/vp8header.c | 378 ++++++++ libv4l-rockchip/libvpu/vp8_enc/vp8header.h | 24 + libv4l-rockchip/libvpu/vp8_enc/vp8init.c | 304 ++++++ libv4l-rockchip/libvpu/vp8_enc/vp8init.h | 27 + libv4l-rockchip/libvpu/vp8_enc/vp8instance.h | 77 ++ .../libvpu/vp8_enc/vp8macroblocktools.c | 72 ++ .../libvpu/vp8_enc/vp8macroblocktools.h | 54 ++ .../libvpu/vp8_enc/vp8picparameterset.c | 38 + .../libvpu/vp8_enc/vp8picparameterset.h | 54 ++ .../libvpu/vp8_enc/vp8picturebuffer.c | 277 ++++++ .../libvpu/vp8_enc/vp8picturebuffer.h | 70 ++ libv4l-rockchip/libvpu/vp8_enc/vp8putbits.c | 164 ++++ libv4l-rockchip/libvpu/vp8_enc/vp8putbits.h | 46 + .../libvpu/vp8_enc/vp8quanttable.h | 92 ++ .../libvpu/vp8_enc/vp8ratecontrol.c | 673 +++++++++++++ .../libvpu/vp8_enc/vp8ratecontrol.h | 95 ++ .../libvpu/vp8_enc/vp8seqparameterset.h | 53 + libv4l-rockchip/libvpu/vp8_enc/vpu_mem.c | 27 + libv4l-rockchip/libvpu/vp8_enc/vpu_mem.h | 21 + 40 files changed, 8416 insertions(+), 33 deletions(-) create mode 100644 libv4l-rockchip/libvpu/rk_vepu_debug.c create mode 100644 libv4l-rockchip/libvpu/rk_vepu_debug.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/encasiccontroller_v2.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/enccfg.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/enccommon.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/encswhwregisters.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8encapi.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8entropy.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8entropy.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8entropytable.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8entropytools.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8header.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8header.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8init.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8init.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8instance.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8putbits.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8putbits.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8quanttable.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vp8seqparameterset.h create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vpu_mem.c create mode 100644 libv4l-rockchip/libvpu/vp8_enc/vpu_mem.h diff --git a/libv4l-rockchip/Makefile.am b/libv4l-rockchip/Makefile.am index 2016e60..fe45119 100644 --- a/libv4l-rockchip/Makefile.am +++ b/libv4l-rockchip/Makefile.am @@ -6,7 +6,24 @@ if WITH_V4L_PLUGINS libv4l2plugin_LTLIBRARIES = libv4l-encplugin-rockchip.la endif -libv4l_encplugin_rockchip_la_SOURCES = libv4l-encplugin-rockchip.c libvpu/rk_vepu.c +libv4l_encplugin_rockchip_la_SOURCES = \ + libv4l-encplugin-rockchip.c \ + libvpu/rk_vepu.c \ + libvpu/rk_vepu_debug.c \ + libvpu/vp8_enc/encasiccontroller.c \ + libvpu/vp8_enc/encasiccontroller_v2.c \ + libvpu/vp8_enc/rk_vp8encapi.c \ + libvpu/vp8_enc/vp8codeframe.c \ + libvpu/vp8_enc/vp8encapi.c \ + libvpu/vp8_enc/vp8entropy.c \ + libvpu/vp8_enc/vp8header.c \ + libvpu/vp8_enc/vp8init.c \ + libvpu/vp8_enc/vp8macroblocktools.c \ + libvpu/vp8_enc/vp8picparameterset.c \ + libvpu/vp8_enc/vp8picturebuffer.c \ + libvpu/vp8_enc/vp8putbits.c \ + libvpu/vp8_enc/vp8ratecontrol.c \ + libvpu/vp8_enc/vpu_mem.c libv4l_encplugin_rockchip_la_CPPFLAGS = $(CFLAG_VISIBILITY) libv4l_encplugin_rockchip_la_LDFLAGS = -avoid-version -module -shared -export-dynamic libv4l_encplugin_rockchip_la_LIBADD = -lpthread diff --git a/libv4l-rockchip/libv4l-encplugin-rockchip.c b/libv4l-rockchip/libv4l-encplugin-rockchip.c index 2921c14..4a7be00 100644 --- a/libv4l-rockchip/libv4l-encplugin-rockchip.c +++ b/libv4l-rockchip/libv4l-encplugin-rockchip.c @@ -16,6 +16,7 @@ #include <sys/syscall.h> #include "config.h" /* For HAVE_VISIBILITY */ #include "libv4l-plugin.h" +#include "libvpu/rk_vepu_debug.h" #include "libvpu/rk_vepu_interface.h" #define VLOG(log_level, str, ...) ((g_log_level >= log_level) ? \ @@ -158,12 +159,7 @@ static int qbuf_if_pending_buffer_exists_locked(struct encoder_context *ctx, static int initialize_libvpu(struct encoder_context *ctx, int fd); /* Return the string represenation of a libv4l command for debugging. */ static const char *v4l_cmd2str(unsigned long int cmd); -/* - * The current log level for VLOG. This is read from environment variable - * LIBV4L_PLUGIN_LOG_LEVEL every time plugin_init is called. - */ -static int g_log_level = 0; -/* Get the log level from the environment variable. */ +/* Get the log level from the environment variable LIBV4L_PLUGIN_LOG_LEVEL. */ static void get_log_level(); static pthread_once_t g_get_log_level_once = PTHREAD_ONCE_INIT; @@ -495,7 +491,7 @@ bool is_rockchip_encoder(int fd) { int ret = SYS_IOCTL(fd, VIDIOC_QUERYCAP, &cap); if (ret) return false; - return strcmp(RK3288_VPU_NAME, cap.driver) == 0; + return strcmp(RK3288_VPU_NAME, (const char *)cap.driver) == 0; } int set_encoder_config_locked(struct encoder_context *ctx, int fd, @@ -556,25 +552,33 @@ static int initialize_libvpu(struct encoder_context *ctx, int fd) struct rk_vepu_init_param init_param; memset(&init_param, 0, sizeof(init_param)); + /* Get the input format. */ struct v4l2_format format; memset(&format, 0, sizeof(format)); format.type = ctx->output_streamon_type; int ret = SYS_IOCTL(fd, VIDIOC_G_FMT, &format); - if (ret) { + if (ret) return ret; - } - init_param.width = format.fmt.pix_mp.width; - init_param.height = format.fmt.pix_mp.height; init_param.input_format = format.fmt.pix_mp.pixelformat; + /* Get the output format. */ memset(&format, 0, sizeof(format)); format.type = ctx->capture_streamon_type; ret = SYS_IOCTL(fd, VIDIOC_G_FMT, &format); - if (ret) { + if (ret) return ret; - } init_param.output_format = format.fmt.pix_mp.pixelformat; + /* Get the cropped size. */ + struct v4l2_crop crop; + memset(&crop, 0, sizeof(crop)); + crop.type = ctx->output_streamon_type; + ret = SYS_IOCTL(fd, VIDIOC_G_CROP, &crop); + if (ret) + return ret; + init_param.width = crop.c.width; + init_param.height = crop.c.height; + /* * If the encoder library has initialized and parameters have not * changed, skip the initialization. diff --git a/libv4l-rockchip/libvpu/rk_vepu.c b/libv4l-rockchip/libvpu/rk_vepu.c index a30e4c7..f3d34f7 100644 --- a/libv4l-rockchip/libvpu/rk_vepu.c +++ b/libv4l-rockchip/libvpu/rk_vepu.c @@ -1,47 +1,92 @@ -/* +/* Copyright 2014 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "libvpu/rk_vepu_interface.h" +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> #include <stdlib.h> -#define NUM_CTRLS 3 +#include "libvpu/rk_vepu_debug.h" +#include "vp8_enc/rk_vp8encapi.h" -static uint32_t rk_ctrl_ids[NUM_CTRLS] = { - V4L2_CID_PRIVATE_RK3288_HEADER, - V4L2_CID_PRIVATE_RK3288_REG_PARAMS, - V4L2_CID_PRIVATE_RK3288_HW_PARAMS -}; -static uint32_t rk_payloads[NUM_CTRLS] = {0}; -static uint32_t rk_payload_sizes[NUM_CTRLS] = { - sizeof(rk_payloads[0]), sizeof(rk_payloads[1]), sizeof(rk_payloads[2]) -}; +void *rk_vepu_init(struct rk_vepu_init_param *param) { + int retval; + struct rk_vp8_encoder *enc = rk_vp8_encoder_alloc_ctx(); -void *rk_vepu_init(struct rk_vepu_init_param *init_param) { - return malloc(sizeof(int)); + assert(param != NULL); + if (enc == NULL) { + VPU_PLG_ERR("Allocate encoder instance failed\n"); + return NULL; + } + + enc->rk_ctrl_ids[0] = V4L2_CID_PRIVATE_RK3288_HEADER; + enc->rk_ctrl_ids[1] = V4L2_CID_PRIVATE_RK3288_REG_PARAMS; + enc->rk_ctrl_ids[2] = V4L2_CID_PRIVATE_RK3288_HW_PARAMS; + + retval = enc->ops->init(enc, param); + if (retval < 0) { + VPU_PLG_ERR("Encoder initialize failed\n"); + rk_vp8_encoder_free_ctx(enc); + return NULL; + } + return enc; } void rk_vepu_deinit(void *enc) { - free(enc); + struct rk_vp8_encoder *ienc = (struct rk_vp8_encoder*)enc; + + assert(enc != NULL); + ienc->ops->deinit(ienc); + rk_vp8_encoder_free_ctx(ienc); } int rk_vepu_get_config(void *enc, size_t *num_ctrls, uint32_t **ctrl_ids, - void ***payloads, uint32_t **payload_sizes) { + void ***payloads, uint32_t **payload_sizes) +{ + int retval; + struct rk_vp8_encoder *ienc = (struct rk_vp8_encoder*)enc; + + assert(enc != NULL && num_ctrls != NULL && ctrl_ids != NULL); + assert(payloads != NULL && payload_sizes != NULL); + + retval = ienc->ops->before_encode(ienc); + if (retval < 0) { + VPU_PLG_ERR("Generate configuration failed\n"); + return -1; + } + *num_ctrls = NUM_CTRLS; - *ctrl_ids = rk_ctrl_ids; - *payloads = (void **)rk_payloads; - *payload_sizes = rk_payload_sizes; + *ctrl_ids = ienc->rk_ctrl_ids; + *payloads = (void **)ienc->rk_payloads; + *payload_sizes = ienc->rk_payload_sizes; return 0; } int rk_vepu_update_config(void *enc, void *config, uint32_t config_size, uint32_t buffer_size) { - return 0; + int retval; + struct rk_vp8_encoder *ienc = (struct rk_vp8_encoder*)enc; + + assert(enc != NULL && config != NULL); + + retval = ienc->ops->updatepriv(ienc, config, config_size); + if (retval < 0) { + VPU_PLG_ERR("Update vp8 encoder private data failed\n"); + return -1; + } + return ienc->ops->after_encode(ienc, buffer_size); } int rk_vepu_update_parameter(void *enc, struct rk_vepu_runtime_param *runtime_param) { + struct rk_vp8_encoder *ienc = (struct rk_vp8_encoder*)enc; + + assert(enc != NULL && runtime_param != NULL); + ienc->ops->updateparameter(ienc, runtime_param); return 0; } diff --git a/libv4l-rockchip/libvpu/rk_vepu_debug.c b/libv4l-rockchip/libvpu/rk_vepu_debug.c new file mode 100644 index 0000000..885ef0e --- /dev/null +++ b/libv4l-rockchip/libvpu/rk_vepu_debug.c @@ -0,0 +1,5 @@ +/* Copyright 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +int g_log_level = 0; diff --git a/libv4l-rockchip/libvpu/rk_vepu_debug.h b/libv4l-rockchip/libvpu/rk_vepu_debug.h new file mode 100644 index 0000000..0362111 --- /dev/null +++ b/libv4l-rockchip/libvpu/rk_vepu_debug.h @@ -0,0 +1,28 @@ +/* Copyright 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef LIBVPU_RK_VEPU_DEBUG_H_ +#define LIBVPU_RK_VEPU_DEBUG_H_ + +#include <stdio.h> + +/* + * The current log level. Higher value will enable more logs. + */ +extern int g_log_level; + +#define VPU_PLG_DBG(fmt, args...) ((g_log_level >= 2) ? \ + (void) fprintf(stderr, "%s:%d: " fmt, __func__, __LINE__, ## args) \ + : (void) 0) + +#define VPU_PLG_INF(fmt, args...) ((g_log_level >= 1) ? \ + (void) fprintf(stderr, "%s:%d: " fmt, __func__, __LINE__, ## args) \ + : (void) 0) + +#define VPU_PLG_ERR(fmt, args...) ((g_log_level >= 0) ? \ + (void) fprintf(stderr, "ERR, %s:%d: " fmt, __func__, __LINE__, ## args) \ + : (void) 0) + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.c b/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.c new file mode 100644 index 0000000..cbb1319 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.c @@ -0,0 +1,907 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ +#include <memory.h> +#include <stdio.h> + +#include "enccommon.h" +#include "encasiccontroller.h" +#include "encswhwregisters.h" + +/* Mask fields */ +#define mask_2b (uint32_t)0x00000003 +#define mask_3b (uint32_t)0x00000007 +#define mask_4b (uint32_t)0x0000000F +#define mask_5b (uint32_t)0x0000001F +#define mask_6b (uint32_t)0x0000003F +#define mask_7b (uint32_t)0x0000007F +#define mask_11b (uint32_t)0x000007FF +#define mask_14b (uint32_t)0x00003FFF +#define mask_16b (uint32_t)0x0000FFFF + +/* NOTE: Don't use ',' in descriptions, because it is used as separator in csv + * parsing. */ +static const regField_s asicRegisterDesc[] = { +/* HW ID register, read-only */ + { HEncProductID, 0x000, 0xffff0000, 16, 0, "Product ID" }, + { HEncProductMajor, 0x000, 0x0000f000, 12, 0, "Major number" }, + { HEncProductMinor, 0x000, 0x00000ff0, 4, 0, "Minor number" }, + { HEncProductBuild, 0x000, 0x0000000f, 0, 0, "Build number defined in synthesis." }, +/* Encoder interrupt register */ + { HEncIRQSliceReady, 0x004, 0x00000100, 8, 0, "IRQ slice ready status bit." }, + { HEncIRQTimeout, 0x004, 0x00000040, 6, 0, "IRQ HW timeout status bit." }, + { HEncIRQBuffer, 0x004, 0x00000020, 5, 1, "IRQ buffer full status bit. bufferFullInterrupt" }, + { HEncIRQReset, 0x004, 0x00000010, 4, 0, "IRQ SW reset status bit." }, + { HEncIRQBusError, 0x004, 0x00000008, 3, 0, "IRQ bus error status bit." }, + { HEncIRQFrameReady, 0x004, 0x00000004, 2, 0, "IRQ frame ready status bit. Encoder has finished a frame." }, + { HEncIRQDisable, 0x004, 0x00000002, 1, 0, "IRQ disable. No interrupts from HW. SW must use polling." }, + { HEncIRQ, 0x004, 0x00000001, 0, 0, "HINTenc Interrupt from HW. SW resets at IRQ handler." }, +/* Encoder configuration register */ + { HEncAXIWriteID, 0x008, 0xff000000, 24, 0, "AXI Write ID" }, + { HEncAXIReadID, 0x008, 0x00ff0000, 16, 0, "AXI Read ID" }, + { HEncOutputSwap16, 0x008, 0x00008000, 15, 0, "Enable output swap 16-bits" }, + { HEncInputSwap16, 0x008, 0x00004000, 14, 0, "Enable input swap 16-bits" }, + { HEncBurstLength, 0x008, 0x00003f00, 8, 0, "Burst length. 0=incremental. 4=max BURST4.8=max BURST8. 16=max BURST16" }, + { HEncBurstDisable, 0x008, 0x00000080, 7, 0, "Disable burst mode for AXI" }, + { HEncBurstIncr, 0x008, 0x00000040, 6, 0, "Burst incremental. 1=INCR burst allowed. 0=use SINGLE burst" }, + { HEncDataDiscard, 0x008, 0x00000020, 5, 0, "Enable burst data discard. 2 or 3 long reads are using BURST4" }, + { HEncClockGating, 0x008, 0x00000010, 4, 0, "Enable clock gating" }, + { HEncOutputSwap32, 0x008, 0x00000008, 3, 0, "Enable output swap 32-bits" }, + { HEncInputSwap32, 0x008, 0x00000004, 2, 0, "Enable input swap 32-bits" }, + { HEncOutputSwap8, 0x008, 0x00000002, 1, 0, "Enable output swap 8-bits" }, + { HEncInputSwap8, 0x008, 0x00000001, 0, 0, "Enable input swap 8-bits" }, + { HEncTestCounter, 0x00c, 0xf0000000, 28, 0, "Test counter" }, + { HEncTestLength, 0x00c, 0x001ffff8, 3, 0, "Test data length for memory test" }, + { HEncTestMem, 0x00c, 0x00000004, 2, 0, "Enable memory coherency test. Reads BaseStream. Writes BaseControl" }, + { HEncTestReg, 0x00c, 0x00000002, 1, 0, "Enable register coherency test. Increments test counter" }, + { HEncTestIrq, 0x00c, 0x00000001, 0, 0, "Enable IRQ test. HW gives interrupt" }, +/* External memory base addresses for encoder input/output */ + { HEncBaseStream, 0x014, 0xffffffff, 0, 0, "Base address for output stream data" }, + { HEncBaseControl, 0x018, 0xffffffff, 0, 0, "Base address for output control data" }, + { HEncBaseRefLum, 0x01c, 0xffffffff, 0, 0, "Base address for reference luma" }, + { HEncBaseRefChr, 0x020, 0xffffffff, 0, 0, "Base address for reference chroma" }, + { HEncBaseRecLum, 0x024, 0xffffffff, 0, 0, "Base address for reconstructed luma" }, + { HEncBaseRecChr, 0x028, 0xffffffff, 0, 0, "Base address for reconstructed chroma" }, + { HEncBaseInLum, 0x02c, 0xffffffff, 0, 0, "Base address for input picture luma" }, + { HEncBaseInCb, 0x030, 0xffffffff, 0, 0, "Base address for input picture cb" }, + { HEncBaseInCr, 0x034, 0xffffffff, 0, 0, "Base address for input picture cr" }, + { HEncIntTimeout, 0x038, 0x80000000, 31, 0, "Enable interrupt for timeout" }, + { HEncMvWrite, 0x038, 0x40000000, 30, 1, "Enable writing MV and SAD of each MB to BaseMvWrite" }, + { HEncNalSizeWrite, 0x038, 0x20000000, 29, 1, "Enable writing size of each NAL unit to BaseControl, nalSizeWriteOut" }, + { HEncIntSliceReady, 0x038, 0x10000000, 28, 0, "Enable interrupt for slice ready" }, + { HEncWidth, 0x038, 0x0ff80000, 19, 1, "Encoded width. lumWidth (macroblocks) H264:[9..255] JPEG:[6..511]" }, + { HEncHeight, 0x038, 0x0007fc00, 10, 1, "Encoded height. lumHeight (macroblocks) H264:[6..255] JPEG:[2..511]" }, + { HEncRecWriteDisable, 0x038, 0x00000040, 6, 1, "Disable writing of reconstructed image. recWriteDisable" }, + { HEncPictureType, 0x038, 0x00000018, 3, 1, "Encoded picture type. frameType. 0=INTER. 1=INTRA(IDR). 2=MVC-INTER. 3=MVC-INTER(ref mod)." }, + { HEncEncodingMode, 0x038, 0x00000006, 1, 1, "Encoding mode. streamType. 1=VP8. 2=JPEG. 3=H264" }, + { HEncEnable, 0x038, 0x00000001, 0, 0, "Encoder enable" }, + { HEncChrOffset, 0x03c, 0xe0000000, 29, 0, "Input chrominance offset (bytes) [0..7]" }, + { HEncLumOffset, 0x03c, 0x1c000000, 26, 0, "Input luminance offset (bytes) [0..7]" }, + { HEncRowLength, 0x03c, 0x03fff000, 12, 1, "Input luminance row length. lumWidthSrc (bytes) [96..8192]" }, + { HEncXFill, 0x03c, 0x00000c00, 10, 0, "Overfill pixels on right edge of image div4 [0..3]" }, + { HEncYFill, 0x03c, 0x000003c0, 6, 1, "Overfill pixels on bottom edge of image. YFill. [0..15]" }, + { HEncInputFormat, 0x03c, 0x0000003c, 2, 1, "Input image format. inputFormat. YUV420P/YUV420SP/YUYV422/UYVY422/RGB565/RGB555/RGB444/RGB888/RGB101010" }, + { HEncInputRot, 0x03c, 0x00000003, 0, 1, "Input image rotation. 0=disabled. 1=90 degrees right. 2=90 degrees left" }, + +/* VP8 / H.264 mixed definitions */ + { HEncBaseRefLum2, 0x040, 0xffffffff, 0, 0, "Base address for second reference luma" }, + { HEncBaseRefChr2, 0x044, 0xffffffff, 0, 0, "Base address for second reference chroma" }, + { HEncPicInitQp, 0x040, 0xfc000000, 26, 0, "H.264 Pic init qp in PPS [0..51]" }, + { HEncSliceAlpha, 0x040, 0x03c00000, 22, 0, "H.264 Slice filter alpha c0 offset div2 [-6..6]" }, + { HEncSliceBeta, 0x040, 0x003c0000, 18, 0, "H.264 Slice filter beta offset div2 [-6..6]" }, + { HEncChromaQp, 0x040, 0x0003e000, 13, 0, "H.264 Chroma qp index offset [-12..12]" }, + { HEncIdrPicId, 0x040, 0x0000001e, 1, 0, "H.264 IDR picture ID" }, + { HEncConstrIP, 0x040, 0x00000001, 0, 1, "H.264 Constrained intra prediction enable. constIntraPred" }, + { HEncPPSID, 0x044, 0xff000000, 24, 0, "H.264 pic_parameter_set_id" }, + { HEncIPPrevModeFavor, 0x044, 0x00ff0000, 16, 0, "H.264 Intra prediction previous 4x4 mode favor" }, + { HEncFrameNum, 0x044, 0x0000ffff, 0, 0, "H.264 Frame num" }, + + { HEncDeblocking, 0x048, 0xc0000000, 30, 0, "Deblocking filter mode. 0=enabled. 1=disabled (vp8=simple). 2=disabled on slice borders" }, + { HEncSliceSize, 0x048, 0x3f800000, 23, 1, "H.264 Slice size. mbRowPerSlice (mb rows) [0..127] 0=one slice per picture" }, + { HEncDisableQPMV, 0x048, 0x00400000, 22, 1, "H.264 Disable quarter pixel MVs. disableQuarterPixelMv" }, + { HEncTransform8x8, 0x048, 0x00200000, 21, 1, "H.264 Transform 8x8 enable. High Profile H.264. transform8x8Mode" }, + { HEncCabacInitIdc, 0x048, 0x00180000, 19, 0, "H.264 CABAC initial IDC. [0..2]" }, + { HEncCabacEnable, 0x048, 0x00040000, 18, 1, "H.264 CABAC / VP8 boolenc enable. entropyCodingMode. 0=CAVLC (Baseline Profile H.264). 1=CABAC (Main Profile H.264)" }, + { HEncInter4Restrict, 0x048, 0x00020000, 17, 1, "H.264 Inter 4x4 mode restriction. restricted4x4Mode" }, + { HEncStreamMode, 0x048, 0x00010000, 16, 1, "H.264 Stream mode. byteStream. 0=NAL unit stream. 1=Byte stream" }, + { HEncIPIntra16Favor, 0x048, 0x0000ffff, 0, 0, "Intra prediction intra 16x16 mode favor" }, + { HEncSplitMv, 0x04c, 0x40000000, 30, 1, "Enable using more than 1 MV per macroblock." }, + { HEncDMVPenalty1p, 0x04c, 0x000003ff, 0, 1, "Differential MV penalty for 1p ME. DMVPenalty1p" }, + { HEncDMVPenalty4p, 0x04c, 0x000ffc00, 10, 1, "Differential MV penalty for 4p ME. DMVPenalty4p" }, + { HEncDMVPenaltyQp, 0x04c, 0x3ff00000, 20, 1, "Differential MV penalty for 1/4p ME. DMVPenaltyQp" }, + +/* Mixed definitions JPEG / video */ + { HEncJpegMode, 0x050, 0x02000000, 25, 0, "JPEG mode. 0=4:2:0 (4lum+2chr blocks/MCU). 1=4:2:2 (2lum+2chr blocks/MCU)" }, + { HEncJpegSlice, 0x050, 0x01000000, 24, 0, "JPEG slice enable. 0=picture ends with EOI. 1=slice ends with RST" }, + { HEncJpegRSTInt, 0x050, 0x00ff0000, 16, 0, "JPEG restart marker interval when slices are disabled (mb rows) [0..255]" }, + { HEncJpegRST, 0x050, 0x0000ffff, 0, 0, "JPEG restart marker for first RST. incremented by HW for next RST" }, + { HEncSplitPenalty16x8, 0x050, 0x3ff00000, 20, 0, "Penalty for using 16x8 or 8x16 MV." }, + { HEncSplitPenalty8x8, 0x050, 0x000ffc00, 10, 0, "Penalty for using 8x8 MV." }, + { HEncSplitPenalty8x4, 0x050, 0x000003ff, 0, 0, "Penalty for using 8x4 or 4x8 MV." }, + + { HEncSkipPenalty, 0x054, 0xff000000, 24, 0, "H.264 SKIP macroblock mode / VP8 zero/nearest/near mode penalty" }, + { HEncNumSlicesReady, 0x054, 0x00ff0000, 16, 0, "H.264 amount of completed slices." }, + { HEncInterFavor, 0x054, 0x0000ffff, 0, 0, "Inter MB mode favor in intra/inter selection" }, + { HEncStrmHdrRem1, 0x058, 0xffffffff, 0, 0, "Stream header remainder bits MSB (MSB aligned)" }, + { HEncStrmHdrRem2, 0x05c, 0xffffffff, 0, 0, "Stream header remainder bits LSB (MSB aligned)" }, + { HEncStrmBufLimit, 0x060, 0xffffffff, 0, 1, "Stream buffer limit (64bit addresses) / output stream size (bits). HWStreamDataCount. If limit is reached buffer full IRQ is given." }, + { HEncMadQpDelta, 0x064, 0xf0000000, 28, 1, "MAD based QP adjustment. madQpChange [-8..7]" }, + { HEncMadThreshold, 0x064, 0x0fc00000, 22, 0, "MAD threshold div256" }, + { HEncQpSum, 0x064, 0x001fffff, 0, 0, "QP Sum div2 output" }, + +/* H.264 Rate control registers */ + { HEncQp, 0x06c, 0xfc000000, 26, 1, "H.264 Initial QP. qpLum [0..51]" }, + { HEncMaxQp, 0x06c, 0x03f00000, 20, 1, "H.264 Maximum QP. qpMax [0..51]" }, + { HEncMinQp, 0x06c, 0x000fc000, 14, 1, "H.264 Minimum QP. qpMin [0..51]" }, + { HEncCPDist, 0x06c, 0x00001fff, 0, 0, "H.264 Checkpoint distance (mb) 0=disabled [0..8191]" }, + { HEncCP1WordTarget, 0x070, 0xffff0000, 16, 0, "H.264 Checkpoint 1 word target/usage div32 [0..65535]" }, + { HEncCP2WordTarget, 0x070, 0x0000ffff, 0, 0, "H.264 Checkpoint 2 word target/usage div32 [0..65535]" }, + { HEncCP3WordTarget, 0x074, 0xffff0000, 16, 0, "H.264 Checkpoint 3 word target/usage div32 [0..65535]" }, + { HEncCP4WordTarget, 0x074, 0x0000ffff, 0, 0, "H.264 Checkpoint 4 word target/usage div32 [0..65535]" }, + { HEncCP5WordTarget, 0x078, 0xffff0000, 16, 0, "H.264 Checkpoint 5 word target/usage div32 [0..65535]" }, + { HEncCP6WordTarget, 0x078, 0x0000ffff, 0, 0, "H.264 Checkpoint 6 word target/usage div32 [0..65535]" }, + { HEncCP7WordTarget, 0x07c, 0xffff0000, 16, 0, "H.264 Checkpoint 7 word target/usage div32 [0..65535]" }, + { HEncCP8WordTarget, 0x07c, 0x0000ffff, 0, 0, "H.264 Checkpoint 8 word target/usage div32 [0..65535]" }, + { HEncCP9WordTarget, 0x080, 0xffff0000, 16, 0, "H.264 Checkpoint 9 word target/usage div32 [0..65535]" }, + { HEncCP10WordTarget, 0x080, 0x0000ffff, 0, 0, "H.264 Checkpoint 10 word target/usage div32 [0..65535]" }, + { HEncCPWordError1, 0x084, 0xffff0000, 16, 0, "H.264 Checkpoint word error 1 div4 [-32768..32767]" }, + { HEncCPWordError2, 0x084, 0x0000ffff, 0, 0, "H.264 Checkpoint word error 2 div4 [-32768..32767]" }, + { HEncCPWordError3, 0x088, 0xffff0000, 16, 0, "H.264 Checkpoint word error 3 div4 [-32768..32767]" }, + { HEncCPWordError4, 0x088, 0x0000ffff, 0, 0, "H.264 Checkpoint word error 4 div4 [-32768..32767]" }, + { HEncCPWordError5, 0x08c, 0xffff0000, 16, 0, "H.264 Checkpoint word error 5 div4 [-32768..32767]" }, + { HEncCPWordError6, 0x08c, 0x0000ffff, 0, 0, "H.264 Checkpoint word error 6 div4 [-32768..32767]" }, + { HEncCPDeltaQp1, 0x090, 0x0f000000, 24, 0, "H.264 Checkpoint delta QP 1 [-8..7]" }, + { HEncCPDeltaQp2, 0x090, 0x00f00000, 20, 0, "H.264 Checkpoint delta QP 2 [-8..7]" }, + { HEncCPDeltaQp3, 0x090, 0x000f0000, 16, 0, "H.264 Checkpoint delta QP 3 [-8..7]" }, + { HEncCPDeltaQp4, 0x090, 0x0000f000, 12, 0, "H.264 Checkpoint delta QP 4 [-8..7]" }, + { HEncCPDeltaQp5, 0x090, 0x00000f00, 8, 0, "H.264 Checkpoint delta QP 5 [-8..7]" }, + { HEncCPDeltaQp6, 0x090, 0x000000f0, 4, 0, "H.264 Checkpoint delta QP 6 [-8..7]" }, + { HEncCPDeltaQp7, 0x090, 0x0000000f, 0, 0, "H.264 Checkpoint delta QP 7 [-8..7]" }, +/* VP8 Rate control registers, regs 0x6C - 0x90 redefined for VP8 */ + { HEncVp8Y1QuantDc, 0x06C, 0x00003fff, 0, 1, "VP8 qpY1QuantDc 14b" }, + { HEncVp8Y1ZbinDc, 0x06C, 0x007fc000, 14, 1, "VP8 qpY1ZbinDc 9b" }, + { HEncVp8Y1RoundDc, 0x06C, 0x7f800000, 23, 1, "VP8 qpY1RoundDc 8b" }, + { HEncVp8Y1QuantAc, 0x070, 0x00003fff, 0, 1, "VP8 qpY1QuantAc 14b" }, + { HEncVp8Y1ZbinAc, 0x070, 0x007fc000, 14, 1, "VP8 qpY1ZbinAc 9b" }, + { HEncVp8Y1RoundAc, 0x070, 0x7f800000, 23, 1, "VP8 qpY1RoundAc 8b" }, + { HEncVp8Y2QuantDc, 0x074, 0x00003fff, 0, 1, "VP8 qpY2QuantDc 14b" }, + { HEncVp8Y2ZbinDc, 0x074, 0x007fc000, 14, 1, "VP8 qpY2ZbinDc 9b" }, + { HEncVp8Y2RoundDc, 0x074, 0x7f800000, 23, 1, "VP8 qpY2RoundDc 8b" }, + { HEncVp8Y2QuantAc, 0x078, 0x00003fff, 0, 1, "VP8 qpY2QuantAc 14b" }, + { HEncVp8Y2ZbinAc, 0x078, 0x007fc000, 14, 1, "VP8 qpY2ZbinAc 9b" }, + { HEncVp8Y2RoundAc, 0x078, 0x7f800000, 23, 1, "VP8 qpY2RoundAc 8b" }, + { HEncVp8ChQuantDc, 0x07C, 0x00003fff, 0, 1, "VP8 qpChQuantDc 14b" }, + { HEncVp8ChZbinDc, 0x07C, 0x007fc000, 14, 1, "VP8 qpChZbinDc 9b" }, + { HEncVp8ChRoundDc, 0x07C, 0x7f800000, 23, 1, "VP8 qpChRoundDc 8b" }, + { HEncVp8ChQuantAc, 0x080, 0x00003fff, 0, 1, "VP8 qpChQuantAc 14b" }, + { HEncVp8ChZbinAc, 0x080, 0x007fc000, 14, 1, "VP8 qpChZbinAc 9b" }, + { HEncVp8ChRoundAc, 0x080, 0x7f800000, 23, 1, "VP8 qpChRoundAc 8b" }, + { HEncVp8Y1DequantDc, 0x084, 0x000000ff, 0, 1, "VP8 qpY1DequantDc 8b" }, + { HEncVp8Y1DequantAc, 0x084, 0x0001ff00, 8, 1, "VP8 qpY1DequantAc 9b" }, + { HEncVp8Y2DequantDc, 0x084, 0x03fe0000, 17, 1, "VP8 qpY2DequantDc 9b" }, + { HEncVp8MvRefIdx, 0x084, 0x0c000000, 26, 0, "VP8 mvRefIdx for first reference frame. 0=ipf. 1=grf. 2=arf." }, + { HEncVp8Y2DequantAc, 0x088, 0x000001ff, 0, 1, "VP8 qpY2DequantAc 9b" }, + { HEncVp8ChDequantDc, 0x088, 0x0001fe00, 9, 1, "VP8 qpChDequantDc 8b" }, + { HEncVp8ChDequantAc, 0x088, 0x03fe0000, 17, 1, "VP8 qpChDequantAc 9b" }, + { HEncVp8MvRefIdx2, 0x088, 0x0c000000, 26, 0, "VP8 mvRefIdx for second reference frame. 0=ipf. 1=grf. 2=arf." }, + { HEncVp8Ref2Enable, 0x088, 0x10000000, 28, 0, "VP8 enable for second reference frame." }, + { HEncVp8SegmentEnable, 0x088, 0x20000000, 29, 1, "VP8 enable for segmentation. Segmentation map is stored in BaseVp8SegmentMap." }, + { HEncVp8SegmentMapUpdate, 0x088, 0x40000000, 30, 0, "VP8 enable for segmentation map update. Map is different from previous frame and is written in stream. " }, + { HEncVp8BoolEncValue, 0x08C, 0xffffffff, 0, 1, "VP8 boolEncValue" }, + { HEncVp8GoldenPenalty, 0x090, 0xff000000, 24, 0, "VP8 Penalty value for second reference frame zero-mv [0..255]" }, + { HEncVp8FilterSharpness, 0x090, 0x00e00000, 21, 0, "VP8 Deblocking filter sharpness [0..7]" }, + { HEncVp8FilterLevel, 0x090, 0x001f8000, 15, 0, "VP8 Deblocking filter level [0..63]" }, + { HEncVp8DctPartitionCount, 0x090, 0x00006000, 13, 0, "VP8 DCT partition count. 0=1. 1=2 [0..1]" }, + { HEncVp8BoolEncValueBits, 0x090, 0x00001f00, 8, 1, "VP8 boolEncValueBitsMinus8 [0..23]" }, + { HEncVp8BoolEncRange, 0x090, 0x000000ff, 0, 1, "VP8 boolEncRange [0..255]" }, + + { HEncStartOffset, 0x094, 0x1f800000, 23, 0, "Stream start offset = amount of StrmHdrRem (bits) [0..63]" }, + { HEncRlcSum, 0x094, 0x007fffff, 0, 0, "RLC codeword count div4 output. max 255*255*384/4" }, + { HEncMadCount, 0x098, 0xffff0000, 16, 0, "Macroblock count with MAD value under threshold output" }, + { HEncMbCount, 0x098, 0x0000ffff, 0, 0, "MB count output. max 255*255" }, +/* Stabilization parameters and outputs */ + { HEncBaseNextLum, 0x09c, 0xffffffff, 0, 0, "Base address for next pic luminance" }, + { HEncStabMode, 0x0a0, 0xc0000000, 30, 1, "Stabilization mode. 0=disabled. 1=stab only. 2=stab+encode" }, + { HEncStabMinimum, 0x0a0, 0x00ffffff, 0, 0, "Stabilization minimum value output. max 253*253*255" }, + { HEncStabMotionSum, 0x0a4, 0xffffffff, 0, 0, "Stabilization motion sum div8 output. max 253*253*255*1089/8" }, + { HEncStabGmvX, 0x0a8, 0xfc000000, 26, 0, "Stabilization GMV horizontal output [-16..16]" }, + { HEncStabMatrix1, 0x0a8, 0x00ffffff, 0, 0, "Stabilization matrix 1 (up-left position) output" }, + { HEncStabGmvY, 0x0ac, 0xfc000000, 26, 0, "Stabilization GMV vertical output [-16..16]" }, + { HEncStabMatrix2, 0x0ac, 0x00ffffff, 0, 0, "Stabilization matrix 2 (up position) output" }, + { HEncStabMatrix3, 0x0b0, 0x00ffffff, 0, 0, "Stabilization matrix 3 (up-right position) output" }, + { HEncStabMatrix4, 0x0b4, 0x00ffffff, 0, 0, "Stabilization matrix 4 (left position) output" }, + { HEncStabMatrix5, 0x0b8, 0x00ffffff, 0, 0, "Stabilization matrix 5 (GMV position) output" }, + { HEncStabMatrix6, 0x0bc, 0x00ffffff, 0, 0, "Stabilization matrix 6 (right position) output" }, + { HEncStabMatrix7, 0x0c0, 0x00ffffff, 0, 0, "Stabilization matrix 7 (down-left position) output" }, + { HEncStabMatrix8, 0x0c4, 0x00ffffff, 0, 0, "Stabilization matrix 8 (down position) output" }, + { HEncStabMatrix9, 0x0c8, 0x00ffffff, 0, 0, "Stabilization matrix 9 (down-right position) output" }, + { HEncBaseCabacCtx, 0x0cc, 0xffffffff, 0, 0, "Base address for cabac context tables (H264) or probability tables (VP8)" }, + { HEncBaseMvWrite, 0x0d0, 0xffffffff, 0, 0, "Base address for MV output writing" }, +/* Pre-processor color conversion parameters */ + { HEncRGBCoeffA, 0x0d4, 0x0000ffff, 0, 0, "RGB to YUV conversion coefficient A" }, + { HEncRGBCoeffB, 0x0d4, 0xffff0000, 16, 0, "RGB to YUV conversion coefficient B" }, + { HEncRGBCoeffC, 0x0d8, 0x0000ffff, 0, 0, "RGB to YUV conversion coefficient C" }, + { HEncRGBCoeffE, 0x0d8, 0xffff0000, 16, 0, "RGB to YUV conversion coefficient E" }, + { HEncRGBCoeffF, 0x0dc, 0x0000ffff, 0, 0, "RGB to YUV conversion coefficient F" }, + { HEncRMaskMSB, 0x0dc, 0x001f0000, 16, 0, "RGB R-component mask MSB bit position [0..31]" }, + { HEncGMaskMSB, 0x0dc, 0x03e00000, 21, 0, "RGB G-component mask MSB bit position [0..31]" }, + { HEncBMaskMSB, 0x0dc, 0x7c000000, 26, 0, "RGB B-component mask MSB bit position [0..31]" }, + { HEncIntraAreaLeft, 0x0e0, 0xff000000, 24, 0, "Intra area left mb column (inside area) [0..255]" }, + { HEncIntraAreaRight, 0x0e0, 0x00ff0000, 16, 0, "Intra area right mb column (outside area) [0..255]" }, + { HEncIntraAreaTop, 0x0e0, 0x0000ff00, 8, 0, "Intra area top mb row (inside area) [0..255]" }, + { HEncIntraAreaBottom, 0x0e0, 0x000000ff, 0, 0, "Intra area bottom mb row (outside area) [0..255]" }, + { HEncCirStart, 0x0e4, 0xffff0000, 16, 0, "CIR first intra mb. 0=disabled [0..65535]" }, + { HEncCirInterval, 0x0e4, 0x0000ffff, 0, 0, "CIR intra mb interval. 0=disabled [0..65535]" }, + +/* H264 / VP8 mixed definitions */ + { HEncIntraSliceMap1, 0x0e8, 0xffffffff, 0, 0, "Intra slice bitmap for slices 0..31. LSB=slice0. MSB=slice31. 1=intra." }, + { HEncIntraSliceMap2, 0x0ec, 0xffffffff, 0, 0, "Intra slice bitmap for slices 32..63. LSB=slice32. MSB=slice63. 1=intra." }, + { HEncIntraSliceMap3, 0x068, 0xffffffff, 0, 0, "Intra slice bitmap for slices 64..95. LSB=slice64. MSB=slice95. 1=intra." }, + { HEncBasePartition1, 0x0e8, 0xffffffff, 0, 0, "Base address for VP8 1st DCT partition" }, + { HEncBasePartition2, 0x0ec, 0xffffffff, 0, 0, "Base address for VP8 2nd DCT partition" }, + { HEncBaseVp8ProbCount, 0x068, 0xffffffff, 0, 0, "Base address for VP8 counters for probability updates" }, + + { HEncRoi1Left, 0x0f0, 0xff000000, 24, 0, "1st ROI area left mb column (inside area) qp+=Roi1DeltaQp" }, + { HEncRoi1Right, 0x0f0, 0x00ff0000, 16, 0, "1st ROI area right mb column (outside area) qp-=Roi1DeltaQp" }, + { HEncRoi1Top, 0x0f0, 0x0000ff00, 8, 0, "1st ROI area top mb row (inside area)" }, + { HEncRoi1Bottom, 0x0f0, 0x000000ff, 0, 0, "1st ROI area bottom mb row (outside area)" }, + { HEncRoi2Left, 0x0f4, 0xff000000, 24, 0, "2nd ROI area left mb column (inside area) qp+=Roi2DeltaQp" }, + { HEncRoi2Right, 0x0f4, 0x00ff0000, 16, 0, "2nd ROI area right mb column (outside area) qp-=Roi2DeltaQp" }, + { HEncRoi2Top, 0x0f4, 0x0000ff00, 8, 0, "2nd ROI area top mb row (inside area)" }, + { HEncRoi2Bottom, 0x0f4, 0x000000ff, 0, 0, "2nd ROI area bottom mb row (outside area)" }, + { HEncRoi1DeltaQp, 0x0f8, 0x000000f0, 4, 0, "1st ROI area delta QP. qp = Qp - Roi1DeltaQp [0..15]" }, + { HEncRoi2DeltaQp, 0x0f8, 0x0000000f, 0, 0, "2nd ROI area delta QP. qp = Qp - Roi2DeltaQp [0..15]" }, + { HEncZeroMvFavor, 0x0f8, 0xf0000000, 28, 0, "Zero 16x16 MV favor div2." }, + { HEncSplitPenalty4x4, 0x0f8, 0x0ff80000, 19, 0, "Penalty for using 4x4 MV." }, + { HEncMvcPriorityId, 0x0f8, 0x00070000, 16, 0, "MVC priority_id [0..7]" }, + { HEncMvcViewId, 0x0f8, 0x0000e000, 13, 0, "MVC view_id [0..7]" }, + { HEncMvcTemporalId, 0x0f8, 0x00001c00, 10, 0, "MVC temporal_id [0..7]" }, + { HEncMvcAnchorPicFlag, 0x0f8, 0x00000200, 9, 0, "MVC anchor_pic_flag. Specifies that the picture is part of an anchor access unit." }, + { HEncMvcInterViewFlag, 0x0f8, 0x00000100, 8, 0, "MVC inter_view_flag. Specifies that the picture is used for inter-view prediction." }, + +/* HW synthesis config register, read-only */ + { HEncHWTiledSupport, 0x0fc, 0x40000000, 30, 0, "Tiled 4x4 input mode supported by HW. 0=not supported. 1=supported" }, + { HEncHWSearchArea, 0x0fc, 0x20000000, 29, 0, "HW search area height. 0=5 MB rows. 1=3 MB rows" }, + { HEncHWRgbSupport, 0x0fc, 0x10000000, 28, 0, "RGB to YUV conversion supported by HW. 0=not supported. 1=supported" }, + { HEncHWH264Support, 0x0fc, 0x08000000, 27, 0, "H.264 encoding supported by HW. 0=not supported. 1=supported" }, + { HEncHWVp8Support, 0x0fc, 0x04000000, 26, 0, "VP8 encoding supported by HW. 0=not supported. 1=supported" }, + { HEncHWJpegSupport, 0x0fc, 0x02000000, 25, 0, "JPEG encoding supported by HW. 0=not supported. 1=supported" }, + { HEncHWStabSupport, 0x0fc, 0x01000000, 24, 0, "Stabilization supported by HW. 0=not supported. 1=supported" }, + { HEncHWBus, 0x0fc, 0x00f00000, 20, 0, "Bus connection of HW. 1=AHB. 2=OCP. 3=AXI. 4=PCI. 5=AXIAHB. 6=AXIAPB." }, + { HEncHWSynthesisLan, 0x0fc, 0x000f0000, 16, 0, "Synthesis language. 1=vhdl. 2=verilog" }, + { HEncHWBusWidth, 0x0fc, 0x0000f000, 12, 0, "Bus width of HW. 0=32b. 1=64b. 2=128b" }, + { HEncHWMaxVideoWidth, 0x0fc, 0x00000fff, 0, 0, "Maximum video width supported by HW (pixels)" }, + +/* JPEG / VP8 mixed definitions regs 0x100-0x17C */ + { HEncJpegQuantLuma1, 0x100, 0xffffffff, 0, 0, "JPEG luma quantization 1" }, + { HEncJpegQuantLuma2, 0x104, 0xffffffff, 0, 0, "JPEG luma quantization 2" }, + { HEncJpegQuantLuma3, 0x108, 0xffffffff, 0, 0, "JPEG luma quantization 3" }, + { HEncJpegQuantLuma4, 0x10c, 0xffffffff, 0, 0, "JPEG luma quantization 4" }, + { HEncJpegQuantLuma5, 0x110, 0xffffffff, 0, 0, "JPEG luma quantization 5" }, + { HEncJpegQuantLuma6, 0x114, 0xffffffff, 0, 0, "JPEG luma quantization 6" }, + { HEncJpegQuantLuma7, 0x118, 0xffffffff, 0, 0, "JPEG luma quantization 7" }, + { HEncJpegQuantLuma8, 0x11c, 0xffffffff, 0, 0, "JPEG luma quantization 8" }, + { HEncJpegQuantLuma9, 0x120, 0xffffffff, 0, 0, "JPEG luma quantization 9" }, + { HEncJpegQuantLuma10, 0x124, 0xffffffff, 0, 0, "JPEG luma quantization 10" }, + { HEncJpegQuantLuma11, 0x128, 0xffffffff, 0, 0, "JPEG luma quantization 11" }, + { HEncJpegQuantLuma12, 0x12c, 0xffffffff, 0, 0, "JPEG luma quantization 12" }, + { HEncJpegQuantLuma13, 0x130, 0xffffffff, 0, 0, "JPEG luma quantization 13" }, + { HEncJpegQuantLuma14, 0x134, 0xffffffff, 0, 0, "JPEG luma quantization 14" }, + { HEncJpegQuantLuma15, 0x138, 0xffffffff, 0, 0, "JPEG luma quantization 15" }, + { HEncJpegQuantLuma16, 0x13c, 0xffffffff, 0, 0, "JPEG luma quantization 16" }, + { HEncJpegQuantChroma1, 0x140, 0xffffffff, 0, 0, "JPEG chroma quantization 1" }, + { HEncJpegQuantChroma2, 0x144, 0xffffffff, 0, 0, "JPEG chroma quantization 2" }, + { HEncJpegQuantChroma3, 0x148, 0xffffffff, 0, 0, "JPEG chroma quantization 3" }, + { HEncJpegQuantChroma4, 0x14c, 0xffffffff, 0, 0, "JPEG chroma quantization 4" }, + { HEncJpegQuantChroma5, 0x150, 0xffffffff, 0, 0, "JPEG chroma quantization 5" }, + { HEncJpegQuantChroma6, 0x154, 0xffffffff, 0, 0, "JPEG chroma quantization 6" }, + { HEncJpegQuantChroma7, 0x158, 0xffffffff, 0, 0, "JPEG chroma quantization 7" }, + { HEncJpegQuantChroma8, 0x15c, 0xffffffff, 0, 0, "JPEG chroma quantization 8" }, + { HEncJpegQuantChroma9, 0x160, 0xffffffff, 0, 0, "JPEG chroma quantization 9" }, + { HEncJpegQuantChroma10, 0x164, 0xffffffff, 0, 0, "JPEG chroma quantization 10" }, + { HEncJpegQuantChroma11, 0x168, 0xffffffff, 0, 0, "JPEG chroma quantization 11" }, + { HEncJpegQuantChroma12, 0x16c, 0xffffffff, 0, 0, "JPEG chroma quantization 12" }, + { HEncJpegQuantChroma13, 0x170, 0xffffffff, 0, 0, "JPEG chroma quantization 13" }, + { HEncJpegQuantChroma14, 0x174, 0xffffffff, 0, 0, "JPEG chroma quantization 14" }, + { HEncJpegQuantChroma15, 0x178, 0xffffffff, 0, 0, "JPEG chroma quantization 15" }, + { HEncJpegQuantChroma16, 0x17C, 0xffffffff, 0, 0, "JPEG chroma quantization 16" }, + { HEncVp8Mode0Penalty, 0x100, 0x00000fff, 0, 0, "VP8 intra 16x16 mode 0 penalty" }, + { HEncVp8Mode1Penalty, 0x100, 0x00fff000, 12, 0, "VP8 intra 16x16 mode 1 penalty" }, + { HEncVp8Mode2Penalty, 0x104, 0x00000fff, 0, 0, "VP8 intra 16x16 mode 2 penalty" }, + { HEncVp8Mode3Penalty, 0x104, 0x00fff000, 12, 0, "VP8 intra 16x16 mode 3 penalty" }, + { HEncVp8Bmode0Penalty, 0x108, 0x00000fff, 0, 0, "VP8 intra 4x4 mode 0 penalty" }, + { HEncVp8Bmode1Penalty, 0x108, 0x00fff000, 12, 0, "VP8 intra 4x4 mode 1 penalty" }, + { HEncVp8Bmode2Penalty, 0x10C, 0x00000fff, 0, 0, "VP8 intra 4x4 mode 2 penalty" }, + { HEncVp8Bmode3Penalty, 0x10C, 0x00fff000, 12, 0, "VP8 intra 4x4 mode 3 penalty" }, + { HEncVp8Bmode4Penalty, 0x110, 0x00000fff, 0, 0, "VP8 intra 4x4 mode 4 penalty" }, + { HEncVp8Bmode5Penalty, 0x110, 0x00fff000, 12, 0, "VP8 intra 4x4 mode 5 penalty" }, + { HEncVp8Bmode6Penalty, 0x114, 0x00000fff, 0, 0, "VP8 intra 4x4 mode 6 penalty" }, + { HEncVp8Bmode7Penalty, 0x114, 0x00fff000, 12, 0, "VP8 intra 4x4 mode 7 penalty" }, + { HEncVp8Bmode8Penalty, 0x118, 0x00000fff, 0, 0, "VP8 intra 4x4 mode 8 penalty" }, + { HEncVp8Bmode9Penalty, 0x118, 0x00fff000, 12, 0, "VP8 intra 4x4 mode 9 penalty" }, + { HEncBaseVp8SegmentMap, 0x11C, 0xffffffff, 0, 0, "Base address for VP8 segmentation map, segmentId 2-bits/macroblock" }, + { HEncVp8Seg1Y1QuantDc, 0x120, 0x00003fff, 0, 1, "VP8 segment1 qpY1QuantDc 14b" }, + { HEncVp8Seg1Y1ZbinDc, 0x120, 0x007fc000, 14, 1, "VP8 segment1 qpY1ZbinDc 9b" }, + { HEncVp8Seg1Y1RoundDc, 0x120, 0x7f800000, 23, 1, "VP8 segment1 qpY1RoundDc 8b" }, + { HEncVp8Seg1Y1QuantAc, 0x124, 0x00003fff, 0, 1, "VP8 segment1 qpY1QuantAc 14b" }, + { HEncVp8Seg1Y1ZbinAc, 0x124, 0x007fc000, 14, 1, "VP8 segment1 qpY1ZbinAc 9b" }, + { HEncVp8Seg1Y1RoundAc, 0x124, 0x7f800000, 23, 1, "VP8 segment1 qpY1RoundAc 8b" }, + { HEncVp8Seg1Y2QuantDc, 0x128, 0x00003fff, 0, 1, "VP8 segment1 qpY2QuantDc 14b" }, + { HEncVp8Seg1Y2ZbinDc, 0x128, 0x007fc000, 14, 1, "VP8 segment1 qpY2ZbinDc 9b" }, + { HEncVp8Seg1Y2RoundDc, 0x128, 0x7f800000, 23, 1, "VP8 segment1 qpY2RoundDc 8b" }, + { HEncVp8Seg1Y2QuantAc, 0x12C, 0x00003fff, 0, 1, "VP8 segment1 qpY2QuantAc 14b" }, + { HEncVp8Seg1Y2ZbinAc, 0x12C, 0x007fc000, 14, 1, "VP8 segment1 qpY2ZbinAc 9b" }, + { HEncVp8Seg1Y2RoundAc, 0x12C, 0x7f800000, 23, 1, "VP8 segment1 qpY2RoundAc 8b" }, + { HEncVp8Seg1ChQuantDc, 0x130, 0x00003fff, 0, 1, "VP8 segment1 qpChQuantDc 14b" }, + { HEncVp8Seg1ChZbinDc, 0x130, 0x007fc000, 14, 1, "VP8 segment1 qpChZbinDc 9b" }, + { HEncVp8Seg1ChRoundDc, 0x130, 0x7f800000, 23, 1, "VP8 segment1 qpChRoundDc 8b" }, + { HEncVp8Seg1ChQuantAc, 0x134, 0x00003fff, 0, 1, "VP8 segment1 qpChQuantAc 14b" }, + { HEncVp8Seg1ChZbinAc, 0x134, 0x007fc000, 14, 1, "VP8 segment1 qpChZbinAc 9b" }, + { HEncVp8Seg1ChRoundAc, 0x134, 0x7f800000, 23, 1, "VP8 segment1 qpChRoundAc 8b" }, + { HEncVp8Seg1Y1DequantDc, 0x138, 0x000000ff, 0, 1, "VP8 segment1 qpY1DequantDc 8b" }, + { HEncVp8Seg1Y1DequantAc, 0x138, 0x0001ff00, 8, 1, "VP8 segment1 qpY1DequantAc 9b" }, + { HEncVp8Seg1Y2DequantDc, 0x138, 0x03fe0000, 17, 1, "VP8 segment1 qpY2DequantDc 9b" }, + { HEncVp8Seg1Y2DequantAc, 0x13C, 0x000001ff, 0, 1, "VP8 segment1 qpY2DequantAc 9b" }, + { HEncVp8Seg1ChDequantDc, 0x13C, 0x0001fe00, 9, 1, "VP8 segment1 qpChDequantDc 8b" }, + { HEncVp8Seg1ChDequantAc, 0x13C, 0x03fe0000, 17, 1, "VP8 segment1 qpChDequantAc 9b" }, + { HEncVp8Seg1FilterLevel, 0x13C, 0xfc000000, 26, 1, "VP8 segment1 filter level 6b" }, + { HEncVp8Seg2Y1QuantDc, 0x140, 0x00003fff, 0, 1, "VP8 segment2 qpY1QuantDc 14b" }, + { HEncVp8Seg2Y1ZbinDc, 0x140, 0x007fc000, 14, 1, "VP8 segment2 qpY1ZbinDc 9b" }, + { HEncVp8Seg2Y1RoundDc, 0x140, 0x7f800000, 23, 1, "VP8 segment2 qpY1RoundDc 8b" }, + { HEncVp8Seg2Y1QuantAc, 0x144, 0x00003fff, 0, 1, "VP8 segment2 qpY1QuantAc 14b" }, + { HEncVp8Seg2Y1ZbinAc, 0x144, 0x007fc000, 14, 1, "VP8 segment2 qpY1ZbinAc 9b" }, + { HEncVp8Seg2Y1RoundAc, 0x144, 0x7f800000, 23, 1, "VP8 segment2 qpY1RoundAc 8b" }, + { HEncVp8Seg2Y2QuantDc, 0x148, 0x00003fff, 0, 1, "VP8 segment2 qpY2QuantDc 14b" }, + { HEncVp8Seg2Y2ZbinDc, 0x148, 0x007fc000, 14, 1, "VP8 segment2 qpY2ZbinDc 9b" }, + { HEncVp8Seg2Y2RoundDc, 0x148, 0x7f800000, 23, 1, "VP8 segment2 qpY2RoundDc 8b" }, + { HEncVp8Seg2Y2QuantAc, 0x14C, 0x00003fff, 0, 1, "VP8 segment2 qpY2QuantAc 14b" }, + { HEncVp8Seg2Y2ZbinAc, 0x14C, 0x007fc000, 14, 1, "VP8 segment2 qpY2ZbinAc 9b" }, + { HEncVp8Seg2Y2RoundAc, 0x14C, 0x7f800000, 23, 1, "VP8 segment2 qpY2RoundAc 8b" }, + { HEncVp8Seg2ChQuantDc, 0x150, 0x00003fff, 0, 1, "VP8 segment2 qpChQuantDc 14b" }, + { HEncVp8Seg2ChZbinDc, 0x150, 0x007fc000, 14, 1, "VP8 segment2 qpChZbinDc 9b" }, + { HEncVp8Seg2ChRoundDc, 0x150, 0x7f800000, 23, 1, "VP8 segment2 qpChRoundDc 8b" }, + { HEncVp8Seg2ChQuantAc, 0x154, 0x00003fff, 0, 1, "VP8 segment2 qpChQuantAc 14b" }, + { HEncVp8Seg2ChZbinAc, 0x154, 0x007fc000, 14, 1, "VP8 segment2 qpChZbinAc 9b" }, + { HEncVp8Seg2ChRoundAc, 0x154, 0x7f800000, 23, 1, "VP8 segment2 qpChRoundAc 8b" }, + { HEncVp8Seg2Y1DequantDc, 0x158, 0x000000ff, 0, 1, "VP8 segment2 qpY1DequantDc 8b" }, + { HEncVp8Seg2Y1DequantAc, 0x158, 0x0001ff00, 8, 1, "VP8 segment2 qpY1DequantAc 9b" }, + { HEncVp8Seg2Y2DequantDc, 0x158, 0x03fe0000, 17, 1, "VP8 segment2 qpY2DequantDc 9b" }, + { HEncVp8Seg2Y2DequantAc, 0x15C, 0x000001ff, 0, 1, "VP8 segment2 qpY2DequantAc 9b" }, + { HEncVp8Seg2ChDequantDc, 0x15C, 0x0001fe00, 9, 1, "VP8 segment2 qpChDequantDc 8b" }, + { HEncVp8Seg2ChDequantAc, 0x15C, 0x03fe0000, 17, 1, "VP8 segment2 qpChDequantAc 9b" }, + { HEncVp8Seg2FilterLevel, 0x15C, 0xfc000000, 26, 1, "VP8 segment2 filter level 6b" }, + { HEncVp8Seg3Y1QuantDc, 0x160, 0x00003fff, 0, 1, "VP8 segment3 qpY1QuantDc 14b" }, + { HEncVp8Seg3Y1ZbinDc, 0x160, 0x007fc000, 14, 1, "VP8 segment3 qpY1ZbinDc 9b" }, + { HEncVp8Seg3Y1RoundDc, 0x160, 0x7f800000, 23, 1, "VP8 segment3 qpY1RoundDc 8b" }, + { HEncVp8Seg3Y1QuantAc, 0x164, 0x00003fff, 0, 1, "VP8 segment3 qpY1QuantAc 14b" }, + { HEncVp8Seg3Y1ZbinAc, 0x164, 0x007fc000, 14, 1, "VP8 segment3 qpY1ZbinAc 9b" }, + { HEncVp8Seg3Y1RoundAc, 0x164, 0x7f800000, 23, 1, "VP8 segment3 qpY1RoundAc 8b" }, + { HEncVp8Seg3Y2QuantDc, 0x168, 0x00003fff, 0, 1, "VP8 segment3 qpY2QuantDc 14b" }, + { HEncVp8Seg3Y2ZbinDc, 0x168, 0x007fc000, 14, 1, "VP8 segment3 qpY2ZbinDc 9b" }, + { HEncVp8Seg3Y2RoundDc, 0x168, 0x7f800000, 23, 1, "VP8 segment3 qpY2RoundDc 8b" }, + { HEncVp8Seg3Y2QuantAc, 0x16C, 0x00003fff, 0, 1, "VP8 segment3 qpY2QuantAc 14b" }, + { HEncVp8Seg3Y2ZbinAc, 0x16C, 0x007fc000, 14, 1, "VP8 segment3 qpY2ZbinAc 9b" }, + { HEncVp8Seg3Y2RoundAc, 0x16C, 0x7f800000, 23, 1, "VP8 segment3 qpY2RoundAc 8b" }, + { HEncVp8Seg3ChQuantDc, 0x170, 0x00003fff, 0, 1, "VP8 segment3 qpChQuantDc 14b" }, + { HEncVp8Seg3ChZbinDc, 0x170, 0x007fc000, 14, 1, "VP8 segment3 qpChZbinDc 9b" }, + { HEncVp8Seg3ChRoundDc, 0x170, 0x7f800000, 23, 1, "VP8 segment3 qpChRoundDc 8b" }, + { HEncVp8Seg3ChQuantAc, 0x174, 0x00003fff, 0, 1, "VP8 segment3 qpChQuantAc 14b" }, + { HEncVp8Seg3ChZbinAc, 0x174, 0x007fc000, 14, 1, "VP8 segment3 qpChZbinAc 9b" }, + { HEncVp8Seg3ChRoundAc, 0x174, 0x7f800000, 23, 1, "VP8 segment3 qpChRoundAc 8b" }, + { HEncVp8Seg3Y1DequantDc, 0x178, 0x000000ff, 0, 1, "VP8 segment3 qpY1DequantDc 8b" }, + { HEncVp8Seg3Y1DequantAc, 0x178, 0x0001ff00, 8, 1, "VP8 segment3 qpY1DequantAc 9b" }, + { HEncVp8Seg3Y2DequantDc, 0x178, 0x03fe0000, 17, 1, "VP8 segment3 qpY2DequantDc 9b" }, + { HEncVp8Seg3Y2DequantAc, 0x17C, 0x000001ff, 0, 1, "VP8 segment3 qpY2DequantAc 9b" }, + { HEncVp8Seg3ChDequantDc, 0x17C, 0x0001fe00, 9, 1, "VP8 segment3 qpChDequantDc 8b" }, + { HEncVp8Seg3ChDequantAc, 0x17C, 0x03fe0000, 17, 1, "VP8 segment3 qpChDequantAc 9b" }, + { HEncVp8Seg3FilterLevel, 0x17C, 0xfc000000, 26, 1, "VP8 segment3 filter level 6b" }, + + { HEncDmvPenalty1, 0x180, 0xffffffff, 0, 0, "DMV 4p/1p penalty values 0-3" }, + { HEncDmvPenalty2, 0x184, 0xffffffff, 0, 0, "DMV 4p/1p penalty values 4-7" }, + { HEncDmvPenalty3, 0x188, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty4, 0x18C, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty5, 0x190, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty6, 0x194, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty7, 0x198, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty8, 0x19C, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty9, 0x1A0, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty10, 0x1A4, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty11, 0x1A8, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty12, 0x1AC, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty13, 0x1B0, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty14, 0x1B4, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty15, 0x1B8, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty16, 0x1BC, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty17, 0x1C0, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty18, 0x1C4, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty19, 0x1C8, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty20, 0x1CC, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty21, 0x1D0, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty22, 0x1D4, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty23, 0x1D8, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty24, 0x1DC, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty25, 0x1E0, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty26, 0x1E4, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty27, 0x1E8, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty28, 0x1EC, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty29, 0x1F0, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty30, 0x1F4, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty31, 0x1F8, 0xffffffff, 0, 0, "DMV 4p/1p penalty values" }, + { HEncDmvPenalty32, 0x1FC, 0xffffffff, 0, 0, "DMV 4p/1p penalty values 124-127" }, + + { HEncDmvQpelPenalty1, 0x200, 0xffffffff, 0, 0, "DMV qpel penalty values 0-3" }, + { HEncDmvQpelPenalty2, 0x204, 0xffffffff, 0, 0, "DMV qpel penalty values 4-7" }, + { HEncDmvQpelPenalty3, 0x208, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty4, 0x20C, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty5, 0x210, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty6, 0x214, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty7, 0x218, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty8, 0x21C, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty9, 0x220, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty10, 0x224, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty11, 0x228, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty12, 0x22C, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty13, 0x230, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty14, 0x234, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty15, 0x238, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty16, 0x23C, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty17, 0x240, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty18, 0x244, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty19, 0x248, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty20, 0x24C, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty21, 0x250, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty22, 0x254, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty23, 0x258, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty24, 0x25C, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty25, 0x260, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty26, 0x264, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty27, 0x268, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty28, 0x26C, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty29, 0x270, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty30, 0x274, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty31, 0x278, 0xffffffff, 0, 0, "DMV qpel penalty values" }, + { HEncDmvQpelPenalty32, 0x27C, 0xffffffff, 0, 0, "DMV qpel penalty values 124-127" }, + + { HEncVp8CostInter, 0x280, 0x00000fff, 0, 0, "VP8 bit cost of inter type" }, + { HEncVp8DmvCostConst, 0x280, 0x00fff000, 12, 0, "VP8 coeff for dmv penalty for intra/inter selection" }, + { HEncVp8CostGoldenRef, 0x284, 0x00000fff, 0, 0, "VP8 bit cost of golden ref frame" }, + { HEncVp8LfRefDelta0, 0x288, 0x0000007f, 0, 0, "VP8 loop filter delta for intra mb" }, + { HEncVp8LfRefDelta1, 0x288, 0x00003f80, 7, 0, "VP8 loop filter delta for last ref" }, + { HEncVp8LfRefDelta2, 0x288, 0x001fc000, 14, 0, "VP8 loop filter delta for golden ref" }, + { HEncVp8LfRefDelta3, 0x288, 0x0fe00000, 21, 0, "VP8 loop filter delta for alt ref" }, + { HEncVp8LfModeDelta0, 0x28C, 0x0000007f, 0, 0, "VP8 loop filter delta for BPRED" }, + { HEncVp8LfModeDelta1, 0x28C, 0x00003f80, 7, 0, "VP8 loop filter delta for ZEROMV" }, + { HEncVp8LfModeDelta2, 0x28C, 0x001fc000, 14, 0, "VP8 loop filter delta for NEWMV" }, + { HEncVp8LfModeDelta3, 0x28C, 0x0fe00000, 21, 0, "VP8 loop filter delta for SPLITMV" } + +}; + + +/*------------------------------------------------------------------------------ + Local function prototypes +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + Initialize empty structure with default values. +------------------------------------------------------------------------------*/ +int32_t VP8_EncAsicControllerInit(asicData_s* asic) { + ASSERT(asic != NULL); + + /* Initialize default values from defined configuration */ + asic->regs.irqDisable = ENCH1_IRQ_DISABLE; + + asic->regs.asicCfgReg = + ((ENCH1_AXI_WRITE_ID & (255)) << 24) | + ((ENCH1_AXI_READ_ID & (255)) << 16) | + ((ENCH1_OUTPUT_SWAP_16 & (1)) << 15) | + ((ENCH1_BURST_LENGTH & (63)) << 8) | + ((ENCH1_BURST_SCMD_DISABLE & (1)) << 7) | + ((ENCH1_BURST_INCR_TYPE_ENABLED & (1)) << 6) | + ((ENCH1_BURST_DATA_DISCARD_ENABLED & (1)) << 5) | + ((ENCH1_ASIC_CLOCK_GATING_ENABLED & (1)) << 4) | + ((ENCH1_OUTPUT_SWAP_32 & (1)) << 3) | + ((ENCH1_OUTPUT_SWAP_8 & (1)) << 1); + + /* Initialize default values */ + asic->regs.roundingCtrl = 0; + asic->regs.cpDistanceMbs = 0; + asic->regs.reconImageId = 0; + + asic->internalImageLuma[0].vir_addr = NULL; + asic->internalImageChroma[0].vir_addr = NULL; + asic->internalImageLuma[1].vir_addr = NULL; + asic->internalImageChroma[1].vir_addr = NULL; + asic->internalImageLuma[2].vir_addr = NULL; + asic->internalImageChroma[2].vir_addr = NULL; + asic->cabacCtx.vir_addr = NULL; + asic->probCount.vir_addr = NULL; + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + EncAsicSetRegisterValue + Set a value into a defined register field +------------------------------------------------------------------------------*/ +void VP8_EncAsicSetRegisterValue(uint32_t* regMirror, regName name, uint32_t value) { + const regField_s* field; + uint32_t regVal; + + field = &asicRegisterDesc[name]; + + /* Check that value fits in field */ + ASSERT(field->name == name); + ASSERT((field->mask >> field->lsb) >= value); + ASSERT(field->base < ASIC_SWREG_AMOUNT * 4); + + /* Clear previous value of field in register */ + regVal = regMirror[field->base / 4] & ~(field->mask); + + /* Put new value of field in register */ + regMirror[field->base / 4] = regVal | ((value << field->lsb) & field->mask); +} + +void VP8_CheckRegisterValues(regValues_s* val) { + uint32_t i; + + ASSERT(val->irqDisable <= 1); + ASSERT(val->rlcLimitSpace / 2 < (1 << 20)); + ASSERT(val->mbsInCol <= 511); + ASSERT(val->mbsInRow <= 511); + ASSERT(val->filterDisable <= 2); + ASSERT(val->skipPenalty <= 255); + ASSERT(val->goldenPenalty <= 255); + ASSERT(val->recWriteDisable <= 1); + ASSERT(val->madThreshold <= 63); + ASSERT(val->madQpDelta >= -8 && val->madQpDelta <= 7); + ASSERT(val->qp <= 63); + ASSERT(val->constrainedIntraPrediction <= 1); + ASSERT(val->roundingCtrl <= 1); + ASSERT(val->frameCodingType <= 3); + ASSERT(val->codingType <= 3); + ASSERT(val->outputStrmSize <= 0x1FFFFFF); + ASSERT(val->pixelsOnRow >= 16 && val->pixelsOnRow <= 8192); /* max input for cropping */ + ASSERT(val->xFill <= 3); + ASSERT(val->yFill <= 14 && ((val->yFill & 0x01) == 0)); + ASSERT(val->sliceAlphaOffset >= -6 && val->sliceAlphaOffset <= 6); + ASSERT(val->sliceBetaOffset >= -6 && val->sliceBetaOffset <= 6); + ASSERT(val->chromaQpIndexOffset >= -12 && val->chromaQpIndexOffset <= 12); + ASSERT(val->sliceSizeMbRows <= 127); + ASSERT(val->inputImageFormat <= ASIC_INPUT_YUYV422TILED); + ASSERT(val->inputImageRotation <= 2); + ASSERT(val->cpDistanceMbs <= 8191); + ASSERT(val->cirStart <= 65535); + ASSERT(val->cirInterval <= 65535); + ASSERT(val->intraAreaTop <= 255); + ASSERT(val->intraAreaLeft <= 255); + ASSERT(val->intraAreaBottom <= 255); + ASSERT(val->intraAreaRight <= 255); + ASSERT(val->roi1Top <= 255); + ASSERT(val->roi1Left <= 255); + ASSERT(val->roi1Bottom <= 255); + ASSERT(val->roi1Right <= 255); + ASSERT(val->roi2Top <= 255); + ASSERT(val->roi2Left <= 255); + ASSERT(val->roi2Bottom <= 255); + ASSERT(val->roi2Right <= 255); + + if (val->cpTarget != NULL) { + ASSERT(val->cpTargetResults != NULL); + + for (i = 0; i < 10; i++) { + ASSERT(*val->cpTarget < (1 << 16)); + } + + ASSERT(val->targetError != NULL); + + for (i = 0; i < 7; i++) { + ASSERT((*val->targetError) >= -32768 && + (*val->targetError) < 32768); + } + + ASSERT(val->deltaQp != NULL); + + for (i = 0; i < 7; i++) { + ASSERT((*val->deltaQp) >= -8 && (*val->deltaQp) < 8); + } + } + + (void)val; +} + +/*------------------------------------------------------------------------------ + Function name : EncAsicFrameStart + Description : + Return type : void + Argument : regValues_s * val +------------------------------------------------------------------------------*/ +void VP8_EncAsicFrameStart(regValues_s* val) { + int32_t i; + + VP8_CheckRegisterValues(val); + + memset(val->regMirror, 0, sizeof(val->regMirror)); + + /* encoder interrupt */ + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIRQDisable, val->irqDisable); + + /* system configuration */ + if (val->inputImageFormat < ASIC_INPUT_RGB565) /* YUV input */ + val->regMirror[2] = val->asicCfgReg | + ((ENCH1_INPUT_SWAP_16_YUV & (1)) << 14) | + ((ENCH1_INPUT_SWAP_32_YUV & (1)) << 2) | + (ENCH1_INPUT_SWAP_8_YUV & (1)); + else if (val->inputImageFormat < ASIC_INPUT_RGB888) /* 16-bit RGB input */ + val->regMirror[2] = val->asicCfgReg | + ((ENCH1_INPUT_SWAP_16_RGB16 & (1)) << 14) | + ((ENCH1_INPUT_SWAP_32_RGB16 & (1)) << 2) | + (ENCH1_INPUT_SWAP_8_RGB16 & (1)); + else /* 32-bit RGB input */ + val->regMirror[2] = val->asicCfgReg | + ((ENCH1_INPUT_SWAP_16_RGB32 & (1)) << 14) | + ((ENCH1_INPUT_SWAP_32_RGB32 & (1)) << 2) | + (ENCH1_INPUT_SWAP_8_RGB32 & (1)); + + /* output stream buffer */ + /// TODO, set in driver with value val->outputStrmOffset + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseStream, val->outputStrmBase); + + /* Video encoding output buffers and reference picture buffers */ + + /// TODO, set in driver, and need to copy to user by g_ext_ctrl. + //VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseControl, val->sizeTblBase); + //VP8_EncAsicSetRegisterValue(val->regMirror, HEncNalSizeWrite, val->sizeTblBase != 0); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncNalSizeWrite, 1); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncMvWrite, val->mvOutputBase != 0); + + /// TODO: set in driver. + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseRefLum, val->internalImageLumBaseR[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseRefChr, val->internalImageChrBaseR[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseRecLum, val->internalImageLumBaseW); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseRecChr, val->internalImageChrBaseW); + + /* Input picture buffers */ + /// TODO, set in driver, with input yuv buffer dma_addr. + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseInLum, 0); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseInCb, 0); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseInCr, 0); + + /* Common control register */ + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIntTimeout, ENCH1_TIMEOUT_INTERRUPT & 1); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIntSliceReady, val->sliceReadyInterrupt); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRecWriteDisable, val->recWriteDisable); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncWidth, val->mbsInRow); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncHeight, val->mbsInCol); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncPictureType, val->frameCodingType); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncEncodingMode, val->codingType); + + /* PreP control */ + /// TODO: set in driver, correpond to Chrome base align. + VP8_EncAsicSetRegisterValue(val->regMirror, HEncChrOffset, 0); + /// TODO: set in driver, correspond to Luma base align. + VP8_EncAsicSetRegisterValue(val->regMirror, HEncLumOffset, 0); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRowLength, val->pixelsOnRow); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncXFill, val->xFill); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncYFill, val->yFill); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncInputFormat, val->inputImageFormat); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncInputRot, val->inputImageRotation); + + /* Common controls */ + VP8_EncAsicSetRegisterValue(val->regMirror, HEncCabacEnable, val->enableCabac); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIPIntra16Favor, val->intra16Favor); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncInterFavor, val->interFavor); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncDisableQPMV, val->disableQuarterPixelMv); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncDeblocking, val->filterDisable); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncSkipPenalty, val->skipPenalty); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncSplitMv, val->splitMvMode); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty16x8, val->splitPenalty[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty8x8, val->splitPenalty[1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty8x4, val->splitPenalty[2]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncSplitPenalty4x4, val->splitPenalty[3]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncZeroMvFavor, val->zeroMvFavorDiv2); + + /* stream buffer limits */ + VP8_EncAsicSetRegisterValue(val->regMirror, HEncStrmHdrRem1, val->strmStartMSB); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncStrmHdrRem2, val->strmStartLSB); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncStrmBufLimit, val->outputStrmSize); + + /* video encoding rate control regs 0x6C - 0x90, + * different register definitions for VP8 and H.264 */ + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseRefLum2, val->internalImageLumBaseR[1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseRefChr2, val->internalImageChrBaseR[1]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1QuantDc, val->qpY1QuantDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1QuantAc, val->qpY1QuantAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2QuantDc, val->qpY2QuantDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2QuantAc, val->qpY2QuantAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChQuantDc, val->qpChQuantDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChQuantAc, val->qpChQuantAc[0]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1ZbinDc, val->qpY1ZbinDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1ZbinAc, val->qpY1ZbinAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2ZbinDc, val->qpY2ZbinDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2ZbinAc, val->qpY2ZbinAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChZbinDc, val->qpChZbinDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChZbinAc, val->qpChZbinAc[0]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1RoundDc, val->qpY1RoundDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1RoundAc, val->qpY1RoundAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2RoundDc, val->qpY2RoundDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2RoundAc, val->qpY2RoundAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChRoundDc, val->qpChRoundDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChRoundAc, val->qpChRoundAc[0]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1DequantDc, val->qpY1DequantDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y1DequantAc, val->qpY1DequantAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2DequantDc, val->qpY2DequantDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Y2DequantAc, val->qpY2DequantAc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChDequantDc, val->qpChDequantDc[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8ChDequantAc, val->qpChDequantAc[0]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8MvRefIdx, val->mvRefIdx[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8MvRefIdx2, val->mvRefIdx[1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Ref2Enable, val->ref2Enable); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8BoolEncValue, val->boolEncValue); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8BoolEncValueBits, val->boolEncValueBits); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8BoolEncRange, val->boolEncRange); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8FilterLevel, val->filterLevel[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8GoldenPenalty, val->goldenPenalty); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8FilterSharpness, val->filterSharpness); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8DctPartitionCount, val->dctPartitions); + /* Stream start offset */ + /// TODO, set firstFreeBit in driver, assosiatte to strm output bus address. + VP8_EncAsicSetRegisterValue(val->regMirror, HEncStartOffset, val->firstFreeBit); + + /* Stabilization */ + /// disable stability. + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseNextLum, 0); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncStabMode, 0); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncDMVPenalty4p, val->diffMvPenalty[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncDMVPenalty1p, val->diffMvPenalty[1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncDMVPenaltyQp, val->diffMvPenalty[2]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseCabacCtx, val->cabacCtxBase); + /// TODO: set in driver. + //VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseMvWrite, val->mvOutputBase); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffA, + val->colorConversionCoeffA & mask_16b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffB, + val->colorConversionCoeffB & mask_16b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffC, + val->colorConversionCoeffC & mask_16b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffE, + val->colorConversionCoeffE & mask_16b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRGBCoeffF, + val->colorConversionCoeffF & mask_16b); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRMaskMSB, val->rMaskMsb & mask_5b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncGMaskMSB, val->gMaskMsb & mask_5b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBMaskMSB, val->bMaskMsb & mask_5b); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncCirStart, val->cirStart); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncCirInterval, val->cirInterval); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaLeft, val->intraAreaLeft); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaRight, val->intraAreaRight); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaTop, val->intraAreaTop); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncIntraAreaBottom, val->intraAreaBottom); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi1Left, val->roi1Left); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi1Right, val->roi1Right); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi1Top, val->roi1Top); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi1Bottom, val->roi1Bottom); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi2Left, val->roi2Left); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi2Right, val->roi2Right); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi2Top, val->roi2Top); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncRoi2Bottom, val->roi2Bottom); + + /// TODO, set in driver with value val->partitionOffset[0] + //VP8_EncAsicSetRegisterValue(val->regMirror, HEncBasePartition1, val->partitionBase[0]); + /// TODO, set in driver with value val->partitionOffset[1] + //VP8_EncAsicSetRegisterValue(val->regMirror, HEncBasePartition2, val->partitionBase[1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseVp8ProbCount, val->probCountBase); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode0Penalty, val->intraModePenalty[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode1Penalty, val->intraModePenalty[1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode2Penalty, val->intraModePenalty[2]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Mode3Penalty, val->intraModePenalty[3]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode0Penalty, val->intraBmodePenalty[0]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode1Penalty, val->intraBmodePenalty[1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode2Penalty, val->intraBmodePenalty[2]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode3Penalty, val->intraBmodePenalty[3]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode4Penalty, val->intraBmodePenalty[4]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode5Penalty, val->intraBmodePenalty[5]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode6Penalty, val->intraBmodePenalty[6]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode7Penalty, val->intraBmodePenalty[7]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode8Penalty, val->intraBmodePenalty[8]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Bmode9Penalty, val->intraBmodePenalty[9]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8SegmentEnable, val->segmentEnable); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8SegmentMapUpdate, val->segmentMapUpdate); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncBaseVp8SegmentMap, val->segmentMapBase); + + for (i = 0; i < 3; i++) { + int32_t off = (HEncVp8Seg2Y1QuantDc - HEncVp8Seg1Y1QuantDc) * i; + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1QuantDc + off, val->qpY1QuantDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1QuantAc + off, val->qpY1QuantAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2QuantDc + off, val->qpY2QuantDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2QuantAc + off, val->qpY2QuantAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChQuantDc + off, val->qpChQuantDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChQuantAc + off, val->qpChQuantAc[i + 1]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1ZbinDc + off, val->qpY1ZbinDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1ZbinAc + off, val->qpY1ZbinAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2ZbinDc + off, val->qpY2ZbinDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2ZbinAc + off, val->qpY2ZbinAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChZbinDc + off, val->qpChZbinDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChZbinAc + off, val->qpChZbinAc[i + 1]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1RoundDc + off, val->qpY1RoundDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1RoundAc + off, val->qpY1RoundAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2RoundDc + off, val->qpY2RoundDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2RoundAc + off, val->qpY2RoundAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChRoundDc + off, val->qpChRoundDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChRoundAc + off, val->qpChRoundAc[i + 1]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1DequantDc + off, val->qpY1DequantDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y1DequantAc + off, val->qpY1DequantAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2DequantDc + off, val->qpY2DequantDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1Y2DequantAc + off, val->qpY2DequantAc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChDequantDc + off, val->qpChDequantDc[i + 1]); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1ChDequantAc + off, val->qpChDequantAc[i + 1]); + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8Seg1FilterLevel + off, val->filterLevel[i + 1]); + } + + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta0, val->lfRefDelta[0] & mask_7b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta1, val->lfRefDelta[1] & mask_7b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta2, val->lfRefDelta[2] & mask_7b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfRefDelta3, val->lfRefDelta[3] & mask_7b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta0, val->lfModeDelta[0] & mask_7b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta1, val->lfModeDelta[1] & mask_7b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta2, val->lfModeDelta[2] & mask_7b); + VP8_EncAsicSetRegisterValue(val->regMirror, HEncVp8LfModeDelta3, val->lfModeDelta[3] & mask_7b); + + { + int32_t i = 0; + + /* Write DMV penalty tables to regs */ + for (i = 0; i < 128; i += 4) { + /* swreg[96]=0x180 to swreg[127]=0x1FC */ + val->regMirror[96 + (i / 4)] = + ((val->dmvPenalty[i] << 24) | + (val->dmvPenalty[i + 1] << 16) | + (val->dmvPenalty[i + 2] << 8) | + (val->dmvPenalty[i + 3])); + } + for (i = 0; i < 128; i += 4) { + /* swreg[128]=0x200 to swreg[159]=0x27C */ + val->regMirror[128 + (i / 4)] = + ((val->dmvQpelPenalty[i] << 24) | + (val->dmvQpelPenalty[i + 1] << 16) | + (val->dmvQpelPenalty[i + 2] << 8) | + (val->dmvQpelPenalty[i + 3])); + } + } + + /* Register with enable bit is written last */ + val->regMirror[14] |= ASIC_STATUS_ENABLE; +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.h b/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.h new file mode 100644 index 0000000..797a134 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller.h @@ -0,0 +1,267 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _ENC_ASIC_CONTROLLER_H_ +#define _ENC_ASIC_CONTROLLER_H_ + +#include <stdint.h> +#include "enccfg.h" +#include "vpu_mem.h" +#include "encswhwregisters.h" + +/* HW status register bits */ +#define ASIC_STATUS_ALL 0x1FD + +#define ASIC_STATUS_SLICE_READY 0x100 +#define ASIC_STATUS_HW_TIMEOUT 0x040 +#define ASIC_STATUS_BUFF_FULL 0x020 +#define ASIC_STATUS_HW_RESET 0x010 +#define ASIC_STATUS_ERROR 0x008 +#define ASIC_STATUS_FRAME_READY 0x004 + +#define ASIC_IRQ_LINE 0x001 + +#define ASIC_STATUS_ENABLE 0x001 + +#define ASIC_H264_BYTE_STREAM 0x00 +#define ASIC_H264_NAL_UNIT 0x01 + +#define ASIC_INPUT_YUV420PLANAR 0x00 +#define ASIC_INPUT_YUV420SEMIPLANAR 0x01 +#define ASIC_INPUT_YUYV422INTERLEAVED 0x02 +#define ASIC_INPUT_UYVY422INTERLEAVED 0x03 +#define ASIC_INPUT_RGB565 0x04 +#define ASIC_INPUT_RGB555 0x05 +#define ASIC_INPUT_RGB444 0x06 +#define ASIC_INPUT_RGB888 0x07 +#define ASIC_INPUT_RGB101010 0x08 +#define ASIC_INPUT_YUYV422TILED 0x09 + +#define ASIC_PENALTY_UNDEFINED -1 + +#define ASIC_PENALTY_TABLE_SIZE 128 + +typedef enum +{ + ASIC_VP8 = 1, + ASIC_JPEG = 2, + ASIC_H264 = 3 +} asicCodingType_e; + +typedef enum +{ + ASIC_P_16x16 = 0, + ASIC_P_16x8 = 1, + ASIC_P_8x16 = 2, + ASIC_P_8x8 = 3, + ASIC_I_4x4 = 4, + ASIC_I_16x16 = 5 +} asicMbType_e; + +typedef enum +{ + ASIC_INTER = 0, + ASIC_INTRA = 1, + ASIC_MVC = 2, + ASIC_MVC_REF_MOD = 3 +} asicFrameCodingType_e; + +typedef struct +{ + uint32_t socket; + uint32_t irqDisable; + uint32_t irqInterval; + uint32_t mbsInCol; + uint32_t mbsInRow; + uint32_t qp; + uint32_t qpMin; + uint32_t qpMax; + uint32_t constrainedIntraPrediction; + uint32_t roundingCtrl; + uint32_t frameCodingType; + uint32_t codingType; + uint32_t pixelsOnRow; + uint32_t xFill; + uint32_t yFill; + uint32_t ppsId; + uint32_t idrPicId; + uint32_t frameNum; + uint32_t picInitQp; + int32_t sliceAlphaOffset; + int32_t sliceBetaOffset; + uint32_t filterDisable; + uint32_t transform8x8Mode; + uint32_t enableCabac; + uint32_t cabacInitIdc; + int32_t chromaQpIndexOffset; + uint32_t sliceSizeMbRows; + uint32_t inputImageFormat; + uint32_t inputImageRotation; + uint32_t outputStrmFrmTagOffset; + uint32_t outputStrmBase; + uint32_t outputStrmSize; + uint32_t firstFreeBit; + uint32_t strmStartMSB; + uint32_t strmStartLSB; + uint32_t rlcBase; + uint32_t rlcLimitSpace; + uint32_t sizeTblBase; + uint32_t sliceReadyInterrupt; + uint32_t recWriteDisable; + uint32_t reconImageId; + uint32_t internalImageLumBaseW; + uint32_t internalImageChrBaseW; + uint32_t internalImageLumBaseR[2]; + uint32_t internalImageChrBaseR[2]; + uint32_t cpDistanceMbs; + uint32_t* cpTargetResults; + const uint32_t* cpTarget; + const int32_t* targetError; + const int32_t* deltaQp; + uint32_t rlcCount; + uint32_t qpSum; + uint32_t h264StrmMode; /* 0 - byte stream, 1 - NAL units */ + uint8_t quantTable[8 * 8 * 2]; + uint8_t dmvPenalty[ASIC_PENALTY_TABLE_SIZE]; + uint8_t dmvQpelPenalty[ASIC_PENALTY_TABLE_SIZE]; + uint32_t jpegMode; + uint32_t jpegSliceEnable; + uint32_t jpegRestartInterval; + uint32_t jpegRestartMarker; + uint32_t regMirror[ASIC_SWREG_AMOUNT]; + uint32_t inputLumaBaseOffsetVert; + uint32_t h264Inter4x4Disabled; + uint32_t disableQuarterPixelMv; + uint32_t vsNextLumaBase; + uint32_t vsMode; + uint32_t asicCfgReg; + int32_t intra16Favor; + int32_t prevModeFavor; + int32_t interFavor; + int32_t skipPenalty; + int32_t goldenPenalty; + int32_t diffMvPenalty[3]; + int32_t madQpDelta; + uint32_t madThreshold; + uint32_t madCount; + uint32_t mvcAnchorPicFlag; + uint32_t mvcPriorityId; + uint32_t mvcViewId; + uint32_t mvcTemporalId; + uint32_t mvcInterViewFlag; + uint32_t cirStart; + uint32_t cirInterval; + uint32_t intraSliceMap1; + uint32_t intraSliceMap2; + uint32_t intraSliceMap3; + uint32_t intraAreaTop; + uint32_t intraAreaLeft; + uint32_t intraAreaBottom; + uint32_t intraAreaRight; + uint32_t roi1Top; + uint32_t roi1Left; + uint32_t roi1Bottom; + uint32_t roi1Right; + uint32_t roi2Top; + uint32_t roi2Left; + uint32_t roi2Bottom; + uint32_t roi2Right; + int32_t roi1DeltaQp; + int32_t roi2DeltaQp; + uint32_t mvOutputBase; + uint32_t cabacCtxBase; + uint32_t probCountBase; + uint32_t segmentMapBase; + uint32_t colorConversionCoeffA; + uint32_t colorConversionCoeffB; + uint32_t colorConversionCoeffC; + uint32_t colorConversionCoeffE; + uint32_t colorConversionCoeffF; + uint32_t rMaskMsb; + uint32_t gMaskMsb; + uint32_t bMaskMsb; + uint32_t partitionOffset[8]; + uint32_t partitionBase[8]; + uint32_t qpY1QuantDc[4]; + uint32_t qpY1QuantAc[4]; + uint32_t qpY2QuantDc[4]; + uint32_t qpY2QuantAc[4]; + uint32_t qpChQuantDc[4]; + uint32_t qpChQuantAc[4]; + uint32_t qpY1ZbinDc[4]; + uint32_t qpY1ZbinAc[4]; + uint32_t qpY2ZbinDc[4]; + uint32_t qpY2ZbinAc[4]; + uint32_t qpChZbinDc[4]; + uint32_t qpChZbinAc[4]; + uint32_t qpY1RoundDc[4]; + uint32_t qpY1RoundAc[4]; + uint32_t qpY2RoundDc[4]; + uint32_t qpY2RoundAc[4]; + uint32_t qpChRoundDc[4]; + uint32_t qpChRoundAc[4]; + uint32_t qpY1DequantDc[4]; + uint32_t qpY1DequantAc[4]; + uint32_t qpY2DequantDc[4]; + uint32_t qpY2DequantAc[4]; + uint32_t qpChDequantDc[4]; + uint32_t qpChDequantAc[4]; + uint32_t segmentEnable; + uint32_t segmentMapUpdate; + uint32_t mvRefIdx[2]; + uint32_t ref2Enable; + uint32_t boolEncValue; + uint32_t boolEncValueBits; + uint32_t boolEncRange; + uint32_t dctPartitions; + uint32_t filterLevel[4]; + uint32_t filterSharpness; + uint32_t intraModePenalty[4]; + uint32_t intraBmodePenalty[10]; + uint32_t zeroMvFavorDiv2; + uint32_t splitMvMode; + uint32_t splitPenalty[4]; + int32_t lfRefDelta[4]; + int32_t lfModeDelta[4]; +} regValues_s; + +#define FRAME_HEADER_SIZE 256 +typedef struct +{ + regValues_s regs; + VPUMemLinear_t internalImageLuma[3]; + VPUMemLinear_t internalImageChroma[4]; + VPUMemLinear_t cabacCtx; + VPUMemLinear_t probCount; + VPUMemLinear_t segmentMap; + uint32_t sizeTblSize; + uint32_t traceRecon; + uint8_t hdr[FRAME_HEADER_SIZE + 8]; + uint32_t frmHdrBufLen; + uint8_t *frmhdr; +} asicData_s; + +int32_t VP8_EncAsicControllerInit(asicData_s* asic); + +int32_t VP8_EncAsicMemAlloc_V2( + asicData_s* asic, uint32_t width, uint32_t height, uint32_t encodingType, + uint32_t numRefBuffsLum, uint32_t numRefBuffsChr); + +void VP8_EncAsicMemFree_V2(asicData_s* asic); + +void VP8_EncAsicFrameStart(regValues_s* val); + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller_v2.c b/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller_v2.c new file mode 100644 index 0000000..ebd1802 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/encasiccontroller_v2.c @@ -0,0 +1,80 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include <malloc.h> +#include <memory.h> +#include "encasiccontroller.h" +#include "enccommon.h" + +int32_t VP8_EncAsicMemAlloc_V2(asicData_s* asic, uint32_t width, uint32_t height, + uint32_t encodingType, uint32_t numRefBuffsLum, + uint32_t numRefBuffsChr) { + uint32_t mbTotal, cabacTablSize; + regValues_s* regs; + + ASSERT(asic != NULL); + ASSERT(width != 0); + ASSERT(height != 0); + ASSERT((height % 2) == 0); + ASSERT((width % 4) == 0); + + regs = &asic->regs; + + regs->codingType = encodingType; + + width = (width + 15) / 16; + height = (height + 15) / 16; + + mbTotal = width * height; + + /* H264: CABAC context tables: all qps, intra+inter, 464 bytes/table. + * VP8: The same table is used for probability tables, 1208 bytes. */ + cabacTablSize = 8 * 55 + 8 * 96; + + if (VPUMallocLinear(&asic->cabacCtx, cabacTablSize) != 0) { + VP8_EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->cabacCtxBase = asic->cabacCtx.phy_addr; + + /* VP8: Table of counter for probability updates. */ + if (VPUMallocLinear(&asic->probCount, ASIC_VP8_PROB_COUNT_SIZE) != 0) { + VP8_EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->probCountBase = asic->probCount.phy_addr; + + /* VP8: Segmentation map, 4 bits/mb, 64-bit multiple. */ + if (VPUMallocLinear(&asic->segmentMap, (mbTotal * 4 + 63) / 64 * 8) != 0) { + VP8_EncAsicMemFree_V2(asic); + return ENCHW_NOK; + } + regs->segmentMapBase = asic->segmentMap.phy_addr; + + memset(asic->segmentMap.vir_addr, 0, asic->segmentMap.size); + + asic->frmhdr = (uint8_t*)(((int)asic->hdr + 7) & (~7)); + asic->frmHdrBufLen = FRAME_HEADER_SIZE; + + return ENCHW_OK; +} + +void VP8_EncAsicMemFree_V2(asicData_s* asic) { + ASSERT(asic != NULL); + VPUFreeLinear(&asic->cabacCtx); + VPUFreeLinear(&asic->probCount); +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/enccfg.h b/libv4l-rockchip/libvpu/vp8_enc/enccfg.h new file mode 100644 index 0000000..2a24267 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/enccfg.h @@ -0,0 +1,190 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _ENCCFG_H_ +#define _ENCCFG_H_ + +#include <stdint.h> + +/* The default values for the encoder build-time configuration are defined here. + * You can override these settings by defining the values as compiler flags in + * the Makefile. + */ + +/* The input image's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC input YUV + * 1 = 64-bit endianess */ +#ifndef ENCH1_INPUT_SWAP_32_YUV +#define ENCH1_INPUT_SWAP_32_YUV 1 +#endif + +/* The input image's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC input YUV + */ +#ifndef ENCH1_INPUT_SWAP_16_YUV +#define ENCH1_INPUT_SWAP_16_YUV 1 +#endif + +/* The input image's 8-bit swap: 0 or 1 + * This defines the byte endianess of the ASIC input YUV + */ +#ifndef ENCH1_INPUT_SWAP_8_YUV +#define ENCH1_INPUT_SWAP_8_YUV 1 +#endif + +/* The input image's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC input RGB16 + * 1 = 64-bit endianess */ +#ifndef ENCH1_INPUT_SWAP_32_RGB16 +#define ENCH1_INPUT_SWAP_32_RGB16 1 +#endif + +/* The input image's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC input RGB16 + */ +#ifndef ENCH1_INPUT_SWAP_16_RGB16 +#define ENCH1_INPUT_SWAP_16_RGB16 1 +#endif + +/* The input image's byte swap: 0 or 1 + * This defines the byte endianess of the ASIC input RGB16 + */ +#ifndef ENCH1_INPUT_SWAP_8_RGB16 +#define ENCH1_INPUT_SWAP_8_RGB16 0 +#endif + +/* The input image's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC input RGB32 + * 1 = 64-bit endianess */ +#ifndef ENCH1_INPUT_SWAP_32_RGB32 +#define ENCH1_INPUT_SWAP_32_RGB32 1 +#endif + +/* The input image's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC input RGB32 + */ +#ifndef ENCH1_INPUT_SWAP_16_RGB32 +#define ENCH1_INPUT_SWAP_16_RGB32 0 +#endif + +/* The input image's byte swap: 0 or 1 + * This defines the byte endianess of the ASIC input RGB32 + */ +#ifndef ENCH1_INPUT_SWAP_8_RGB32 +#define ENCH1_INPUT_SWAP_8_RGB32 0 +#endif + +/* ENCH1_OUTPUT_SWAP_XX define the byte endianess of the ASIC output data. + * This MUST be configured to be the same as the native system endianess, + * because the control software relies on system endianess when reading + * the data from the memory. */ + +/* The output data's 32-bit swap: 0 or 1 + * This defines the 32-bit endianess of the ASIC output data + * 1 = 64-bit endianess */ +#ifndef ENCH1_OUTPUT_SWAP_32 +#define ENCH1_OUTPUT_SWAP_32 1 +#endif + +/* The output data's 16-bit swap: 0 or 1 + * This defines the 16-bit endianess of the ASIC output data. + */ +#ifndef ENCH1_OUTPUT_SWAP_16 +#define ENCH1_OUTPUT_SWAP_16 1 +#endif + +/* The output data's 8-bit swap: 0 or 1 + * This defines the byte endianess of the ASIC output data. + */ +#ifndef ENCH1_OUTPUT_SWAP_8 +#define ENCH1_OUTPUT_SWAP_8 1 +#endif + +/* ASIC interrupt enable. + * This enables/disables the ASIC to generate interrupts + * If this is '1', the EWL must poll the registers to find out + * when the HW is ready. + */ +#ifndef ENCH1_IRQ_DISABLE +#define ENCH1_IRQ_DISABLE 0 +#endif + +/* ASIC bus interface configuration values */ +/* DO NOT CHANGE IF NOT FAMILIAR WITH THE CONCEPTS INVOLVED */ + +/* Burst length. This sets the maximum length of a single ASIC burst in addresses. + * Allowed values are: + * AHB {0, 4, 8, 16} ( 0 means incremental burst type INCR) + * OCP [1,63] + * AXI [1,16] + */ +#ifndef ENCH1_BURST_LENGTH +#define ENCH1_BURST_LENGTH 16 +#endif + +/* SCMD burst mode disable */ +/* 0 - enable SCMD burst mode */ +/* 1 - disable SCMD burst mode */ +#ifndef ENCH1_BURST_SCMD_DISABLE +#define ENCH1_BURST_SCMD_DISABLE 0 +#endif + +/* INCR type burst mode */ +/* 0 - enable INCR type bursts */ +/* 1 - disable INCR type and use SINGLE instead */ +#ifndef ENCH1_BURST_INCR_TYPE_ENABLED +#define ENCH1_BURST_INCR_TYPE_ENABLED 0 +#endif + +/* Data discard mode. When enabled read bursts of length 2 or 3 are converted */ +/* to BURST4 and useless data is discarded. Otherwise use INCR type for that */ +/* kind of read bursts */ +/* 0 - disable data discard */ +/* 1 - enable data discard */ +#ifndef ENCH1_BURST_DATA_DISCARD_ENABLED +#define ENCH1_BURST_DATA_DISCARD_ENABLED 0 +#endif + +/* AXI bus read and write ID values used by HW. 0 - 255 */ +#ifndef ENCH1_AXI_READ_ID +#define ENCH1_AXI_READ_ID 0 +#endif + +#ifndef ENCH1_AXI_WRITE_ID +#define ENCH1_AXI_WRITE_ID 0 +#endif + +/* End of "ASIC bus interface configuration values" */ + +/* ASIC internal clock gating control. 0 - disabled, 1 - enabled */ +#ifndef ENCH1_ASIC_CLOCK_GATING_ENABLED +#define ENCH1_ASIC_CLOCK_GATING_ENABLED 0 +#endif + +/* ASIC timeout interrupt enable/disable */ +#ifndef ENCH1_TIMEOUT_INTERRUPT +#define ENCH1_TIMEOUT_INTERRUPT 1 +#endif + +/* H.264 slice ready interrupt enable/disable. When enabled the HW will raise */ +/* interrupt after every completed slice creating several IRQ per frame. */ +/* When disabled the HW will raise interrupt only when the frame encoding is */ +/* finished. */ +#ifndef ENCH1_SLICE_READY_INTERRUPT +#define ENCH1_SLICE_READY_INTERRUPT 1 +#endif + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/enccommon.h b/libv4l-rockchip/libvpu/vp8_enc/enccommon.h new file mode 100644 index 0000000..dc9eeb5 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/enccommon.h @@ -0,0 +1,43 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _ENC_COMMON_H_ +#define _ENC_COMMON_H_ + +#define ASSERT(expr) +#define COMMENT(x) +#define TRACE_BIT_STREAM(v,n) + +typedef enum +{ + ENCHW_NOK = -1, + ENCHW_OK = 0 +} bool_e; + +typedef enum +{ + ENCHW_NO = 0, + ENCHW_YES = 1 +} true_e; + +/* General tools */ +#define ABS(x) ((x) < (0) ? -(x) : (x)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define SIGN(a) ((a) < (0) ? (-1) : (1)) +#define CLIP3(v, min, max) ((v) < (min) ? (min) : ((v) > (max) ? (max) : (v))) + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/encswhwregisters.h b/libv4l-rockchip/libvpu/vp8_enc/encswhwregisters.h new file mode 100644 index 0000000..5b1b35f --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/encswhwregisters.h @@ -0,0 +1,527 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _ENC_SWHWREGISTERS_H_ +#define _ENC_SWHWREGISTERS_H_ + +#include <stdint.h> + +#define ASIC_SWREG_AMOUNT (0x28C/4+1) + +#define ASIC_INPUT_YUV420PLANAR 0x00 +#define ASIC_INPUT_YUV420SEMIPLANAR 0x01 +#define ASIC_INPUT_YUYV422INTERLEAVED 0x02 +#define ASIC_INPUT_UYVY422INTERLEAVED 0x03 +#define ASIC_INPUT_RGB565 0x04 +#define ASIC_INPUT_RGB555 0x05 +#define ASIC_INPUT_RGB444 0x06 +#define ASIC_INPUT_RGB888 0x07 +#define ASIC_INPUT_RGB101010 0x08 + +/* Bytes of external memory for VP8 counters for probability updates, + * 252 counters for dct coeff probs, 1 for skipped, 1 for intra type and + * 2 * 11 for mv probs, each counter 2 bytes */ +#define ASIC_VP8_PROB_COUNT_SIZE (244*2) +#define ASIC_VP8_PROB_COUNT_MODE_OFFSET 220 +#define ASIC_VP8_PROB_COUNT_MV_OFFSET 222 + +/* HW Register field names */ +typedef enum { + HEncProductID, + HEncProductMajor, + HEncProductMinor, + HEncProductBuild, + + HEncIRQSliceReady, + HEncIRQTimeout, + HEncIRQBuffer, + HEncIRQReset, + HEncIRQBusError, + HEncIRQFrameReady, + HEncIRQDisable, + HEncIRQ, + + HEncAXIWriteID, + HEncAXIReadID, + HEncOutputSwap16, + HEncInputSwap16, + HEncBurstLength, + HEncBurstDisable, + HEncBurstIncr, + HEncDataDiscard, + HEncClockGating, + HEncOutputSwap32, + HEncInputSwap32, + HEncOutputSwap8, + HEncInputSwap8, + + HEncTestCounter, + HEncTestLength, + HEncTestMem, + HEncTestReg, + HEncTestIrq, + + HEncBaseStream, + HEncBaseControl, + HEncBaseRefLum, + HEncBaseRefChr, + HEncBaseRecLum, + HEncBaseRecChr, + HEncBaseInLum, + HEncBaseInCb, + HEncBaseInCr, + + HEncIntTimeout, + HEncMvWrite, + HEncNalSizeWrite, + HEncIntSliceReady, + HEncWidth, + HEncHeight, + HEncRecWriteDisable, + HEncPictureType, + HEncEncodingMode, + HEncEnable, + + HEncChrOffset, + HEncLumOffset, + HEncRowLength, + HEncXFill, + HEncYFill, + HEncInputFormat, + HEncInputRot, + + HEncBaseRefLum2, + HEncBaseRefChr2, + HEncPicInitQp, + HEncSliceAlpha, + HEncSliceBeta, + HEncChromaQp, + HEncIdrPicId, + HEncConstrIP, + HEncPPSID, + HEncIPPrevModeFavor, + HEncFrameNum, + + HEncDeblocking, + HEncSliceSize, + HEncDisableQPMV, + HEncTransform8x8, + HEncCabacInitIdc, + HEncCabacEnable, + HEncInter4Restrict, + HEncStreamMode, + HEncIPIntra16Favor, + + HEncSplitMv, + HEncDMVPenalty1p, + HEncDMVPenalty4p, + HEncDMVPenaltyQp, + + HEncJpegMode, + HEncJpegSlice, + HEncJpegRSTInt, + HEncJpegRST, + HEncSplitPenalty16x8, + HEncSplitPenalty8x8, + HEncSplitPenalty8x4, + + HEncSkipPenalty, + HEncNumSlicesReady, + HEncInterFavor, + + HEncStrmHdrRem1, + HEncStrmHdrRem2, + + HEncStrmBufLimit, + + HEncMadQpDelta, + HEncMadThreshold, + HEncQpSum, + + HEncQp, + HEncMaxQp, + HEncMinQp, + HEncCPDist, + + HEncCP1WordTarget, + HEncCP2WordTarget, + HEncCP3WordTarget, + HEncCP4WordTarget, + HEncCP5WordTarget, + HEncCP6WordTarget, + HEncCP7WordTarget, + HEncCP8WordTarget, + HEncCP9WordTarget, + HEncCP10WordTarget, + + HEncCPWordError1, + HEncCPWordError2, + HEncCPWordError3, + HEncCPWordError4, + HEncCPWordError5, + HEncCPWordError6, + + HEncCPDeltaQp1, + HEncCPDeltaQp2, + HEncCPDeltaQp3, + HEncCPDeltaQp4, + HEncCPDeltaQp5, + HEncCPDeltaQp6, + HEncCPDeltaQp7, + + HEncVp8Y1QuantDc, + HEncVp8Y1ZbinDc, + HEncVp8Y1RoundDc, + HEncVp8Y1QuantAc, + HEncVp8Y1ZbinAc, + HEncVp8Y1RoundAc, + HEncVp8Y2QuantDc, + HEncVp8Y2ZbinDc, + HEncVp8Y2RoundDc, + HEncVp8Y2QuantAc, + HEncVp8Y2ZbinAc, + HEncVp8Y2RoundAc, + HEncVp8ChQuantDc, + HEncVp8ChZbinDc, + HEncVp8ChRoundDc, + HEncVp8ChQuantAc, + HEncVp8ChZbinAc, + HEncVp8ChRoundAc, + + HEncVp8Y1DequantDc, + HEncVp8Y1DequantAc, + HEncVp8Y2DequantDc, + HEncVp8MvRefIdx, + HEncVp8Y2DequantAc, + HEncVp8ChDequantDc, + HEncVp8ChDequantAc, + HEncVp8MvRefIdx2, + HEncVp8Ref2Enable, + HEncVp8SegmentEnable, + HEncVp8SegmentMapUpdate, + + HEncVp8BoolEncValue, + HEncVp8GoldenPenalty, + HEncVp8FilterSharpness, + HEncVp8FilterLevel, + HEncVp8DctPartitionCount, + HEncVp8BoolEncValueBits, + HEncVp8BoolEncRange, + + HEncStartOffset, + HEncRlcSum, + HEncMadCount, + HEncMbCount, + + HEncBaseNextLum, + + HEncStabMode, + HEncStabMinimum, + HEncStabMotionSum, + HEncStabGmvX, + HEncStabMatrix1, + HEncStabGmvY, + HEncStabMatrix2, + HEncStabMatrix3, + HEncStabMatrix4, + HEncStabMatrix5, + HEncStabMatrix6, + HEncStabMatrix7, + HEncStabMatrix8, + HEncStabMatrix9, + + HEncBaseCabacCtx, + HEncBaseMvWrite, + + HEncRGBCoeffA, + HEncRGBCoeffB, + HEncRGBCoeffC, + HEncRGBCoeffE, + HEncRGBCoeffF, + + HEncRMaskMSB, + HEncGMaskMSB, + HEncBMaskMSB, + + HEncIntraAreaLeft, + HEncIntraAreaRight, + HEncIntraAreaTop, + HEncIntraAreaBottom, + + HEncCirStart, + HEncCirInterval, + + HEncIntraSliceMap1, + HEncIntraSliceMap2, + HEncIntraSliceMap3, + HEncBasePartition1, + HEncBasePartition2, + HEncBaseVp8ProbCount, + + HEncRoi1Left, + HEncRoi1Right, + HEncRoi1Top, + HEncRoi1Bottom, + + HEncRoi2Left, + HEncRoi2Right, + HEncRoi2Top, + HEncRoi2Bottom, + + HEncRoi1DeltaQp, + HEncRoi2DeltaQp, + HEncZeroMvFavor, + HEncSplitPenalty4x4, + + HEncMvcPriorityId, + HEncMvcViewId, + HEncMvcTemporalId, + HEncMvcAnchorPicFlag, + HEncMvcInterViewFlag, + + HEncHWTiledSupport, + HEncHWSearchArea, + HEncHWRgbSupport, + HEncHWH264Support, + HEncHWVp8Support, + HEncHWJpegSupport, + HEncHWStabSupport, + HEncHWBus, + HEncHWSynthesisLan, + HEncHWBusWidth, + HEncHWMaxVideoWidth, + + HEncJpegQuantLuma1, + HEncJpegQuantLuma2, + HEncJpegQuantLuma3, + HEncJpegQuantLuma4, + HEncJpegQuantLuma5, + HEncJpegQuantLuma6, + HEncJpegQuantLuma7, + HEncJpegQuantLuma8, + HEncJpegQuantLuma9, + HEncJpegQuantLuma10, + HEncJpegQuantLuma11, + HEncJpegQuantLuma12, + HEncJpegQuantLuma13, + HEncJpegQuantLuma14, + HEncJpegQuantLuma15, + HEncJpegQuantLuma16, + + HEncJpegQuantChroma1, + HEncJpegQuantChroma2, + HEncJpegQuantChroma3, + HEncJpegQuantChroma4, + HEncJpegQuantChroma5, + HEncJpegQuantChroma6, + HEncJpegQuantChroma7, + HEncJpegQuantChroma8, + HEncJpegQuantChroma9, + HEncJpegQuantChroma10, + HEncJpegQuantChroma11, + HEncJpegQuantChroma12, + HEncJpegQuantChroma13, + HEncJpegQuantChroma14, + HEncJpegQuantChroma15, + HEncJpegQuantChroma16, + + /* VP8 penalty registers */ + HEncVp8Mode0Penalty, + HEncVp8Mode1Penalty, + HEncVp8Mode2Penalty, + HEncVp8Mode3Penalty, + HEncVp8Bmode0Penalty, + HEncVp8Bmode1Penalty, + HEncVp8Bmode2Penalty, + HEncVp8Bmode3Penalty, + HEncVp8Bmode4Penalty, + HEncVp8Bmode5Penalty, + HEncVp8Bmode6Penalty, + HEncVp8Bmode7Penalty, + HEncVp8Bmode8Penalty, + HEncVp8Bmode9Penalty, + HEncBaseVp8SegmentMap, + HEncVp8Seg1Y1QuantDc, + HEncVp8Seg1Y1ZbinDc, + HEncVp8Seg1Y1RoundDc, + HEncVp8Seg1Y1QuantAc, + HEncVp8Seg1Y1ZbinAc, + HEncVp8Seg1Y1RoundAc, + HEncVp8Seg1Y2QuantDc, + HEncVp8Seg1Y2ZbinDc, + HEncVp8Seg1Y2RoundDc, + HEncVp8Seg1Y2QuantAc, + HEncVp8Seg1Y2ZbinAc, + HEncVp8Seg1Y2RoundAc, + HEncVp8Seg1ChQuantDc, + HEncVp8Seg1ChZbinDc, + HEncVp8Seg1ChRoundDc, + HEncVp8Seg1ChQuantAc, + HEncVp8Seg1ChZbinAc, + HEncVp8Seg1ChRoundAc, + HEncVp8Seg1Y1DequantDc, + HEncVp8Seg1Y1DequantAc, + HEncVp8Seg1Y2DequantDc, + HEncVp8Seg1Y2DequantAc, + HEncVp8Seg1ChDequantDc, + HEncVp8Seg1ChDequantAc, + HEncVp8Seg1FilterLevel, + HEncVp8Seg2Y1QuantDc, + HEncVp8Seg2Y1ZbinDc, + HEncVp8Seg2Y1RoundDc, + HEncVp8Seg2Y1QuantAc, + HEncVp8Seg2Y1ZbinAc, + HEncVp8Seg2Y1RoundAc, + HEncVp8Seg2Y2QuantDc, + HEncVp8Seg2Y2ZbinDc, + HEncVp8Seg2Y2RoundDc, + HEncVp8Seg2Y2QuantAc, + HEncVp8Seg2Y2ZbinAc, + HEncVp8Seg2Y2RoundAc, + HEncVp8Seg2ChQuantDc, + HEncVp8Seg2ChZbinDc, + HEncVp8Seg2ChRoundDc, + HEncVp8Seg2ChQuantAc, + HEncVp8Seg2ChZbinAc, + HEncVp8Seg2ChRoundAc, + HEncVp8Seg2Y1DequantDc, + HEncVp8Seg2Y1DequantAc, + HEncVp8Seg2Y2DequantDc, + HEncVp8Seg2Y2DequantAc, + HEncVp8Seg2ChDequantDc, + HEncVp8Seg2ChDequantAc, + HEncVp8Seg2FilterLevel, + HEncVp8Seg3Y1QuantDc, + HEncVp8Seg3Y1ZbinDc, + HEncVp8Seg3Y1RoundDc, + HEncVp8Seg3Y1QuantAc, + HEncVp8Seg3Y1ZbinAc, + HEncVp8Seg3Y1RoundAc, + HEncVp8Seg3Y2QuantDc, + HEncVp8Seg3Y2ZbinDc, + HEncVp8Seg3Y2RoundDc, + HEncVp8Seg3Y2QuantAc, + HEncVp8Seg3Y2ZbinAc, + HEncVp8Seg3Y2RoundAc, + HEncVp8Seg3ChQuantDc, + HEncVp8Seg3ChZbinDc, + HEncVp8Seg3ChRoundDc, + HEncVp8Seg3ChQuantAc, + HEncVp8Seg3ChZbinAc, + HEncVp8Seg3ChRoundAc, + HEncVp8Seg3Y1DequantDc, + HEncVp8Seg3Y1DequantAc, + HEncVp8Seg3Y2DequantDc, + HEncVp8Seg3Y2DequantAc, + HEncVp8Seg3ChDequantDc, + HEncVp8Seg3ChDequantAc, + HEncVp8Seg3FilterLevel, + + HEncDmvPenalty1, + HEncDmvPenalty2, + HEncDmvPenalty3, + HEncDmvPenalty4, + HEncDmvPenalty5, + HEncDmvPenalty6, + HEncDmvPenalty7, + HEncDmvPenalty8, + HEncDmvPenalty9, + HEncDmvPenalty10, + HEncDmvPenalty11, + HEncDmvPenalty12, + HEncDmvPenalty13, + HEncDmvPenalty14, + HEncDmvPenalty15, + HEncDmvPenalty16, + HEncDmvPenalty17, + HEncDmvPenalty18, + HEncDmvPenalty19, + HEncDmvPenalty20, + HEncDmvPenalty21, + HEncDmvPenalty22, + HEncDmvPenalty23, + HEncDmvPenalty24, + HEncDmvPenalty25, + HEncDmvPenalty26, + HEncDmvPenalty27, + HEncDmvPenalty28, + HEncDmvPenalty29, + HEncDmvPenalty30, + HEncDmvPenalty31, + HEncDmvPenalty32, + + HEncDmvQpelPenalty1, + HEncDmvQpelPenalty2, + HEncDmvQpelPenalty3, + HEncDmvQpelPenalty4, + HEncDmvQpelPenalty5, + HEncDmvQpelPenalty6, + HEncDmvQpelPenalty7, + HEncDmvQpelPenalty8, + HEncDmvQpelPenalty9, + HEncDmvQpelPenalty10, + HEncDmvQpelPenalty11, + HEncDmvQpelPenalty12, + HEncDmvQpelPenalty13, + HEncDmvQpelPenalty14, + HEncDmvQpelPenalty15, + HEncDmvQpelPenalty16, + HEncDmvQpelPenalty17, + HEncDmvQpelPenalty18, + HEncDmvQpelPenalty19, + HEncDmvQpelPenalty20, + HEncDmvQpelPenalty21, + HEncDmvQpelPenalty22, + HEncDmvQpelPenalty23, + HEncDmvQpelPenalty24, + HEncDmvQpelPenalty25, + HEncDmvQpelPenalty26, + HEncDmvQpelPenalty27, + HEncDmvQpelPenalty28, + HEncDmvQpelPenalty29, + HEncDmvQpelPenalty30, + HEncDmvQpelPenalty31, + HEncDmvQpelPenalty32, + + HEncVp8CostInter, + HEncVp8DmvCostConst, + HEncVp8CostGoldenRef, + + /* VP8 loop filter deltas */ + HEncVp8LfRefDelta0, + HEncVp8LfRefDelta1, + HEncVp8LfRefDelta2, + HEncVp8LfRefDelta3, + HEncVp8LfModeDelta0, + HEncVp8LfModeDelta1, + HEncVp8LfModeDelta2, + HEncVp8LfModeDelta3, + + HEncRegisterAmount + +} regName; + +/* HW Register field descriptions */ +typedef struct { + int32_t name; /* Register name and index */ + int32_t base; /* Register base address */ + uint32_t mask; /* Bitmask for this field */ + int32_t lsb; /* LSB for this field [31..0] */ + int32_t trace; /* Enable/disable writing in swreg_params.trc */ + char* description; /* Field description */ +} regField_s; + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c b/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c new file mode 100644 index 0000000..ed3cc6e --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c @@ -0,0 +1,735 @@ +/* Copyright 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "rk_vp8encapi.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "enccommon.h" +#include "vp8encapi.h" +#include "vp8instance.h" +#include "libvpu/rk_vepu_debug.h" +#include "libvpu/vp8_enc/vpu_mem.h" + +/* Value for parameter to use API default */ +#define DEFAULT -100 + +/* Intermediate Video File Format */ +#define IVF_HDR_BYTES 32 +#define IVF_FRM_BYTES 12 + +#define PRIVATE_DATA_HEADER_SIZE 192 + +static int rk_vp8_encoder_after_encode(struct rk_vp8_encoder *enc, + uint32_t outputStreamSize); +static int rk_vp8_encoder_before_encode(struct rk_vp8_encoder *enc); +static int rk_vp8_encoder_init(struct rk_vp8_encoder *enc, + struct rk_vepu_init_param *enc_parms); +static void rk_vp8_encoder_genpriv(struct rk_vp8_encoder *enc); +static void rk_vp8_encoder_getpriv(struct rk_vp8_encoder *enc, + uint8_t **priv_data, uint32_t *size); +static void rk_vp8_encoder_setconfig(struct rk_vp8_encoder *enc, + struct rk_vepu_runtime_param *param); +static void rk_vp8_encoder_store_priv_data(struct rk_vp8_encoder *enc, + uint8_t *priv, uint32_t size, + int32_t type); +static int rk_vp8_encoder_updatepriv(struct rk_vp8_encoder *enc, + void *config, uint32_t cfglen); +static int OpenEncoder(EncoderParameters* cml, VP8EncInst* pEnc); +static void CloseEncoder(VP8EncInst encoder); +static void MaAddFrame(ma_s* ma, int32_t frameSizeBits); +static int32_t Ma(ma_s* ma); +static void SetDefaultParameter(EncoderParameters* tb); + + +static int rk_vp8_encoder_init(struct rk_vp8_encoder *enc, + struct rk_vepu_init_param *enc_parms) { + EncoderParameters* cml = &enc->cmdl; + + SetDefaultParameter(cml); + + /* modify parameters using input encode setting */ + cml->lumWidthSrc = enc_parms->width; + cml->lumHeightSrc = enc_parms->height; + cml->width = enc_parms->width; + cml->height = enc_parms->height; + + switch (enc_parms->input_format) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV420M: + cml->inputFormat = VP8ENC_YUV420_PLANAR; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12M: + cml->inputFormat = VP8ENC_YUV420_SEMIPLANAR; + break; + case V4L2_PIX_FMT_YUYV: + cml->inputFormat = VP8ENC_YUV422_INTERLEAVED_YUYV; + break; + case V4L2_PIX_FMT_UYVY: + cml->inputFormat = VP8ENC_YUV422_INTERLEAVED_UYVY; + break; + default: + VPU_PLG_ERR("Unsupport format 0x%08x\n", enc_parms->input_format); + return -1; + } + + /* Encoder initialization */ + if (OpenEncoder(cml, &enc->encoder) != 0) + return -1; + + /* First frame is always intra with zero time increment */ + enc->encIn.codingType = VP8ENC_INTRA_FRAME; + enc->encIn.timeIncrement = 0; + + enc->priv_data = (uint8_t *)calloc(1, 5487); + if (enc->priv_data == NULL) { + VPU_PLG_ERR("allocate private data buffer failed\n"); + CloseEncoder(enc->encoder); + return -1; + } + + enc->hdr_idx = 0; + enc->priv_offset = 0; + return 0; +} + +static void rk_vp8_encoder_setconfig(struct rk_vp8_encoder *enc, + struct rk_vepu_runtime_param *param) +{ + int ret; + vp8Instance_s *pEncInst = (vp8Instance_s *)enc->encoder; + VP8EncRateCtrl rc; + pEncInst->encStatus = VP8ENCSTAT_INIT; + VP8EncGetRateCtrl(enc->encoder, &rc); + if (param->bitrate != 0) { + rc.bitPerSecond = param->bitrate; + rc.pictureRc = ENCHW_YES; + rc.qpHdr = -1; + } + + if (param->framerate_denom != 0 && param->framerate_numer != 0) { + pEncInst->rateControl.outRateNum = param->framerate_numer; + pEncInst->rateControl.outRateDenom = param->framerate_denom; + enc->cmdl.outputRateDenom = param->framerate_denom; + enc->cmdl.outputRateNumer = param->framerate_numer; + } + + ret = VP8EncSetRateCtrl(enc->encoder, &rc); + if (ret < 0) { + VPU_PLG_ERR("failed to set rate control\n"); + } + + VPU_PLG_INF("Reset bitrate calculation parameters\n"); + enc->cmdl.streamSize = 0; + enc->cmdl.frameCntTotal = 0; + + if (param->keyframe_request) { + enc->encIn.codingType = + param->keyframe_value ? VP8ENC_INTRA_FRAME : VP8ENC_PREDICTED_FRAME; + } +} + +static int rk_vp8_encoder_after_encode(struct rk_vp8_encoder *enc, + uint32_t outputStreamSize) { + VP8EncRet ret; + EncoderParameters* cml = &enc->cmdl; + + ret = VP8EncStrmEncodeResult(enc->encoder, &cml->encOut, outputStreamSize); + + VP8EncGetRateCtrl(enc->encoder, &cml->rc); + + cml->streamSize += cml->encOut.frameSize; + + MaAddFrame(&cml->ma, cml->encOut.frameSize * 8); + + enc->encIn.timeIncrement = cml->outputRateDenom; + + cml->frameCnt++; + cml->frameCntTotal++; + + if (cml->encOut.codingType != VP8ENC_NOTCODED_FRAME) { + enc->intraPeriodCnt++; + enc->codedFrameCnt++; + } + + /* calculate the bitrate using output stream size. */ + if ((cml->frameCntTotal + 1) && cml->outputRateDenom) { + /* Using 64-bits to avoid overflow */ + uint64_t tmp = cml->streamSize / (cml->frameCntTotal + 1); + tmp *= (uint32_t)cml->outputRateNumer; + + cml->bitrate = (uint32_t)(8 * (tmp / (uint32_t)cml->outputRateDenom)); + } + + /* Print information about encoded frames */ + VPU_PLG_INF("\nBitrate target %d bps, actual %d bps (%d%%).\n", + cml->rc.bitPerSecond, cml->bitrate, + (cml->rc.bitPerSecond) ? + cml->bitrate * 100 / cml->rc.bitPerSecond : 0); + VPU_PLG_INF("Total of %llu frames processed, %d frames encoded, %d bytes.\n", + cml->frameCntTotal, enc->codedFrameCnt, cml->streamSize); + + if (cml->psnrCnt) + VPU_PLG_INF("Average PSNR %d.%02d\n", + (cml->psnrSum / cml->psnrCnt) / 100, + (cml->psnrSum / cml->psnrCnt) % 100); + + return ret; +} + +static int rk_vp8_encoder_before_encode(struct rk_vp8_encoder *enc) { + int ret = 0; + EncoderParameters* cml = &enc->cmdl; + + cml->ma.pos = cml->ma.count = 0; + cml->ma.frameRateNumer = cml->outputRateNumer; + cml->ma.frameRateDenom = cml->outputRateDenom; + if (cml->outputRateDenom) + cml->ma.length = MAX(1, MIN(cml->outputRateNumer / cml->outputRateDenom, + MOVING_AVERAGE_FRAMES)); + else + cml->ma.length = MOVING_AVERAGE_FRAMES; + + /* Source Image Size */ + if (cml->inputFormat <= 1) { + enc->src_img_size = cml->lumWidthSrc * cml->lumHeightSrc + + 2 * (((cml->lumWidthSrc + 1) >> 1) * + ((cml->lumHeightSrc + 1) >> 1)); + } else if ((cml->inputFormat <= 9) || (cml->inputFormat == 14)) { + /* 422 YUV or 16-bit RGB */ + enc->src_img_size = cml->lumWidthSrc * cml->lumHeightSrc * 2; + } else { + /* 32-bit RGB */ + enc->src_img_size = cml->lumWidthSrc * cml->lumHeightSrc * 4; + } + + if (VP8EncGetRateCtrl(enc->encoder, &cml->rc) < 0) { + VPU_PLG_ERR("VP8 Get Rate Control failed\n"); + return -1; + } + + /* Select frame type */ + if ((cml->intraPicRate != 0) && (enc->intraPeriodCnt >= cml->intraPicRate)) + enc->encIn.codingType = VP8ENC_INTRA_FRAME; + else + enc->encIn.codingType = VP8ENC_PREDICTED_FRAME; + + if (enc->encIn.codingType == VP8ENC_INTRA_FRAME) + enc->intraPeriodCnt = 0; + + /* This applies for PREDICTED frames only. By default always predict + * from the previous frame only. */ + enc->encIn.ipf = VP8ENC_REFERENCE_AND_REFRESH; + enc->encIn.grf = enc->encIn.arf = VP8ENC_REFERENCE; + + /* Force odd frames to be coded as droppable. */ + if (cml->droppable && cml->frameCnt & 1) { + enc->encIn.codingType = VP8ENC_PREDICTED_FRAME; + enc->encIn.ipf = enc->encIn.grf = enc->encIn.arf = VP8ENC_REFERENCE; + } + + /* Encode one frame */ + ret = VP8EncStrmEncode(enc->encoder, &enc->encIn, &cml->encOut, cml); + if (ret < 0) { + VPU_PLG_ERR("Generate Encoder configuration failed\n"); + return -1; + } + + VP8EncGetFrameHeader(enc->encoder, (uint8_t**)&enc->rk_payloads[0], + &enc->rk_payload_sizes[0]); + VP8EncGetRegs(enc->encoder, (uint32_t**)&enc->rk_payloads[1], + &enc->rk_payload_sizes[1]); + rk_vp8_encoder_getpriv( + enc, (uint8_t**)&enc->rk_payloads[2], &enc->rk_payload_sizes[2]); + return 0; +} + +static void rk_vp8_encoder_store_priv_data(struct rk_vp8_encoder *enc, + uint8_t *priv, uint32_t size, + int32_t type) { + uint32_t* hdr = (uint32_t*)enc->priv_data; + uint8_t* data = (uint8_t*)enc->priv_data + PRIVATE_DATA_HEADER_SIZE; + + VPU_PLG_DBG("store type %02x, size %02x\n", type, size); + enc->priv_offset = (enc->priv_offset + 7) & (~7); + + hdr[enc->hdr_idx++] = type; + hdr[enc->hdr_idx++] = size; + hdr[enc->hdr_idx++] = enc->priv_offset; + + memcpy(data + enc->priv_offset, priv, size); + enc->priv_offset += size; +} + +static void rk_vp8_encoder_genpriv(struct rk_vp8_encoder *enc) { + uint8_t *priv; + uint32_t size; + + enc->hdr_idx = 0; + enc->priv_offset = 0; + VP8EncGetCabacCtx(enc->encoder, &priv, &size); + rk_vp8_encoder_store_priv_data(enc, priv, size, VP8E_PRIVATE_DATA_TYPE_CABAC); + VP8EncGetSegmentMap(enc->encoder, &priv, &size); + rk_vp8_encoder_store_priv_data(enc, priv, size, VP8E_PRIVATE_DATA_TYPE_SEGMAP); + rk_vp8_encoder_store_priv_data(enc, NULL, 0, VP8E_PRIVATE_DATA_TYPE_END); +} + +static void rk_vp8_encoder_getpriv(struct rk_vp8_encoder *enc, + uint8_t **priv_data, uint32_t *size) { + rk_vp8_encoder_genpriv(enc); + *priv_data = enc->priv_data; + *size = 5487; +} + +static int rk_vp8_encoder_updatepriv(struct rk_vp8_encoder *enc, + void *config, uint32_t cfglen) { + return VP8EncSetProbCnt(enc->encoder, (uint8_t *)config, cfglen); +} + +static void rk_vp8_encoder_deinit(struct rk_vp8_encoder *enc) { + free(enc->priv_data); + enc->priv_data = NULL; + CloseEncoder(enc->encoder); +} + +/*---------------------------------------------------------------------------- + + OpenEncoder + Create and configure an encoder instance. + + Params: + cml - processed command line options + pEnc - place where to save the new encoder instance + Return: + 0 - for success + -1 - error + +-----------------------------------------------------------------------------*/ +static int OpenEncoder(EncoderParameters* cml, VP8EncInst* pEnc) { + VP8EncRet ret; + VP8EncConfig cfg; + VP8EncCodingCtrl codingCfg; + VP8EncRateCtrl rcCfg; + + VP8EncInst encoder; + + /* input resolution == encoded resolution if not defined */ + if (cml->width == DEFAULT) + cml->width = cml->lumWidthSrc; + if (cml->height == DEFAULT) + cml->height = cml->lumHeightSrc; + + if (cml->rotation) { + cfg.width = cml->height; + cfg.height = cml->width; + } else { + cfg.width = cml->width; + cfg.height = cml->height; + } + + cfg.frameRateDenom = cml->outputRateDenom; + cfg.frameRateNum = cml->outputRateNumer; + cfg.refFrameAmount = cml->refFrameAmount; + + VPU_PLG_DBG("Init config: size %dx%d %d/%d fps %d refFrames\n", + cfg.width, cfg.height, cfg.frameRateNum, cfg.frameRateDenom, + cfg.refFrameAmount); + + if ((ret = VP8EncInit(&cfg, pEnc)) != VP8ENC_OK) { + VPU_PLG_ERR("VP8EncInit() failed. ret %d\n", ret); + return ret; + } + + encoder = *pEnc; + + /* Encoder setup: rate control */ + if ((ret = VP8EncGetRateCtrl(encoder, &rcCfg)) != VP8ENC_OK) { + VPU_PLG_ERR("VP8EncGetRateCtrl() failed. ret %d\n", ret); + CloseEncoder(encoder); + return -1; + } + + VPU_PLG_INF("Get rate control: qp=%2d [%2d..%2d] %8d bps," + " picRc=%d gop=%d\n", + rcCfg.qpHdr, rcCfg.qpMin, rcCfg.qpMax, rcCfg.bitPerSecond, + rcCfg.pictureRc, rcCfg.bitrateWindow); + + if (cml->picRc != DEFAULT) + rcCfg.pictureRc = cml->picRc; + if (cml->picSkip != DEFAULT) + rcCfg.pictureSkip = cml->picSkip; + if (cml->qpHdr != DEFAULT) + rcCfg.qpHdr = cml->qpHdr; + if (cml->qpMin != DEFAULT) + rcCfg.qpMin = cml->qpMin; + if (cml->qpMax != DEFAULT) + rcCfg.qpMax = cml->qpMax; + if (cml->bitPerSecond != DEFAULT) + rcCfg.bitPerSecond = cml->bitPerSecond; + if (cml->gopLength != DEFAULT) + rcCfg.bitrateWindow = cml->gopLength; + if (cml->intraQpDelta != DEFAULT) + rcCfg.intraQpDelta = cml->intraQpDelta; + if (cml->fixedIntraQp != DEFAULT) + rcCfg.fixedIntraQp = cml->fixedIntraQp; + + VPU_PLG_DBG("Set rate control: qp=%2d [%2d..%2d] %8d bps," + " picRc=%d gop=%d\n", + rcCfg.qpHdr, rcCfg.qpMin, rcCfg.qpMax, rcCfg.bitPerSecond, + rcCfg.pictureRc, rcCfg.bitrateWindow); + + if ((ret = VP8EncSetRateCtrl(encoder, &rcCfg)) != VP8ENC_OK) { + VPU_PLG_ERR("VP8EncSetRateCtrl() failed. ret %d\n", ret); + CloseEncoder(encoder); + return -1; + } + + /* Encoder setup: coding control */ + if ((ret = VP8EncGetCodingCtrl(encoder, &codingCfg)) != VP8ENC_OK) { + VPU_PLG_ERR("VP8EncGetCodingCtrl() failed. ret %d\n", ret); + CloseEncoder(encoder); + return -1; + } + + if (cml->dctPartitions != DEFAULT) + codingCfg.dctPartitions = cml->dctPartitions; + if (cml->errorResilient != DEFAULT) + codingCfg.errorResilient = cml->errorResilient; + if (cml->ipolFilter != DEFAULT) + codingCfg.interpolationFilter = cml->ipolFilter; + if (cml->filterType != DEFAULT) + codingCfg.filterType = cml->filterType; + if (cml->filterLevel != DEFAULT) + codingCfg.filterLevel = cml->filterLevel; + if (cml->filterSharpness != DEFAULT) + codingCfg.filterSharpness = cml->filterSharpness; + if (cml->quarterPixelMv != DEFAULT) + codingCfg.quarterPixelMv = cml->quarterPixelMv; + if (cml->splitMv != DEFAULT) + codingCfg.splitMv = cml->splitMv; + + codingCfg.cirStart = cml->cirStart; + codingCfg.cirInterval = cml->cirInterval; + codingCfg.intraArea.enable = cml->intraAreaEnable; + codingCfg.intraArea.top = cml->intraAreaTop; + codingCfg.intraArea.left = cml->intraAreaLeft; + codingCfg.intraArea.bottom = cml->intraAreaBottom; + codingCfg.intraArea.right = cml->intraAreaRight; + codingCfg.roi1Area.enable = cml->roi1AreaEnable; + codingCfg.roi1Area.top = cml->roi1AreaTop; + codingCfg.roi1Area.left = cml->roi1AreaLeft; + codingCfg.roi1Area.bottom = cml->roi1AreaBottom; + codingCfg.roi1Area.right = cml->roi1AreaRight; + codingCfg.roi2Area.enable = cml->roi2AreaEnable; + codingCfg.roi2Area.top = cml->roi2AreaTop; + codingCfg.roi2Area.left = cml->roi2AreaLeft; + codingCfg.roi2Area.bottom = cml->roi2AreaBottom; + codingCfg.roi2Area.right = cml->roi2AreaRight; + codingCfg.roi1DeltaQp = cml->roi1DeltaQp; + codingCfg.roi2DeltaQp = cml->roi2DeltaQp; + + VPU_PLG_DBG("Set coding control: dctPartitions=%d ipolFilter=%d" + " errorResilient=%d\n" + " filterType=%d filterLevel=%d filterSharpness=%d" + " quarterPixelMv=%d" + " splitMv=%d\n", + codingCfg.dctPartitions, codingCfg.interpolationFilter, + codingCfg.errorResilient, codingCfg.filterType, + codingCfg.filterLevel, codingCfg.filterSharpness, + codingCfg.quarterPixelMv, codingCfg.splitMv); + + if (codingCfg.cirInterval) + VPU_PLG_DBG(" CIR: %d %d\n", + codingCfg.cirStart, codingCfg.cirInterval); + + if (codingCfg.intraArea.enable) + VPU_PLG_DBG(" IntraArea: %dx%d-%dx%d\n", + codingCfg.intraArea.left, codingCfg.intraArea.top, + codingCfg.intraArea.right, codingCfg.intraArea.bottom); + + if (codingCfg.roi1Area.enable) + VPU_PLG_DBG(" ROI 1: %d %dx%d-%dx%d\n", codingCfg.roi1DeltaQp, + codingCfg.roi1Area.left, codingCfg.roi1Area.top, + codingCfg.roi1Area.right, codingCfg.roi1Area.bottom); + + if (codingCfg.roi2Area.enable) + VPU_PLG_DBG(" ROI 2: %d %dx%d-%dx%d\n", codingCfg.roi2DeltaQp, + codingCfg.roi2Area.left, codingCfg.roi2Area.top, + codingCfg.roi2Area.right, codingCfg.roi2Area.bottom); + + + if ((ret = VP8EncSetCodingCtrl(encoder, &codingCfg)) != VP8ENC_OK) { + VPU_PLG_ERR("VP8EncSetCodingCtrl() failed. ret %d\n", ret); + CloseEncoder(encoder); + return -1; + } + + return 0; +} + +/*------------------------------------------------------------------------------ + + CloseEncoder + Release an encoder insatnce. + + Params: + encoder - the instance to be released +------------------------------------------------------------------------------*/ +static void CloseEncoder(VP8EncInst encoder) { + VP8EncRet ret; + + if ((ret = VP8EncRelease(encoder)) != VP8ENC_OK) + VPU_PLG_ERR("VP8EncRelease() failed. ret %d\n", ret); +} + +void SetDefaultParameter(EncoderParameters* cml) { + memset(cml, 0, sizeof(EncoderParameters)); + + /* Default setting tries to parse resolution from file name */ + + /* Width of encoded output image */ + cml->width = 176; + /* Height of encoded output image */ + cml->height = 144; + /* Width of source image [176] */ + cml->lumWidthSrc = 176; + /* Height of source image [144] */ + cml->lumHeightSrc = 144; + /* Output image horizontal cropping offset [0] */ + cml->horOffsetSrc = 0; + /* Output image vertical cropping offset [0] */ + cml->verOffsetSrc = 0; + + /* Input YUV format [1] */ + cml->inputFormat = VP8ENC_YUV420_SEMIPLANAR; + /* 1..1048575 Output picture rate numerator. [--inputRateNumer] */ + cml->outputRateNumer = 30; + /* 1..1048575 Output picture rate denominator. [--inputRateDenom] */ + cml->outputRateDenom = 1; + /* 1..3 Amount of buffered reference frames. [1] */ + cml->refFrameAmount = 1; + + /* Default settings are get from API and not changed in testbench */ + + /* RGB to YCbCr color conversion type. [0] */ + cml->colorConversion = VP8ENC_RGBTOYUV_BT601; + /* Enable video stabilization or scene change detection. [0] */ + cml->videoStab = 0; + /* Rotate input image. [0] */ + cml->rotation = 0; + + /* -1..127, Initial QP used for the first frame. [36] */ + cml->qpHdr = 36; + /* 0..127, Minimum frame header QP. [10] */ + cml->qpMin = 0; + /* 0..127, Maximum frame header QP. [51] */ + cml->qpMax = QINDEX_RANGE - 1; + /* 10000..60000000, Target bitrate for rate control [1000000] */ + cml->bitPerSecond = 1000000; + /* 0=OFF, 1=ON, Picture rate control enable. [1] */ + cml->picRc = 0; + /* 0=OFF, 1=ON, Picture skip rate control. [0] */ + cml->picSkip = 0; + /* -12..12, Intra QP delta. [0] */ + cml->intraQpDelta = 0; + /* 0..127, Fixed Intra QP, 0 = disabled. [0] */ + cml->fixedIntraQp = 0; + + /* Intra picture rate in frames. [0] */ + cml->intraPicRate = 150; + /* 1..300, Group Of Pictures length in frames. [--intraPicRate] */ + cml->gopLength = cml->intraPicRate; + /* 0=1, 1=2, 2=4, 3=8, Amount of DCT partitions to create */ + cml->dctPartitions = 0; + /* Enable error resilient stream mode. [0] */ + cml->errorResilient = 0; + /* 0=Bicubic, 1=Bilinear, 2=None, Interpolation filter mode. [1] */ + cml->ipolFilter = 1; + /* 0=Normal, 1=Simple, Type of in-loop deblocking filter. [0] */ + cml->filterType = 0; + /* 0..64, 64=auto, Filter strength level for deblocking. [64] */ + cml->filterLevel = 64; + /* 0..8, 8=auto, Filter sharpness for deblocking. [8] */ + cml->filterSharpness = 8; + /* 0=OFF, 1=Adaptive, 2=ON, use 1/4 pixel MVs. [1] */ + cml->quarterPixelMv = 1; + /* 0=OFF, 1=Adaptive, 2=ON, allowed to to use more than 1 MV/MB. [1] */ + cml->splitMv = 1; + + /* start:interval for Cyclic Intra Refresh, forces MBs intra */ + cml->cirStart = 0; + /* start:interval for Cyclic Intra Refresh, forces MBs intra */ + cml->cirInterval = 0; + + /* left:top:right:bottom macroblock coordinates */ + cml->intraAreaLeft = 0; + cml->intraAreaTop = 0; + cml->intraAreaRight = 0; + cml->intraAreaBottom = 0; + cml->intraAreaEnable = 0; + + /* left:top:right:bottom macroblock coordinates */ + cml->roi1AreaLeft = 0; + cml->roi1AreaTop = 0; + cml->roi1AreaRight = 0; + cml->roi1AreaBottom = 0; + cml->roi1AreaEnable = 0; + cml->roi2AreaLeft = 0; + cml->roi2AreaTop = 0; + cml->roi2AreaRight = 0; + cml->roi2AreaBottom = 0; + cml->roi2AreaEnable = 0; + + /* QP delta value for 1st Region-Of-Interest. [-50,0] */ + cml->roi1DeltaQp = 0; + cml->roi2DeltaQp = 0; + cml->roi1AreaEnable = cml->roi1DeltaQp; + cml->roi2AreaEnable = cml->roi2DeltaQp; + + /* Enables PSNR calculation for each frame. [0] */ + cml->psnrSum = 0; + cml->psnrCnt = 0; + + /* Enable MV writing in <mv.txt> [0] */ + cml->mvOutput = 0; + + /* Favor value for I16x16 mode in I16/I4 */ + cml->intra16Favor = 0; + /* Penalty value for intra mode in intra/inter */ + cml->intraPenalty = 0; + /* Code all odd frames as droppable */ + cml->droppable = 0; +} + +void PrintTitle(EncoderParameters* cml) { + VPU_PLG_DBG("\n"); + VPU_PLG_DBG("Input | Pic | QP | Type | IP GR AR | " + "BR avg MA(%3d) | ByteCnt (inst) |", + cml->ma.length); + + if (cml->printPsnr) + VPU_PLG_DBG(" PSNR |"); + + VPU_PLG_DBG("\n"); + VPU_PLG_DBG("----------------------------------------" + "-----------------------------------------\n"); + + VPU_PLG_DBG(" | | %3d | HDR | | " + " | %7i %6i |", + cml->rc.qpHdr, cml->streamSize, IVF_HDR_BYTES); + + if (cml->printPsnr) + VPU_PLG_DBG(" |"); + VPU_PLG_DBG("\n"); +} + +void PrintFrame(EncoderParameters* cml, VP8EncInst encoder, + uint32_t frameNumber, + VP8EncRet ret) { + if ((cml->frameCntTotal + 1) && cml->outputRateDenom) { + /* Using 64-bits to avoid overflow */ + uint64_t tmp = cml->streamSize / (cml->frameCntTotal + 1); + tmp *= (uint32_t)cml->outputRateNumer; + + cml->bitrate = (uint32_t)(8 * (tmp / (uint32_t)cml->outputRateDenom)); + } + + VPU_PLG_DBG("%5i | %3llu | %3d | ", + frameNumber, cml->frameCntTotal, cml->rc.qpHdr); + + VPU_PLG_DBG("%s", + (ret == VP8ENC_OUTPUT_BUFFER_OVERFLOW) ? + "lost" : (cml->encOut.codingType == VP8ENC_INTRA_FRAME) ? " I " : + (cml->encOut.codingType == VP8ENC_PREDICTED_FRAME) ? " P " : "skip"); + + /* Print reference frame usage */ + VPU_PLG_DBG(" | %c%c %c%c %c%c", + cml->encOut.ipf & VP8ENC_REFERENCE ? 'R' : ' ', + cml->encOut.ipf & VP8ENC_REFRESH ? 'W' : ' ', + cml->encOut.grf & VP8ENC_REFERENCE ? 'R' : ' ', + cml->encOut.grf & VP8ENC_REFRESH ? 'W' : ' ', + cml->encOut.arf & VP8ENC_REFERENCE ? 'R' : ' ', + cml->encOut.arf & VP8ENC_REFRESH ? 'W' : ' '); + + /* Print bitrate statistics and frame size */ + VPU_PLG_DBG(" | %9u %9u | %7i %6i | ", + cml->bitrate, Ma(&cml->ma), cml->streamSize, cml->encOut.frameSize); + + /* Print size of each partition in bytes */ + VPU_PLG_DBG("%d %d %d %d\n", cml->encOut.frameSize ? IVF_FRM_BYTES : 0, + cml->encOut.streamSize[0], + cml->encOut.streamSize[1], cml->encOut.streamSize[2]); + + /* Check that partition sizes match frame size */ + if (cml->encOut.frameSize != (cml->encOut.streamSize[0] + + cml->encOut.streamSize[1] + + cml->encOut.streamSize[2])) { + VPU_PLG_DBG("ERROR: Frame size doesn't match partition sizes!\n"); + } +} + +/*---------------------------------------------------------------------------- + Add new frame bits for moving average bitrate calculation +-----------------------------------------------------------------------------*/ +static void MaAddFrame(ma_s* ma, int32_t frameSizeBits) { + ma->frame[ma->pos++] = frameSizeBits; + + if (ma->pos == ma->length) + ma->pos = 0; + + if (ma->count < ma->length) + ma->count++; +} + +/*---------------------------------------------------------------------------- + Calculate average bitrate of moving window +-----------------------------------------------------------------------------*/ +static int32_t Ma(ma_s* ma) { + int32_t i; + uint64_t sum = 0; /* Using 64-bits to avoid overflow */ + + for (i = 0; i < ma->count; i++) + sum += ma->frame[i]; + + if (!ma->frameRateDenom) + return 0; + + sum = sum / ma->length; + + return sum * ma->frameRateNumer / ma->frameRateDenom; +} + +static struct rk_venc_ops vp8_enc_ops = { + .init = rk_vp8_encoder_init, + .before_encode = rk_vp8_encoder_before_encode, + .after_encode = rk_vp8_encoder_after_encode, + .deinit = rk_vp8_encoder_deinit, + .updatepriv = rk_vp8_encoder_updatepriv, + .updateparameter = rk_vp8_encoder_setconfig, +}; + +struct rk_vp8_encoder* rk_vp8_encoder_alloc_ctx(void) +{ + struct rk_vp8_encoder* enc = + (struct rk_vp8_encoder*)calloc(1, sizeof(struct rk_vp8_encoder)); + + if (enc == NULL) { + VPU_PLG_ERR("allocate decoder context failed\n"); + return NULL; + } + + enc->ops = &vp8_enc_ops; + + return enc; +} + +void rk_vp8_encoder_free_ctx(struct rk_vp8_encoder *enc) +{ + free(enc); +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.h b/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.h new file mode 100644 index 0000000..783f5bf --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.h @@ -0,0 +1,56 @@ +/* Copyright 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef _RK_VP8ENCAPI_H_ +#define _RK_VP8ENCAPI_H_ + +#include "vp8encapi.h" +#include "libvpu/rk_vepu_interface.h" + +enum VP8E_PRIVATE_DATA_TYPE { + VP8E_PRIVATE_DATA_TYPE_END, + VP8E_PRIVATE_DATA_TYPE_FRAMETAG, + VP8E_PRIVATE_DATA_TYPE_FRAMEHEADER, + VP8E_PRIVATE_DATA_TYPE_CABAC, + VP8E_PRIVATE_DATA_TYPE_SEGMAP, + VP8E_PRIVATE_DATA_TYPE_REG, + VP8E_PRIVATE_DATA_TYPE_PROBCNT +}; + +struct rk_vp8_encoder; + +struct rk_venc_ops { + int (*init)(struct rk_vp8_encoder *enc, struct rk_vepu_init_param *enc_parms); + int (*before_encode)(struct rk_vp8_encoder *enc); + int (*after_encode)(struct rk_vp8_encoder *enc, uint32_t outputStreamSize); + void (*deinit)(struct rk_vp8_encoder *enc); + int (*updatepriv)(struct rk_vp8_encoder *enc, void *config, uint32_t cfglen); + void (*updateparameter)(struct rk_vp8_encoder *enc, struct rk_vepu_runtime_param *param); +}; + +#define NUM_CTRLS 3 +struct rk_vp8_encoder { + struct rk_venc_ops *ops; + + EncoderParameters cmdl; + VP8EncInst encoder; + VP8EncIn encIn; + int intraPeriodCnt; + int codedFrameCnt; + int src_img_size; + int next; + uint8_t *priv_data; + uint32_t priv_offset; /* offset of current private data */ + uint32_t hdr_idx; + bool first_frame; + uint32_t rk_ctrl_ids[NUM_CTRLS]; + void *rk_payloads[NUM_CTRLS]; + uint32_t rk_payload_sizes[NUM_CTRLS]; +}; + +struct rk_vp8_encoder* rk_vp8_encoder_alloc_ctx(void); +void rk_vp8_encoder_free_ctx(struct rk_vp8_encoder *enc); +#endif /* _RK_VP8ENCAPI_H_ */ + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.c b/libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.c new file mode 100644 index 0000000..7b62b35 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.c @@ -0,0 +1,479 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include <memory.h> +#include "enccommon.h" +#include "encasiccontroller.h" +#include "vp8codeframe.h" +#include "vp8ratecontrol.h" +#include "vp8header.h" +#include "vp8entropy.h" + +/* Intra 16x16 mode tree penalty values */ +static const int32_t const intra16ModeTreePenalty[] = { + 305, 841, 914, 1082 +}; + + +/* Intra 4x4 mode tree penalty values */ +static const int32_t const intra4ModeTreePenalty[] = { + 280, 622, 832, 1177, 1240, 1341, 1085, 1259, 1357, 1495 +}; + +/* This is visually fitted. TODO use GNUPLOT or octave to fit curve at + * given data. ~round((2*(2+exp((x+22)/39)) + (2+exp((x+15)/32)))/3) */ +const int32_t const weight[128] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, + 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, + 14, 14, 14, 14, 15, 15, 15, 16, 16, 17, + 17, 18, 18, 19, 19, 20, 20, 20, 21, 22, + 23, 23, 24, 24, 25, 25, 26, 27, 28, 28, + 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 44, 44, 46, 47, 48, + 50, 51, 52, 54, 55, 57, 58, 61 +}; + +/* experimentally fitted, 24.893*exp(0.02545*qp) */ +const int32_t vp8SplitPenalty[128] = { + 24, 25, 26, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 52, 53, 54, + 56, 57, 59, 60, 62, 63, 65, 67, 68, 70, 72, 74, 76, 78, 80, 82, + 84, 86, 88, 91, 93, 95, 98, 100, 103, 106, 108, 111, 114, 117, 120, 123, + 126, 130, 133, 136, 140, 144, 147, 151, 155, 159, 163, 167, 172, 176, 181, 185, + 190, 195, 200, 205, 211, 216, 222, 227, 233, 239, 245, 252, 258, 265, 272, 279, + 286, 293, 301, 309, 317, 325, 333, 342, 351, 360, 369, 379, 388, 398, 409, 419, + 430, 441, 453, 464, 476, 488, 501, 514, 527, 541, 555, 569, 584, 599, 614, 630 +}; + +static void VP8SetNewFrame(vp8Instance_s* inst); +static void SetIntraPredictionPenalties(regValues_s* regs, uint32_t qp); +static void SetSegmentation(vp8Instance_s* inst); +static void SetFilterParameters(vp8Instance_s* inst); + +void VP8SetFrameParams(vp8Instance_s* inst) { + pps* pps = inst->ppss.pps; /* Active picture parameters */ + sps* sps = &inst->sps; + int32_t qp = inst->rateControl.qpHdr; + int32_t i; + + /* Segment parameters, testId/ROI may override qpSgm and + * auto filter level setting may override levelSgm. */ + for (i = 0; i < SGM_CNT; i++) { + pps->qpSgm[i] = qp; + pps->levelSgm[i] = sps->filterLevel; + } +} + +void VP8CodeFrame(vp8Instance_s* inst, EncoderParameters* cml) { + /* Initialize probability tables for frame header. */ + InitEntropy(inst); + SetSegmentation(inst); + SetFilterParameters(inst); + + /* Write frame headers, also updates segmentation probs. */ + VP8FrameHeader(inst); + VP8FrameTag(inst); + VP8SetNewFrame(inst); + + /* Write final probability tables for ASIC. */ + WriteEntropyTables(inst); + + VP8_EncAsicFrameStart(&inst->asic.regs); +} + +void VP8SetNewFrame(vp8Instance_s* inst) { + regValues_s* regs = &inst->asic.regs; + sps* sps = &inst->sps; + int32_t qp, i; + + /* We tell HW the size of DCT partition buffers, they all are equal size. + * There is no overflow check for control partition on ASIC, but since + * the stream buffers are in one linear memory the overflow of control + * partition will only corrupt the first DCT partition and SW will + * notice this and discard the frame. */ + regs->outputStrmSize /= 8; /* 64-bit addresses */ + regs->outputStrmSize &= (~0x07); /* 8 multiple size */ + + /* Since frame tag is 10 bytes the stream base is not 64-bit aligned. + * Now the frame headers have been written so we must align the base for + * HW and set the header remainder properly. */ + regs->outputStrmBase = inst->buffer[0].byteCnt; + regs->outputStrmBase += inst->buffer[1].byteCnt; + + /* bit offset in the last 64-bit word */ + /** TODO, no StrmBase here, firstFreeBit also need to be + * config in the driver. */ + regs->firstFreeBit = (regs->outputStrmBase & 0x07) * 8; + + /* 64-bit aligned HW base */ + regs->outputStrmBase = regs->outputStrmBase & (~0x07); + + /* header remainder is byte aligned, max 7 bytes = 56 bits */ + if (regs->firstFreeBit != 0) { + /* 64-bit aligned stream pointer */ + uint8_t* pTmp = (uint8_t*)((size_t)(inst->buffer[1].data) & (uint32_t)(~0x07)); + uint32_t val; + + /* Clear remaining bits */ + for (val = 6; val >= regs->firstFreeBit / 8; val--) + pTmp[val] = 0; + + val = pTmp[0] << 24; + val |= pTmp[1] << 16; + val |= pTmp[2] << 8; + val |= pTmp[3]; + + regs->strmStartMSB = val; /* 32 bits to MSB */ + + if (regs->firstFreeBit > 32) { + val = pTmp[4] << 24; + val |= pTmp[5] << 16; + val |= pTmp[6] << 8; + + regs->strmStartLSB = val; + } else + regs->strmStartLSB = 0; + } else { + regs->strmStartMSB = regs->strmStartLSB = 0; + } + + /* Quarter pixel MV mode */ + if (sps->quarterPixelMv == 0) + regs->disableQuarterPixelMv = 1; + else if (sps->quarterPixelMv == 1) { + /* Adaptive setting. When resolution larger than 1080p = 8160 macroblocks + * there is not enough time to do 1/4 pixel ME */ + if (inst->mbPerFrame > 8160) + regs->disableQuarterPixelMv = 1; + else + regs->disableQuarterPixelMv = 0; + } else + regs->disableQuarterPixelMv = 0; + + /* Cabac enable bit signals ASIC to read probability tables */ + regs->enableCabac = 1; + + /* Split MV mode */ + if (sps->splitMv == 0) + regs->splitMvMode = 0; + else if (sps->splitMv == 1) { + /* Adaptive setting. When resolution larger than 4CIF = 1584 macroblocks + * there is no benefit from using split MVs */ + if (inst->mbPerFrame > 1584) + regs->splitMvMode = 0; + else + regs->splitMvMode = 1; + } else + regs->splitMvMode = 1; + + qp = inst->rateControl.qpHdr; + + /* If favor has not been set earlier by testId use default */ + if (regs->interFavor == ASIC_PENALTY_UNDEFINED) { + int32_t tmp = 128 - inst->entropy->intraProb; + + /* This is called intraPenalty in system model */ + if (tmp < 0) { + regs->interFavor = tmp & 0xFFFF; /* Signed 16-bit value */ + } else { + tmp = qp * 2 - 40; + regs->interFavor = MAX(0, tmp); + } + } + if (regs->diffMvPenalty[0] == ASIC_PENALTY_UNDEFINED) + regs->diffMvPenalty[0] = 64 / 2; + if (regs->diffMvPenalty[1] == ASIC_PENALTY_UNDEFINED) + regs->diffMvPenalty[1] = 60 / 2 * 32; + if (regs->diffMvPenalty[2] == ASIC_PENALTY_UNDEFINED) + regs->diffMvPenalty[2] = 8; + if (regs->skipPenalty == ASIC_PENALTY_UNDEFINED) + regs->skipPenalty = (qp >= 100) ? (3 * qp / 4) : 0; /* Zero/nearest/near */ + if (regs->goldenPenalty == ASIC_PENALTY_UNDEFINED) + regs->goldenPenalty = MAX(0, 5 * qp / 4 - 10); + if (regs->splitPenalty[0] == ASIC_PENALTY_UNDEFINED) + regs->splitPenalty[0] = MIN(1023, vp8SplitPenalty[qp] / 2); + if (regs->splitPenalty[1] == ASIC_PENALTY_UNDEFINED) + regs->splitPenalty[1] = MIN(1023, (2 * vp8SplitPenalty[qp] + 40) / 4); + if (regs->splitPenalty[3] == ASIC_PENALTY_UNDEFINED) + regs->splitPenalty[3] = MIN(511, (8 * vp8SplitPenalty[qp] + 500) / 16); + + /* DMV penalty tables */ + for (i = 0; i < ASIC_PENALTY_TABLE_SIZE; i++) { + int32_t y, x; + + regs->dmvPenalty[i] = i * 2; + y = CostMv(i * 2, inst->entropy->mvProb[0]); /* mv y */ + x = CostMv(i * 2, inst->entropy->mvProb[1]); /* mv x */ + regs->dmvQpelPenalty[i] = MIN(255, (y + x + 1) / 2 * weight[qp] >> 8); + } + + /* Quantization tables for each segment */ + for (i = 0; i < SGM_CNT; i++) { + qp = inst->ppss.pps->qpSgm[i]; + regs->qpY1QuantDc[i] = inst->qpY1[qp].quant[0]; + regs->qpY1QuantAc[i] = inst->qpY1[qp].quant[1]; + regs->qpY2QuantDc[i] = inst->qpY2[qp].quant[0]; + regs->qpY2QuantAc[i] = inst->qpY2[qp].quant[1]; + regs->qpChQuantDc[i] = inst->qpCh[qp].quant[0]; + regs->qpChQuantAc[i] = inst->qpCh[qp].quant[1]; + regs->qpY1ZbinDc[i] = inst->qpY1[qp].zbin[0]; + regs->qpY1ZbinAc[i] = inst->qpY1[qp].zbin[1]; + regs->qpY2ZbinDc[i] = inst->qpY2[qp].zbin[0]; + regs->qpY2ZbinAc[i] = inst->qpY2[qp].zbin[1]; + regs->qpChZbinDc[i] = inst->qpCh[qp].zbin[0]; + regs->qpChZbinAc[i] = inst->qpCh[qp].zbin[1]; + regs->qpY1RoundDc[i] = inst->qpY1[qp].round[0]; + regs->qpY1RoundAc[i] = inst->qpY1[qp].round[1]; + regs->qpY2RoundDc[i] = inst->qpY2[qp].round[0]; + regs->qpY2RoundAc[i] = inst->qpY2[qp].round[1]; + regs->qpChRoundDc[i] = inst->qpCh[qp].round[0]; + regs->qpChRoundAc[i] = inst->qpCh[qp].round[1]; + regs->qpY1DequantDc[i] = inst->qpY1[qp].dequant[0]; + regs->qpY1DequantAc[i] = inst->qpY1[qp].dequant[1]; + regs->qpY2DequantDc[i] = inst->qpY2[qp].dequant[0]; + regs->qpY2DequantAc[i] = inst->qpY2[qp].dequant[1]; + regs->qpChDequantDc[i] = inst->qpCh[qp].dequant[0]; + regs->qpChDequantAc[i] = inst->qpCh[qp].dequant[1]; + + regs->filterLevel[i] = inst->ppss.pps->levelSgm[i]; + } + + regs->boolEncValue = inst->buffer[1].bottom; + regs->boolEncValueBits = 24 - inst->buffer[1].bitsLeft; + regs->boolEncRange = inst->buffer[1].range; + + regs->cpTarget = NULL; + + /* Select frame type */ + if (inst->picBuffer.cur_pic->i_frame) + regs->frameCodingType = ASIC_INTRA; + else + regs->frameCodingType = ASIC_INTER; + + regs->dctPartitions = sps->dctPartitions; + regs->filterDisable = sps->filterType; + regs->filterSharpness = sps->filterSharpness; + regs->segmentEnable = inst->ppss.pps->segmentEnabled; + regs->segmentMapUpdate = inst->ppss.pps->sgm.mapModified; + + /* For next frame the segmentation map is not needed unless it is modified. */ + inst->ppss.pps->sgm.mapModified = false; + + for (i = 0; i < 4; i++) { + regs->lfRefDelta[i] = sps->refDelta[i]; + regs->lfModeDelta[i] = sps->modeDelta[i]; + } + + SetIntraPredictionPenalties(regs, qp); + + memset(inst->asic.probCount.vir_addr, 0, + inst->asic.probCount.size); +} + +void SetIntraPredictionPenalties(regValues_s* regs, uint32_t qp) { + + int32_t i, tmp; + + /* Intra 4x4 mode */ + tmp = qp * 2 + 8; + for (i = 0; i < 10; i++) { + regs->intraBmodePenalty[i] = (intra4ModeTreePenalty[i] * tmp) >> 8; + + } + + /* Intra 16x16 mode */ + tmp = qp * 2 + 64; + for (i = 0; i < 4; i++) { + regs->intraModePenalty[i] = (intra16ModeTreePenalty[i] * tmp) >> 8; + } + + /* If favor has not been set earlier by testId use default */ + if (regs->intra16Favor == ASIC_PENALTY_UNDEFINED) + regs->intra16Favor = qp * 1024 / 128; +} + +void SetSegmentation(vp8Instance_s* inst) { + regValues_s* regs = &inst->asic.regs; + uint32_t* map = inst->asic.segmentMap.vir_addr; + ppss* ppss = &inst->ppss; + pps* pps = inst->ppss.pps; /* Active picture parameters */ + int32_t qp = inst->rateControl.qpHdr; + uint32_t x, y, mb, mask, id; + uint32_t mapSize = (inst->mbPerFrame + 15) / 16 * 8; /* Bytes, 64-bit multiple */ + + /* Set the segmentation parameters according to ROI settings. + * This will override any earlier segmentation settings. */ + + if (regs->roi1DeltaQp) + pps->qpSgm[1] = CLIP3(qp - regs->roi1DeltaQp, 0, 127); + + if (regs->roi2DeltaQp) + pps->qpSgm[2] = CLIP3(qp - regs->roi2DeltaQp, 0, 127); + + if (regs->roi1DeltaQp || regs->roi2DeltaQp) { + pps->segmentEnabled = 1; + + memset(pps->sgm.idCnt, 0, sizeof(pps->sgm.idCnt)); + + /* Set ROI 1 (ID == 1) and ROI 2 (ID == 2) into map */ + for (y = 0, mb = 0, mask = 0; y < inst->mbPerCol; y++) { + for (x = 0; x < inst->mbPerRow; x++) { + id = 0; + if ((x >= regs->roi1Left) && (x <= regs->roi1Right) && + (y >= regs->roi1Top) && (y <= regs->roi1Bottom)) id = 1; + if ((x >= regs->roi2Left) && (x <= regs->roi2Right) && + (y >= regs->roi2Top) && (y <= regs->roi2Bottom)) id = 2; + + pps->sgm.idCnt[id]++; + + mask |= id << (28 - 4 * (mb % 8)); + if ((mb % 8) == 7) { + *map++ = mask; + mask = 0; + } + mb++; + } + } + *map++ = mask; + EncSwapEndianess((uint32_t*)inst->asic.segmentMap.vir_addr, mapSize); + } else if (pps->segmentEnabled && pps->sgm.mapModified) { + memset(pps->sgm.idCnt, 0, sizeof(pps->sgm.idCnt)); + + /* Use the map to calculate id counts */ + for (mb = 0, mask = 0; mb < mapSize / 4; mb++) { + mask = map[mb]; + for (x = 0; x < 8; x++) { + if (mb * 8 + x < inst->mbPerFrame) { + id = (mask >> (28 - 4 * x)) & 0xF; + pps->sgm.idCnt[id]++; + } + } + } + EncSwapEndianess((uint32_t*)inst->asic.segmentMap.vir_addr, mapSize); + } + + /* If current frame is key frame or segmentation is not enabled old + * segmentation data is not valid anymore, set out of range data to + * inform Segmentation(). */ + if (inst->picBuffer.cur_pic->i_frame || !pps->segmentEnabled) { + memset(ppss->qpSgm, 0xff, sizeof(ppss->qpSgm)); + memset(ppss->levelSgm, 0xff, sizeof(ppss->levelSgm)); + ppss->prevPps = NULL; + } else { + ppss->prevPps = ppss->pps; + } +} + +void SetFilterParameters(vp8Instance_s* inst) { + sps* sps = &inst->sps; + pps* pps = inst->ppss.pps; /* Active picture parameters */ + uint32_t qp = inst->rateControl.qpHdr; + uint32_t tmp, i; + uint32_t iframe = inst->picBuffer.cur_pic->i_frame; + const int32_t const interLevel[128] = { + 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, + 18, 19, 19, 20, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, + 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 48, 49, 50, 51, 53, 54, 56, 57, 59, + 60, 62, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63 + }; + + + /* auto level */ + if (sps->autoFilterLevel) { + if (iframe) { + tmp = (qp * 64) / 128 + 8; + sps->filterLevel = CLIP3(tmp, 0, 63); + pps->levelSgm[0] = CLIP3((pps->qpSgm[0] * 64) / 128 + 8, 0, 63); + pps->levelSgm[1] = CLIP3((pps->qpSgm[1] * 64) / 128 + 8, 0, 63); + pps->levelSgm[2] = CLIP3((pps->qpSgm[2] * 64) / 128 + 8, 0, 63); + pps->levelSgm[3] = CLIP3((pps->qpSgm[3] * 64) / 128 + 8, 0, 63); + } else { + sps->filterLevel = interLevel[qp]; + pps->levelSgm[0] = interLevel[pps->qpSgm[0]]; + pps->levelSgm[1] = interLevel[pps->qpSgm[1]]; + pps->levelSgm[2] = interLevel[pps->qpSgm[2]]; + pps->levelSgm[3] = interLevel[pps->qpSgm[3]]; + } + } + /* auto sharpness */ + if (sps->autoFilterSharpness) { + sps->filterSharpness = 0; + } + + if (!sps->filterDeltaEnable) return; + + if (sps->filterDeltaEnable == 2) { + /* Special meaning, test ID set filter delta values */ + sps->filterDeltaEnable = true; + return; + } + + /* force deltas to 0 if filterLevel == 0 (assumed to mean that filtering + * is completely disabled) */ + if (sps->filterLevel == 0) { + sps->refDelta[0] = 0; /* Intra frame */ + sps->refDelta[1] = 0; /* Last frame */ + sps->refDelta[2] = 0; /* Golden frame */ + sps->refDelta[3] = 0; /* Altref frame */ + sps->modeDelta[0] = 0; /* BPRED */ + sps->modeDelta[1] = 0; /* Zero */ + sps->modeDelta[2] = 0; /* New mv */ + sps->modeDelta[3] = 0; /* Split mv */ + return; + } + + if (!inst->picBuffer.cur_pic->ipf && !inst->picBuffer.cur_pic->grf && + !inst->picBuffer.cur_pic->arf) { + /* Frame is droppable, ie. doesn't update ipf, grf nor arf so don't + * update the filter level deltas. */ + memcpy(sps->refDelta, sps->oldRefDelta, sizeof(sps->refDelta)); + memcpy(sps->modeDelta, sps->oldModeDelta, sizeof(sps->modeDelta)); + return; + } + + /* Adjustment based on reference frame */ + sps->refDelta[0] = 2; /* Intra frame */ + sps->refDelta[1] = 0; /* Last frame */ + sps->refDelta[2] = -2; /* Golden frame */ + sps->refDelta[3] = -2; /* Altref frame */ + + /* Adjustment based on mb mode */ + sps->modeDelta[0] = 4; /* BPRED */ + sps->modeDelta[1] = -2; /* Zero */ + sps->modeDelta[2] = 2; /* New mv */ + sps->modeDelta[3] = 4; /* Split mv */ + + /* ABS(delta) is 6bits, see FilterLevelDelta() */ + for (i = 0; i < 4; i++) { + sps->refDelta[i] = CLIP3(sps->refDelta[i], -0x3f, 0x3f); + sps->modeDelta[i] = CLIP3(sps->modeDelta[i], -0x3f, 0x3f); + } +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.h b/libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.h new file mode 100644 index 0000000..eb8faab --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8codeframe.h @@ -0,0 +1,50 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef __VP8_CODE_FRAME_H__ +#define __VP8_CODE_FRAME_H__ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "vp8instance.h" +#include "vp8encapi.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +typedef enum +{ + VP8ENCODE_OK = 0, + VP8ENCODE_TIMEOUT = 1, + VP8ENCODE_DATA_ERROR = 2, + VP8ENCODE_HW_ERROR = 3, + VP8ENCODE_SYSTEM_ERROR = 4, + VP8ENCODE_HW_RESET = 5 +} vp8EncodeFrame_e; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +void VP8SetFrameParams(vp8Instance_s* inst); +void VP8CodeFrame(vp8Instance_s* inst, EncoderParameters* cml); + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.c b/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.c new file mode 100644 index 0000000..53c5f77 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.c @@ -0,0 +1,651 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include <memory.h> +#include <stdio.h> + +#include "vp8encapi.h" +#include "libvpu/rk_vepu_debug.h" + +#include "enccommon.h" +#include "vp8codeframe.h" +#include "vp8init.h" +#include "vp8instance.h" +#include "vp8ratecontrol.h" +#include "vp8putbits.h" + +#ifdef VIDEOSTAB_ENABLED +#include "vidstabcommon.h" +#endif + +/* Parameter limits */ +#define VP8ENC_MAX_PP_INPUT_WIDTH 8176 +#define VP8ENC_MAX_PP_INPUT_HEIGHT 8176 +#define VP8ENC_MAX_BITRATE (50000*1200) + +/*---------------------------------------------------------------------------- + Function name : VP8EncInit + Description : Initialize an encoder instance and + returns it to application + + Return type : VP8EncRet + Argument : pEncCfg - initialization parameters + instAddr - where to save the created instance +-----------------------------------------------------------------------------*/ +VP8EncRet VP8EncInit(const VP8EncConfig* pEncCfg, VP8EncInst* instAddr) { + VP8EncRet ret; + vp8Instance_s* pEncInst = NULL; + + VPU_PLG_DBG("VP8EncInit#"); + + /* check that right shift on negative numbers is performed signed */ +#if (((-1) >> 1) != (-1)) +#error Right bit-shifting (>>) does not preserve the sign +#endif + + /* Check for illegal inputs */ + if (pEncCfg == NULL || instAddr == NULL) { + VPU_PLG_ERR("VP8EncInit: ERROR Null argument"); + return VP8ENC_NULL_ARGUMENT; + } + + /* Check that configuration is valid */ + if (VP8CheckCfg(pEncCfg) == ENCHW_NOK) { + VPU_PLG_ERR("VP8EncInit: ERROR Invalid configuration"); + return VP8ENC_INVALID_ARGUMENT; + } + + /* Initialize encoder instance and allocate memories */ + ret = VP8Init(pEncCfg, &pEncInst); + if (ret != VP8ENC_OK) { + VPU_PLG_ERR("VP8EncInit: ERROR Initialization failed"); + return ret; + } + + pEncInst->encStatus = VP8ENCSTAT_INIT; + + pEncInst->inst = pEncInst; + + *instAddr = (VP8EncInst)pEncInst; + + VPU_PLG_DBG("VP8EncInit: OK"); + return VP8ENC_OK; +} + +/*---------------------------------------------------------------------------- + + Function name : VP8EncRelease + Description : Releases encoder instance and all associated resource + + Return type : VP8EncRet + Argument : inst - the instance to be released +-----------------------------------------------------------------------------*/ +VP8EncRet VP8EncRelease(VP8EncInst inst) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + + VPU_PLG_DBG("VP8EncRelease#"); + + /* Check for illegal inputs */ + if (pEncInst == NULL) { + VPU_PLG_DBG("VP8EncRelease: ERROR Null argument"); + return VP8ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if (pEncInst->inst != pEncInst) { + VPU_PLG_DBG("VP8EncRelease: ERROR Invalid instance"); + return VP8ENC_INSTANCE_ERROR; + } + +#ifdef TRACE_STREAM + EncCloseStreamTrace(); +#endif + + VP8Shutdown(pEncInst); + + VPU_PLG_DBG("VP8EncRelease: OK"); + return VP8ENC_OK; +} + +/*---------------------------------------------------------------------------- + + Function name : VP8EncSetCodingCtrl + Description : Sets encoding parameters + + Return type : VP8EncRet + Argument : inst - the instance in use + pCodeParams - user provided parameters +-----------------------------------------------------------------------------*/ +VP8EncRet VP8EncSetCodingCtrl(VP8EncInst inst, + const VP8EncCodingCtrl* pCodeParams) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + regValues_s* regs; + sps* sps; + uint32_t area1 = 0, area2 = 0; + + VPU_PLG_DBG("VP8EncSetCodingCtrl#"); + + /* Check for illegal inputs */ + if ((pEncInst == NULL) || (pCodeParams == NULL)) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Null argument\n"); + return VP8ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if (pEncInst->inst != pEncInst) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid instance\n"); + return VP8ENC_INSTANCE_ERROR; + } + + /* check limits */ + if (pCodeParams->filterLevel > VP8ENC_FILTER_LEVEL_AUTO || + pCodeParams->filterSharpness > VP8ENC_FILTER_SHARPNESS_AUTO) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid parameter\n"); + return VP8ENC_INVALID_ARGUMENT; + } + + if (pCodeParams->cirStart > pEncInst->mbPerFrame || + pCodeParams->cirInterval > pEncInst->mbPerFrame) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid CIR value\n"); + return VP8ENC_INVALID_ARGUMENT; + } + + if (pCodeParams->intraArea.enable) { + if (!(pCodeParams->intraArea.top <= pCodeParams->intraArea.bottom && + pCodeParams->intraArea.bottom < pEncInst->mbPerCol && + pCodeParams->intraArea.left <= pCodeParams->intraArea.right && + pCodeParams->intraArea.right < pEncInst->mbPerRow)) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid intraArea\n"); + return VP8ENC_INVALID_ARGUMENT; + } + } + + if (pCodeParams->roi1Area.enable) { + if (!(pCodeParams->roi1Area.top <= pCodeParams->roi1Area.bottom && + pCodeParams->roi1Area.bottom < pEncInst->mbPerCol && + pCodeParams->roi1Area.left <= pCodeParams->roi1Area.right && + pCodeParams->roi1Area.right < pEncInst->mbPerRow)) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid roi1Area\n"); + return VP8ENC_INVALID_ARGUMENT; + } + area1 = (pCodeParams->roi1Area.right + 1 - pCodeParams->roi1Area.left) * + (pCodeParams->roi1Area.bottom + 1 - pCodeParams->roi1Area.top); + } + + if (pCodeParams->roi2Area.enable) { + if (!pCodeParams->roi1Area.enable) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Roi2 enabled but not Roi1\n"); + return VP8ENC_INVALID_ARGUMENT; + } + if (!(pCodeParams->roi2Area.top <= pCodeParams->roi2Area.bottom && + pCodeParams->roi2Area.bottom < pEncInst->mbPerCol && + pCodeParams->roi2Area.left <= pCodeParams->roi2Area.right && + pCodeParams->roi2Area.right < pEncInst->mbPerRow)) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid roi2Area\n"); + return VP8ENC_INVALID_ARGUMENT; + } + area2 = (pCodeParams->roi2Area.right + 1 - pCodeParams->roi2Area.left) * + (pCodeParams->roi2Area.bottom + 1 - pCodeParams->roi2Area.top); + } + + if (area1 + area2 >= pEncInst->mbPerFrame) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid roi (whole frame)\n"); + return VP8ENC_INVALID_ARGUMENT; + } + + if (pCodeParams->roi1DeltaQp < -50 || + pCodeParams->roi1DeltaQp > 0 || + pCodeParams->roi2DeltaQp < -50 || + pCodeParams->roi2DeltaQp > 0) { + VPU_PLG_ERR("VP8EncSetCodingCtrl: ERROR Invalid ROI delta QP\n"); + return VP8ENC_INVALID_ARGUMENT; + } + + sps = &pEncInst->sps; + + /* TODO check limits */ + sps->filterType = pCodeParams->filterType; + if (pCodeParams->filterLevel == VP8ENC_FILTER_LEVEL_AUTO) { + sps->autoFilterLevel = 1; + sps->filterLevel = 0; + } else { + sps->autoFilterLevel = 0; + sps->filterLevel = pCodeParams->filterLevel; + } + + if (pCodeParams->filterSharpness == VP8ENC_FILTER_SHARPNESS_AUTO) { + sps->autoFilterSharpness = 1; + sps->filterSharpness = 0; + } else { + sps->autoFilterSharpness = 0; + sps->filterSharpness = pCodeParams->filterSharpness; + } + + sps->dctPartitions = pCodeParams->dctPartitions; + sps->partitionCnt = 2 + (1 << sps->dctPartitions); + sps->refreshEntropy = pCodeParams->errorResilient ? 0 : 1; + sps->quarterPixelMv = pCodeParams->quarterPixelMv; + sps->splitMv = pCodeParams->splitMv; + + regs = &pEncInst->asic.regs; + regs->cirStart = pCodeParams->cirStart; + regs->cirInterval = pCodeParams->cirInterval; + if (pCodeParams->intraArea.enable) { + regs->intraAreaTop = pCodeParams->intraArea.top; + regs->intraAreaLeft = pCodeParams->intraArea.left; + regs->intraAreaBottom = pCodeParams->intraArea.bottom; + regs->intraAreaRight = pCodeParams->intraArea.right; + } + if (pCodeParams->roi1Area.enable) { + regs->roi1Top = pCodeParams->roi1Area.top; + regs->roi1Left = pCodeParams->roi1Area.left; + regs->roi1Bottom = pCodeParams->roi1Area.bottom; + regs->roi1Right = pCodeParams->roi1Area.right; + } + if (pCodeParams->roi2Area.enable) { + regs->roi2Top = pCodeParams->roi2Area.top; + regs->roi2Left = pCodeParams->roi2Area.left; + regs->roi2Bottom = pCodeParams->roi2Area.bottom; + regs->roi2Right = pCodeParams->roi2Area.right; + } + + /* ROI setting updates the segmentation map usage */ + if (pCodeParams->roi1Area.enable || pCodeParams->roi2Area.enable) + pEncInst->ppss.pps->segmentEnabled = 1; + else { + pEncInst->ppss.pps->segmentEnabled = 0; + /* Disabling ROI will clear the segment ID map */ + memset(pEncInst->asic.segmentMap.vir_addr, 0, + pEncInst->asic.segmentMap.size); + } + pEncInst->ppss.pps->sgm.mapModified = true; + + regs->roi1DeltaQp = -pCodeParams->roi1DeltaQp; + regs->roi2DeltaQp = -pCodeParams->roi2DeltaQp; + + VPU_PLG_DBG("VP8EncSetCodingCtrl: OK"); + return VP8ENC_OK; +} + +/*---------------------------------------------------------------------------- + + Function name : VP8EncGetCodingCtrl + Description : Returns current encoding parameters + + Return type : VP8EncRet + Argument : inst - the instance in use + pCodeParams - palce where parameters are returned +-----------------------------------------------------------------------------*/ +VP8EncRet VP8EncGetCodingCtrl(VP8EncInst inst, + VP8EncCodingCtrl* pCodeParams) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + regValues_s* regs; + sps* sps; + + VPU_PLG_DBG("VP8EncGetCodingCtrl#"); + + /* Check for illegal inputs */ + if ((pEncInst == NULL) || (pCodeParams == NULL)) { + VPU_PLG_ERR("VP8EncGetCodingCtrl: ERROR Null argument\n"); + return VP8ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if (pEncInst->inst != pEncInst) { + VPU_PLG_ERR("VP8EncGetCodingCtrl: ERROR Invalid instance\n"); + return VP8ENC_INSTANCE_ERROR; + } + + sps = &pEncInst->sps; + + pCodeParams->interpolationFilter = 1; /* Only bicubic supported */ + pCodeParams->dctPartitions = sps->dctPartitions; + pCodeParams->quarterPixelMv = sps->quarterPixelMv; + pCodeParams->splitMv = sps->splitMv; + pCodeParams->filterType = sps->filterType; + pCodeParams->errorResilient = !sps->refreshEntropy; + + if (sps->autoFilterLevel) + pCodeParams->filterLevel = VP8ENC_FILTER_LEVEL_AUTO; + else + pCodeParams->filterLevel = sps->filterLevel; + + if (sps->autoFilterSharpness) + pCodeParams->filterSharpness = VP8ENC_FILTER_SHARPNESS_AUTO; + else + pCodeParams->filterSharpness = sps->filterSharpness; + + regs = &pEncInst->asic.regs; + pCodeParams->cirStart = regs->cirStart; + pCodeParams->cirInterval = regs->cirInterval; + pCodeParams->intraArea.enable = + regs->intraAreaTop < pEncInst->mbPerCol ? 1 : 0; + pCodeParams->intraArea.top = regs->intraAreaTop; + pCodeParams->intraArea.left = regs->intraAreaLeft; + pCodeParams->intraArea.bottom = regs->intraAreaBottom; + pCodeParams->intraArea.right = regs->intraAreaRight; + + VPU_PLG_DBG("VP8EncGetCodingCtrl: OK\n"); + return VP8ENC_OK; +} + +/*---------------------------------------------------------------------------- + + Function name : VP8EncSetRateCtrl + Description : Sets rate control parameters + + Return type : VP8EncRet + Argument : inst - the instance in use + pRateCtrl - user provided parameters +-----------------------------------------------------------------------------*/ +VP8EncRet VP8EncSetRateCtrl(VP8EncInst inst, + const VP8EncRateCtrl* pRateCtrl) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + vp8RateControl_s rc_tmp; + + VPU_PLG_DBG("VP8EncSetRateCtrl#"); + + /* Check for illegal inputs */ + if ((pEncInst == NULL) || (pRateCtrl == NULL)) { + VPU_PLG_ERR("VP8EncSetRateCtrl: ERROR Null argument\n"); + return VP8ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if (pEncInst->inst != pEncInst) { + VPU_PLG_ERR("VP8EncSetRateCtrl: ERROR Invalid instance\n"); + return VP8ENC_INSTANCE_ERROR; + } + + /* TODO Check for invalid values */ + + rc_tmp = pEncInst->rateControl; + rc_tmp.qpHdr = pRateCtrl->qpHdr; + rc_tmp.picRc = pRateCtrl->pictureRc; + rc_tmp.picSkip = pRateCtrl->pictureSkip; + rc_tmp.qpMin = pRateCtrl->qpMin; + rc_tmp.qpMax = pRateCtrl->qpMax; + rc_tmp.virtualBuffer.bitRate = pRateCtrl->bitPerSecond; + rc_tmp.gopLen = pRateCtrl->bitrateWindow; + rc_tmp.intraQpDelta = pRateCtrl->intraQpDelta; + rc_tmp.fixedIntraQp = pRateCtrl->fixedIntraQp; + rc_tmp.intraPictureRate = pRateCtrl->intraPictureRate; + rc_tmp.goldenPictureRate = pRateCtrl->goldenPictureRate; + rc_tmp.altrefPictureRate = pRateCtrl->altrefPictureRate; + + VP8InitRc(&rc_tmp, pEncInst->encStatus == VP8ENCSTAT_INIT); + + /* Set final values into instance */ + pEncInst->rateControl = rc_tmp; + + VPU_PLG_DBG("VP8EncSetRateCtrl: OK\n"); + return VP8ENC_OK; +} + +/*---------------------------------------------------------------------------- + + Function name : VP8EncGetRateCtrl + Description : Return current rate control parameters + + Return type : VP8EncRet + Argument : inst - the instance in use + pRateCtrl - place where parameters are returned +-----------------------------------------------------------------------------*/ +VP8EncRet VP8EncGetRateCtrl(VP8EncInst inst, VP8EncRateCtrl* pRateCtrl) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + + VPU_PLG_DBG("VP8EncGetRateCtrl#"); + + /* Check for illegal inputs */ + if (pEncInst == NULL || pRateCtrl == NULL) { + VPU_PLG_ERR("%s ERROR, Instance doesn't initialized\n", __func__); + return VP8ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if (pEncInst->inst != pEncInst) { + VPU_PLG_ERR("VP8EncGetRateCtrl: ERROR Invalid instance\n"); + return VP8ENC_INSTANCE_ERROR; + } + + pRateCtrl->qpHdr = pEncInst->rateControl.qpHdr; + pRateCtrl->pictureRc = pEncInst->rateControl.picRc; + pRateCtrl->pictureSkip = pEncInst->rateControl.picSkip; + pRateCtrl->qpMin = pEncInst->rateControl.qpMin; + pRateCtrl->qpMax = pEncInst->rateControl.qpMax; + pRateCtrl->bitPerSecond = pEncInst->rateControl.virtualBuffer.bitRate; + pRateCtrl->bitrateWindow = pEncInst->rateControl.gopLen; + pRateCtrl->intraQpDelta = pEncInst->rateControl.intraQpDelta; + pRateCtrl->fixedIntraQp = pEncInst->rateControl.fixedIntraQp; + pRateCtrl->intraPictureRate = pEncInst->rateControl.intraPictureRate; + pRateCtrl->goldenPictureRate = pEncInst->rateControl.goldenPictureRate; + pRateCtrl->altrefPictureRate = pEncInst->rateControl.altrefPictureRate; + + VPU_PLG_DBG("VP8EncGetRateCtrl: OK\n"); + return VP8ENC_OK; +} + +VP8EncRet VP8EncStrmEncodeResult(VP8EncInst inst, VP8EncOut* pEncOut, + uint32_t outputStreamSize) { + + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + picBuffer* picBuffer; + + pEncOut->frameSize = outputStreamSize; + + picBuffer = &pEncInst->picBuffer; + + /* Rate control action after frame */ + VP8AfterPicRc(&pEncInst->rateControl, outputStreamSize); + + if (picBuffer->cur_pic->i_frame) { + pEncOut->codingType = VP8ENC_INTRA_FRAME; + pEncOut->arf = pEncOut->grf = pEncOut->ipf = 0; + } else { + pEncOut->codingType = VP8ENC_PREDICTED_FRAME; + pEncOut->ipf = picBuffer->refPicList[0].search ? VP8ENC_REFERENCE : 0; + pEncOut->grf = picBuffer->refPicList[1].search ? VP8ENC_REFERENCE : 0; + pEncOut->arf = picBuffer->refPicList[2].search ? VP8ENC_REFERENCE : 0; + } + + /* Mark which reference frame was refreshed */ + pEncOut->arf |= picBuffer->cur_pic->arf ? VP8ENC_REFRESH : 0; + pEncOut->grf |= picBuffer->cur_pic->grf ? VP8ENC_REFRESH : 0; + pEncOut->ipf |= picBuffer->cur_pic->ipf ? VP8ENC_REFRESH : 0; + + UpdatePictureBuffer(picBuffer); + + /* Frame was encoded so increment frame number */ + pEncInst->frameCnt++; + pEncInst->encStatus = VP8ENCSTAT_START_FRAME; + pEncInst->prevFrameLost = 0; + + VPU_PLG_DBG("VP8EncStrmEncode: OK\n"); + return 0; +} + +void VP8EncGetFrameHeader(VP8EncInst inst, uint8_t** frmhdr, uint32_t* size) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + + *frmhdr = pEncInst->asic.frmhdr; + *size = pEncInst->asic.frmHdrBufLen; +} + +void VP8EncGetCabacCtx(VP8EncInst inst, uint8_t** cabac, uint32_t* size) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + + *cabac = (uint8_t*)pEncInst->asic.cabacCtx.vir_addr; + *size = pEncInst->asic.cabacCtx.size; +} + +void VP8EncGetSegmentMap(VP8EncInst inst, uint8_t** segmap, uint32_t* size) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + + *segmap = (uint8_t*)pEncInst->asic.segmentMap.vir_addr; + *size = pEncInst->asic.segmentMap.size; +} + +void VP8EncGetRegs(VP8EncInst inst, uint32_t** regs, uint32_t* size) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + + *regs = pEncInst->asic.regs.regMirror; + *size = sizeof(pEncInst->asic.regs.regMirror); +} + +VP8EncRet VP8EncSetProbCnt(VP8EncInst inst, uint8_t* probcnt, uint32_t size) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + if (probcnt == NULL || size > pEncInst->asic.probCount.size) { + VPU_PLG_ERR("Invalid input parameter\n"); + return -1; + } + + memcpy(pEncInst->asic.probCount.vir_addr, probcnt, size); + + return 0; +} + +/*---------------------------------------------------------------------------- + + Function name : VP8EncStrmEncode + Description : Encodes a new picture + Return type : VP8EncRet + Argument : inst - encoder instance + Argument : pEncIn - user provided input parameters + pEncOut - place where output info is returned +-----------------------------------------------------------------------------*/ +VP8EncRet VP8EncStrmEncode(VP8EncInst inst, const VP8EncIn* pEncIn, + VP8EncOut* pEncOut, EncoderParameters* cml) { + vp8Instance_s* pEncInst = (vp8Instance_s*)inst; + picBuffer* picBuffer; + int32_t i; + VP8EncPictureCodingType ct; + + VPU_PLG_DBG("VP8EncStrmEncode#\n"); + + /* Check for illegal inputs */ + if ((pEncInst == NULL) || (pEncIn == NULL) || (pEncOut == NULL)) { + VPU_PLG_ERR("VP8EncStrmEncode: ERROR Null argument\n"); + return VP8ENC_NULL_ARGUMENT; + } + + /* Check for existing instance */ + if (pEncInst->inst != pEncInst) { + VPU_PLG_ERR("VP8EncStrmEncode: ERROR Invalid instance\n"); + return VP8ENC_INSTANCE_ERROR; + } + + /* Clear the output structure */ + pEncOut->codingType = VP8ENC_NOTCODED_FRAME; + pEncOut->frameSize = 0; + for (i = 0; i < 9; i++) { + pEncOut->pOutBuf[i] = NULL; + pEncOut->streamSize[i] = 0; + } + + /* Check status, ERROR not allowed */ + if ((pEncInst->encStatus != VP8ENCSTAT_INIT) && + (pEncInst->encStatus != VP8ENCSTAT_KEYFRAME) && + (pEncInst->encStatus != VP8ENCSTAT_START_FRAME)) { + VPU_PLG_ERR("VP8EncStrmEncode: ERROR Invalid status\n"); + return VP8ENC_INVALID_STATUS; + } + + /* Choose frame coding type */ + ct = pEncIn->codingType; + + /* Status may affect the frame coding type */ + if ((pEncInst->encStatus == VP8ENCSTAT_INIT) || + (pEncInst->encStatus == VP8ENCSTAT_KEYFRAME)) + ct = VP8ENC_INTRA_FRAME; + + /* Divide stream buffer for every partition */ + { + uint8_t* pStart = (uint8_t*)pEncInst->asic.frmhdr; + uint32_t bufSize = pEncInst->asic.frmHdrBufLen; + uint8_t* pEnd; + int32_t status = ENCHW_OK; + + /* Frame tag 10 bytes (I-frame) or 3 bytes (P-frame), + * written by SW at end of frame */ + pEnd = pStart + 3; + if (ct == VP8ENC_INTRA_FRAME) pEnd += 7; + if (VP8SetBuffer(&pEncInst->buffer[0], pStart, pEnd - pStart) == ENCHW_NOK) + status = ENCHW_NOK; + + pStart = pEnd; + pEnd = pStart + bufSize; + if (VP8SetBuffer(&pEncInst->buffer[1], pStart, pEnd - pStart) == ENCHW_NOK) + status = ENCHW_NOK; + + if (status == ENCHW_NOK) { + VPU_PLG_ERR("VP8 Set frame header buffer failed\n"); + return status; + } + } + + /* Initialize picture buffer and ref pic list according to frame type */ + picBuffer = &pEncInst->picBuffer; + picBuffer->cur_pic->show = 1; + picBuffer->cur_pic->poc = pEncInst->frameCnt; + picBuffer->cur_pic->i_frame = (ct == VP8ENC_INTRA_FRAME); + InitializePictureBuffer(picBuffer); + + /* Set picture buffer according to frame coding type */ + if (ct == VP8ENC_PREDICTED_FRAME) { + picBuffer->cur_pic->p_frame = 1; + picBuffer->cur_pic->arf = (pEncIn->arf & VP8ENC_REFRESH) ? 1 : 0; + picBuffer->cur_pic->grf = (pEncIn->grf & VP8ENC_REFRESH) ? 1 : 0; + picBuffer->cur_pic->ipf = (pEncIn->ipf & VP8ENC_REFRESH) ? 1 : 0; + picBuffer->refPicList[0].search = (pEncIn->ipf & VP8ENC_REFERENCE) ? 1 : 0; + picBuffer->refPicList[1].search = (pEncIn->grf & VP8ENC_REFERENCE) ? 1 : 0; + picBuffer->refPicList[2].search = (pEncIn->arf & VP8ENC_REFERENCE) ? 1 : 0; + } + + /* Rate control */ + VP8BeforePicRc(&pEncInst->rateControl, pEncIn->timeIncrement, + picBuffer->cur_pic->i_frame); + + /* Rate control may choose to skip the frame */ + if (pEncInst->rateControl.frameCoded == ENCHW_NO) { + VPU_PLG_DBG("VP8EncStrmEncode: OK, frame skipped"); + return VP8ENC_FRAME_READY; + } + + /* TODO: RC can set frame to grf and copy grf to arf */ + if (pEncInst->rateControl.goldenPictureRate) { + picBuffer->cur_pic->grf = 1; + if (!picBuffer->cur_pic->arf) + picBuffer->refPicList[1].arf = 1; + } + + /* Set some frame coding parameters before internal test configure */ + VP8SetFrameParams(pEncInst); + +#ifdef TRACE_STREAM + traceStream.frameNum = pEncInst->frameCnt; + traceStream.id = 0; /* Stream generated by SW */ + traceStream.bitCnt = 0; /* New frame */ +#endif + + /* Get the reference frame buffers from picture buffer */ + PictureBufferSetRef(picBuffer, &pEncInst->asic); + + /* Code one frame */ + VP8CodeFrame(pEncInst, cml); + + return VP8ENC_OK; +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h b/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h new file mode 100644 index 0000000..d37d474 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h @@ -0,0 +1,449 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _VP8ENCAPI_H_ +#define _VP8ENCAPI_H_ + +#include "vpu_mem.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* The maximum amount of frames for bitrate moving average calculation */ +#define MOVING_AVERAGE_FRAMES 30 + +typedef const void* VP8EncInst; + +/* Function return values */ +typedef enum +{ + VP8ENC_OK = 0, + VP8ENC_FRAME_READY = 1, + + VP8ENC_ERROR = -1, + VP8ENC_NULL_ARGUMENT = -2, + VP8ENC_INVALID_ARGUMENT = -3, + VP8ENC_MEMORY_ERROR = -4, + VP8ENC_EWL_ERROR = -5, + VP8ENC_EWL_MEMORY_ERROR = -6, + VP8ENC_INVALID_STATUS = -7, + VP8ENC_OUTPUT_BUFFER_OVERFLOW = -8, + VP8ENC_HW_BUS_ERROR = -9, + VP8ENC_HW_DATA_ERROR = -10, + VP8ENC_HW_TIMEOUT = -11, + VP8ENC_HW_RESERVED = -12, + VP8ENC_SYSTEM_ERROR = -13, + VP8ENC_INSTANCE_ERROR = -14, + VP8ENC_HRD_ERROR = -15, + VP8ENC_HW_RESET = -16 +} VP8EncRet; + +/* Picture YUV type for pre-processing */ +typedef enum +{ + VP8ENC_YUV420_PLANAR = 0, /* YYYY... UUUU... VVVV */ + VP8ENC_YUV420_SEMIPLANAR = 1, /* YYYY... UVUVUV... */ + VP8ENC_YUV422_INTERLEAVED_YUYV = 2, /* YUYVYUYV... */ + VP8ENC_YUV422_INTERLEAVED_UYVY = 3, /* UYVYUYVY... */ + VP8ENC_RGB565 = 4, /* 16-bit RGB */ + VP8ENC_BGR565 = 5, /* 16-bit RGB */ + VP8ENC_RGB555 = 6, /* 15-bit RGB */ + VP8ENC_BGR555 = 7, /* 15-bit RGB */ + VP8ENC_RGB444 = 8, /* 12-bit RGB */ + VP8ENC_BGR444 = 9, /* 12-bit RGB */ + VP8ENC_RGB888 = 10, /* 24-bit RGB */ + VP8ENC_BGR888 = 11, /* 24-bit RGB */ + VP8ENC_RGB101010 = 12, /* 30-bit RGB */ + VP8ENC_BGR101010 = 13 /* 30-bit RGB */ +} VP8EncPictureType; + +/* Picture rotation for pre-processing */ +typedef enum +{ + VP8ENC_ROTATE_0 = 0, + VP8ENC_ROTATE_90R = 1, /* Rotate 90 degrees clockwise */ + VP8ENC_ROTATE_90L = 2 /* Rotate 90 degrees counter-clockwise */ +} VP8EncPictureRotation; + +/* Picture color space conversion (RGB input) for pre-processing */ +typedef enum +{ + VP8ENC_RGBTOYUV_BT601 = 0, /* Color conversion according to BT.601 */ + VP8ENC_RGBTOYUV_BT709 = 1, /* Color conversion according to BT.709 */ + VP8ENC_RGBTOYUV_USER_DEFINED = 2 /* User defined color conversion */ +} VP8EncColorConversionType; + +/* Picture type for encoding */ +typedef enum +{ + VP8ENC_INTRA_FRAME = 0, + VP8ENC_PREDICTED_FRAME = 1, + VP8ENC_NOTCODED_FRAME = 2 /* Used just as a return value */ +} VP8EncPictureCodingType; + +/* Reference picture mode for reading and writing */ +typedef enum +{ + VP8ENC_NO_REFERENCE_NO_REFRESH = 0, + VP8ENC_REFERENCE = 1, + VP8ENC_REFRESH = 2, + VP8ENC_REFERENCE_AND_REFRESH = 3 +} VP8EncRefPictureMode; + +/* Definitions to enable encoder internal control of filter parameters */ +#define VP8ENC_FILTER_SHARPNESS_AUTO 8 +#define VP8ENC_FILTER_LEVEL_AUTO 64 + +/*------------------------------------------------------------------------------ + 3. Structures for API function parameters +------------------------------------------------------------------------------*/ + +/* Configuration info for initialization + * Width and height are picture dimensions after rotation + */ +typedef struct +{ + uint32_t refFrameAmount; /* Amount of reference frame buffers, [1..3] + * 1 = only last frame buffered, + * always predict from and refresh ipf, + * stream buffer overflow causes new key frame + * 2 = last and golden frames buffered + * 3 = last and golden and altref frame buffered */ + uint32_t width; /* Encoded picture width in pixels, multiple of 4 */ + uint32_t height; /* Encoded picture height in pixels, multiple of 2*/ + uint32_t frameRateNum; /* The stream time scale, [1..1048575] */ + uint32_t frameRateDenom; /* Maximum frame rate is frameRateNum/frameRateDenom + * in frames/second. [1..frameRateNum] */ +} VP8EncConfig; + +/* Defining rectangular macroblock area in encoded picture */ +typedef struct +{ + uint32_t enable; /* [0,1] Enables this area */ + uint32_t top; /* Top mb row inside area [0..heightMbs-1] */ + uint32_t left; /* Left mb row inside area [0..widthMbs-1] */ + uint32_t bottom; /* Bottom mb row inside area [top..heightMbs-1] */ + uint32_t right; /* Right mb row inside area [left..widthMbs-1] */ +} VP8EncPictureArea; + +/* Coding control parameters */ +typedef struct +{ + /* The following parameters can only be adjusted before stream is + * started. They affect the stream profile and decoding complexity. */ + uint32_t interpolationFilter; /* Defines the type of interpolation filter + * for reconstruction. [0..2] + * 0 = Bicubic (6-tap interpolation filter), + * 1 = Bilinear (2-tap interpolation filter), + * 2 = None (Full pixel motion vectors) */ + uint32_t filterType; /* Deblocking loop filter type, + * 0 = Normal deblocking filter, + * 1 = Simple deblocking filter */ + + /* The following parameters can be adjusted between frames. */ + uint32_t filterLevel; /* Deblocking filter level [0..64] + * 0 = No filtering, + * higher level => more filtering, + * VP8ENC_FILTER_LEVEL_AUTO = calculate + * filter level based on quantization */ + uint32_t filterSharpness; /* Deblocking filter sharpness [0..8], + * VP8ENC_FILTER_SHARPNESS_AUTO = calculate + * filter sharpness automatically */ + uint32_t dctPartitions; /* Amount of DCT coefficient partitions to + * create for each frame, subject to HW + * limitations on maximum partition amount. + * 0 = 1 DCT residual partition, + * 1 = 2 DCT residual partitions, + * 2 = 4 DCT residual partitions, + * 3 = 8 DCT residual partitions */ + uint32_t errorResilient; /* Enable error resilient stream mode. [0,1] + * This prevents cumulative probability + * updates. */ + uint32_t splitMv; /* Split MV mode ie. using more than 1 MV/MB + * 0=disabled, 1=adaptive, 2=enabled */ + uint32_t quarterPixelMv; /* 1/4 pixel motion estimation + * 0=disabled, 1=adaptive, 2=enabled */ + uint32_t cirStart; /* [0..mbTotal] First macroblock for + * Cyclic Intra Refresh */ + uint32_t cirInterval; /* [0..mbTotal] Macroblock interval for + * Cyclic Intra Refresh, 0=disabled */ + VP8EncPictureArea intraArea; /* Area for forcing intra macroblocks */ + VP8EncPictureArea roi1Area; /* Area for 1st Region-Of-Interest */ + VP8EncPictureArea roi2Area; /* Area for 2nd Region-Of-Interest */ + int32_t roi1DeltaQp; /* [-50..0] QP delta value for 1st ROI */ + int32_t roi2DeltaQp; /* [-50..0] QP delta value for 2nd ROI */ +} VP8EncCodingCtrl; + +/* Rate control parameters */ +typedef struct +{ + uint32_t pictureRc; /* Adjust QP between pictures, [0,1] */ + uint32_t pictureSkip; /* Allow rate control to skip pictures, [0,1] */ + int32_t qpHdr; /* QP for next encoded picture, [-1..127] + * -1 = Let rate control calculate initial QP. + * qpHdr is used for all pictures if + * pictureRc is disabled. */ + uint32_t qpMin; /* Minimum QP for any picture, [0..127] */ + uint32_t qpMax; /* Maximum QP for any picture, [0..127] */ + uint32_t bitPerSecond; /* Target bitrate in bits/second + * [10000..60000000] */ + uint32_t bitrateWindow; /* Number of pictures over which the target + * bitrate should be achieved. Smaller window + * maintains constant bitrate but forces rapid + * quality changes whereas larger window + * allows smoother quality changes. [1..150] */ + int32_t intraQpDelta; /* Intra QP delta. intraQP = QP + intraQpDelta + * This can be used to change the relative + * quality of the Intra pictures or to decrease + * the size of Intra pictures. [-12..12] */ + uint32_t fixedIntraQp; /* Fixed QP value for all Intra pictures, [0..127] + * 0 = Rate control calculates intra QP. */ + uint32_t intraPictureRate; /* The distance of two intra pictures, [0..300] + * This will force periodical intra pictures. + * 0=disabled. */ + uint32_t goldenPictureRate; /* The distance of two golden pictures, [0..300] + * This will force periodical golden pictures. + * 0=disabled. */ + uint32_t altrefPictureRate; /* The distance of two altref pictures, [0..300] + * This will force periodical altref pictures. + * 0=disabled. */ +} VP8EncRateCtrl; + +/* Encoder input structure */ +typedef struct +{ + uint32_t busLuma; /* Bus address for input picture + * planar format: luminance component + * semiplanar format: luminance component + * interleaved format: whole picture + */ + uint32_t busChromaU; /* Bus address for input chrominance + * planar format: cb component + * semiplanar format: both chrominance + * interleaved format: not used + */ + uint32_t busChromaV; /* Bus address for input chrominance + * planar format: cr component + * semiplanar format: not used + * interleaved format: not used + */ + VP8EncPictureCodingType codingType; /* Proposed picture coding type, + * INTRA/PREDICTED */ + uint32_t timeIncrement; /* The previous picture duration in units + * of 1/frameRateNum. 0 for the very first + * picture and typically equal to frameRateDenom + * for the rest. */ + + /* The following three parameters apply when + * codingType == PREDICTED. They define for each + * of the reference pictures if it should be used + * for prediction and if it should be refreshed + * with the encoded frame. There must always be + * atleast one (ipf/grf/arf) that is referenced + * and atleast one that is refreshed. + * Note that refFrameAmount may limit the + * availability of golden and altref frames. */ + VP8EncRefPictureMode ipf; /* Immediately previous == last frame */ + VP8EncRefPictureMode grf; /* Golden reference frame */ + VP8EncRefPictureMode arf; /* Alternative reference frame */ +} VP8EncIn; + +/* Encoder output structure */ +typedef struct +{ + VP8EncPictureCodingType codingType; /* Realized picture coding type, + * INTRA/PREDICTED/NOTCODED */ + uint32_t* pOutBuf[9]; /* Pointers to start of each partition in + * output stream buffer, + * pOutBuf[0] = Frame header + mb mode partition, + * pOutBuf[1] = First DCT partition, + * pOutBuf[2] = Second DCT partition (if exists) + * etc. */ + uint32_t streamSize[9]; /* Size of each partition of output stream + * in bytes. */ + uint32_t frameSize; /* Size of output frame in bytes + * (==sum of partition sizes) */ + int8_t* motionVectors; /* Pointer to buffer storing encoded frame MVs. + * One pixel motion vector x and y and + * corresponding SAD value for every macroblock. + * Format: mb0x mb0y mb0sadMsb mb0sadLsb mb1x .. */ + + /* The following three parameters apply when + * codingType == PREDICTED. They define for each + * of the reference pictures if it was used for + * prediction and it it was refreshed. */ + VP8EncRefPictureMode ipf; /* Immediately previous == last frame */ + VP8EncRefPictureMode grf; /* Golden reference frame */ + VP8EncRefPictureMode arf; /* Alternative reference frame */ +} VP8EncOut; + +/* Input pre-processing */ +typedef struct +{ + VP8EncColorConversionType type; + uint16_t coeffA; /* User defined color conversion coefficient */ + uint16_t coeffB; /* User defined color conversion coefficient */ + uint16_t coeffC; /* User defined color conversion coefficient */ + uint16_t coeffE; /* User defined color conversion coefficient */ + uint16_t coeffF; /* User defined color conversion coefficient */ +} VP8EncColorConversion; + +/* Version information */ +typedef struct +{ + uint32_t major; /* Encoder API major version */ + uint32_t minor; /* Encoder API minor version */ +} VP8EncApiVersion; + +typedef struct +{ + uint32_t swBuild; /* Software build ID */ + uint32_t hwBuild; /* Hardware build ID */ +} VP8EncBuild; + + +typedef struct { + int32_t frame[MOVING_AVERAGE_FRAMES]; + int32_t length; + int32_t count; + int32_t pos; + int32_t frameRateNumer; + int32_t frameRateDenom; +} ma_s; + +/* Structure for command line options and testbench variables */ +typedef struct +{ + int32_t width; + int32_t height; + int32_t lumWidthSrc; + int32_t lumHeightSrc; + int32_t horOffsetSrc; + int32_t verOffsetSrc; + int32_t outputRateNumer; + int32_t outputRateDenom; + int32_t refFrameAmount; + + int32_t inputFormat; + int32_t rotation; + int32_t colorConversion; + int32_t videoStab; + + int32_t bitPerSecond; + int32_t picRc; + int32_t picSkip; + int32_t gopLength; + int32_t qpHdr; + int32_t qpMin; + int32_t qpMax; + int32_t intraQpDelta; + int32_t fixedIntraQp; + + int32_t intraPicRate; + int32_t dctPartitions; /* Dct data partitions 0=1, 1=2, 2=4, 3=8 */ + int32_t errorResilient; + int32_t ipolFilter; + int32_t quarterPixelMv; + int32_t splitMv; + int32_t filterType; + int32_t filterLevel; + int32_t filterSharpness; + int32_t cirStart; + int32_t cirInterval; + int32_t intraAreaEnable; + int32_t intraAreaLeft; + int32_t intraAreaTop; + int32_t intraAreaRight; + int32_t intraAreaBottom; + int32_t roi1AreaEnable; + int32_t roi2AreaEnable; + int32_t roi1AreaTop; + int32_t roi1AreaLeft; + int32_t roi1AreaBottom; + int32_t roi1AreaRight; + int32_t roi2AreaTop; + int32_t roi2AreaLeft; + int32_t roi2AreaBottom; + int32_t roi2AreaRight; + int32_t roi1DeltaQp; + int32_t roi2DeltaQp; + + int32_t printPsnr; + int32_t mvOutput; + int32_t droppable; + + int32_t intra16Favor; + int32_t intraPenalty; + + /* SW/HW shared memories for input/output buffers */ + VPUMemLinear_t pictureMem; + VPUMemLinear_t pictureStabMem; + + VP8EncRateCtrl rc; + VP8EncOut encOut; + + uint32_t streamSize; /* Size of output stream in bytes */ + uint32_t bitrate; /* Calculate average bitrate of encoded frames */ + ma_s ma; /* Calculate moving average of bitrate */ + uint32_t psnrSum; /* Calculate average PSNR over encoded frames */ + uint32_t psnrCnt; + + int32_t frameCnt; /* Frame counter of input file */ + uint64_t frameCntTotal; /* Frame counter of all frames */ +} EncoderParameters; + + +/* Initialization & release */ +VP8EncRet VP8EncInit(const VP8EncConfig* pEncConfig, + VP8EncInst* instAddr); +VP8EncRet VP8EncRelease(VP8EncInst inst); + +/* Encoder configuration before stream generation */ +VP8EncRet VP8EncSetCodingCtrl(VP8EncInst inst, const VP8EncCodingCtrl* + pCodingParams); +VP8EncRet VP8EncGetCodingCtrl(VP8EncInst inst, VP8EncCodingCtrl* + pCodingParams); + +/* Encoder configuration before and during stream generation */ +VP8EncRet VP8EncSetRateCtrl(VP8EncInst inst, + const VP8EncRateCtrl* pRateCtrl); +VP8EncRet VP8EncGetRateCtrl(VP8EncInst inst, + VP8EncRateCtrl* pRateCtrl); + +/* Stream generation */ + +void VP8EncGetFrameHeader(VP8EncInst inst, uint8_t** frmhdr, uint32_t* size); +void VP8EncGetCabacCtx(VP8EncInst inst, uint8_t** cabac, uint32_t* size); +void VP8EncGetSegmentMap(VP8EncInst inst, uint8_t** segmap, uint32_t* size); +void VP8EncGetRegs(VP8EncInst inst, uint32_t** regs, uint32_t* size); +VP8EncRet VP8EncSetProbCnt(VP8EncInst inst, uint8_t* probcnt, uint32_t size); + +/* VP8EncStrmEncode encodes one video frame. */ +VP8EncRet VP8EncStrmEncodeResult(VP8EncInst inst, VP8EncOut* pEncOut, uint32_t outputStreamSize); +VP8EncRet VP8EncStrmEncode(VP8EncInst inst, const VP8EncIn* pEncIn, + VP8EncOut* pEncOut, EncoderParameters* cml); + +void PrintTitle(EncoderParameters* cml); +void PrintFrame(EncoderParameters* cml, VP8EncInst encoder, uint32_t frameNumber, + VP8EncRet ret); + +#ifdef __cplusplus +} +#endif + +#endif /*__VP8ENCAPI_H__*/ diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8entropy.c b/libv4l-rockchip/libvpu/vp8_enc/vp8entropy.c new file mode 100644 index 0000000..d9719fd --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8entropy.c @@ -0,0 +1,530 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include "vp8entropy.h" + +#include <memory.h> +#include "enccommon.h" +#include "vp8entropytable.h" +#include "vp8macroblocktools.h" + +/* Approximate bit cost of bin at given probability prob */ +#define COST_BOOL(prob, bin)\ + ((bin) ? vp8_prob_cost[255 - (prob)] : vp8_prob_cost[prob]) + +enum { + MAX_BAND = 7, + MAX_CTX = 3, +}; + +static int32_t CostTree(tree const* tree, int32_t* prob); +static void UpdateEntropy(vp8Instance_s* inst); + +void EncSwapEndianess(uint32_t* buf, uint32_t sizeBytes) { +#if (ENCH1_OUTPUT_SWAP_8 == 1) + uint32_t i = 0; + int32_t words = sizeBytes / 4; + + ASSERT((sizeBytes % 8) == 0); + + while (words > 0) { + uint32_t val = buf[i]; + uint32_t tmp = 0; + + tmp |= (val & 0xFF) << 24; + tmp |= (val & 0xFF00) << 8; + tmp |= (val & 0xFF0000) >> 8; + tmp |= (val & 0xFF000000) >> 24; + +#if(ENCH1_OUTPUT_SWAP_32 == 1) /* need this for 64-bit HW */ + { + uint32_t val2 = buf[i + 1]; + uint32_t tmp2 = 0; + + tmp2 |= (val2 & 0xFF) << 24; + tmp2 |= (val2 & 0xFF00) << 8; + tmp2 |= (val2 & 0xFF0000) >> 8; + tmp2 |= (val2 & 0xFF000000) >> 24; + + buf[i] = tmp2; + words--; + i++; + } +#endif + buf[i] = tmp; + words--; + i++; + } +#endif + +} + +void InitEntropy(vp8Instance_s* inst) { + entropy* entropy = inst->entropy; + + ASSERT(sizeof(defaultCoeffProb) == sizeof(entropy->coeffProb)); + ASSERT(sizeof(defaultCoeffProb) == sizeof(coeffUpdateProb)); + ASSERT(sizeof(defaultMvProb) == sizeof(mvUpdateProb)); + ASSERT(sizeof(defaultMvProb) == sizeof(entropy->mvProb)); + + UpdateEntropy(inst); + + /* Default propability */ + entropy->lastProb = 255; /* Stetson-Harrison method TODO */ + entropy->gfProb = 128; /* Stetson-Harrison method TODO */ + memcpy(entropy->YmodeProb, YmodeProb, sizeof(YmodeProb)); + memcpy(entropy->UVmodeProb, UVmodeProb, sizeof(UVmodeProb)); +} + +void WriteEntropyTables(vp8Instance_s* inst) { + entropy* entropy = inst->entropy; + uint8_t* table = (uint8_t*)inst->asic.cabacCtx.vir_addr; + int32_t i, j, k, l; + + ASSERT(table); + + /* Write probability tables to ASIC linear memory, reg + mem */ + memset(table, 0, 56); + table[0] = entropy->skipFalseProb; + table[1] = entropy->intraProb; + table[2] = entropy->lastProb; + table[3] = entropy->gfProb; + table[4] = entropy->segmentProb[0]; + table[5] = entropy->segmentProb[1]; + table[6] = entropy->segmentProb[2]; + + table[8] = entropy->YmodeProb[0]; + table[9] = entropy->YmodeProb[1]; + table[10] = entropy->YmodeProb[2]; + table[11] = entropy->YmodeProb[3]; + table[12] = entropy->UVmodeProb[0]; + table[13] = entropy->UVmodeProb[1]; + table[14] = entropy->UVmodeProb[2]; + + /* MV probabilities x+y: short, sign, size 8-9 */ + table[16] = entropy->mvProb[1][0]; + table[17] = entropy->mvProb[0][0]; + table[18] = entropy->mvProb[1][1]; + table[19] = entropy->mvProb[0][1]; + table[20] = entropy->mvProb[1][17]; + table[21] = entropy->mvProb[1][18]; + table[22] = entropy->mvProb[0][17]; + table[23] = entropy->mvProb[0][18]; + + /* MV X size */ + for (i = 0; i < 8; i++) + table[24 + i] = entropy->mvProb[1][9 + i]; + + /* MV Y size */ + for (i = 0; i < 8; i++) + table[32 + i] = entropy->mvProb[0][9 + i]; + + /* MV X short tree */ + for (i = 0; i < 7; i++) + table[40 + i] = entropy->mvProb[1][2 + i]; + + /* MV Y short tree */ + for (i = 0; i < 7; i++) + table[48 + i] = entropy->mvProb[0][2 + i]; + + /* Update the ASIC table when needed. */ + if (entropy->updateCoeffProbFlag) { + table += 56; + /* DCT coeff probabilities 0-2, two fields per line. */ + for (i = 0; i < 4; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 3; k++) { + for (l = 0; l < 3; l++) { + *table++ = entropy->coeffProb[i][j][k][l]; + } + *table++ = 0; + } + + /* ASIC second probability table in ext mem. + * DCT coeff probabilities 4 5 6 7 8 9 10 3 on each line. + * coeff 3 was moved from first table to second so it is last. */ + for (i = 0; i < 4; i++) + for (j = 0; j < 8; j++) + for (k = 0; k < 3; k++) { + for (l = 4; l < 11; l++) { + *table++ = entropy->coeffProb[i][j][k][l]; + } + *table++ = entropy->coeffProb[i][j][k][3]; + } + } + + table = (uint8_t*)inst->asic.cabacCtx.vir_addr; + if (entropy->updateCoeffProbFlag) + EncSwapEndianess((uint32_t*)table, 56 + 8 * 48 + 8 * 96); + else + EncSwapEndianess((uint32_t*)table, 56); +} + +void InitTreePenaltyTables(vp8Instance_s* container) { + mbs* mbs = &container->mbs; /* Macroblock related stuff */ + int32_t tmp, i; + + /* Calculate bit cost for each 16x16 mode, uses p-frame probs */ + for (i = DC_PRED; i <= B_PRED; i++) { + tmp = CostTree(YmodeTree[i], (int32_t*)YmodeProb); + mbs->intra16ModeBitCost[i] = tmp; + } + + /* Calculate bit cost for each 4x4 mode, uses p-frame probs */ + for (i = B_DC_PRED; i <= B_HU_PRED; i++) { + tmp = CostTree(BmodeTree[i], (int32_t*)BmodeProb); + mbs->intra4ModeBitCost[i] = tmp; + } +} + +int32_t CostTree(tree const* tree, int32_t* prob) { + int32_t value = tree->value; + int32_t number = tree->number; + int32_t const* index = tree->index; + int32_t bitCost = 0; + + while (number--) { + bitCost += COST_BOOL(prob[*index++], (value >> number) & 1); + } + + return bitCost; +} + +int32_t CostMv(int32_t mvd, int32_t* mvProb) { + int32_t i, tmp, bitCost = 0; + + /* Luma motion vectors are doubled, see 18.1 in "VP8 Data Format and + * Decoding Guide". */ + ASSERT(!(mvd & 1)); + tmp = ABS(mvd >> 1); + + /* Short Tree */ + if (tmp < 8) { + bitCost += COST_BOOL(mvProb[0], 0); + bitCost += CostTree(&mvTree[tmp], mvProb + 2); + if (!tmp) return bitCost; + + /* Sign */ + bitCost += COST_BOOL(mvProb[1], mvd < 0); + return bitCost; + } + + /* Long Tree */ + bitCost += COST_BOOL(mvProb[0], 1); + + /* Bits 0, 1, 2 */ + for (i = 0; i < 3; i++) { + bitCost += COST_BOOL(mvProb[9 + i], (tmp >> i) & 1); + } + + /* Bits 9, 8, 7, 6, 5, 4 */ + for (i = 9; i > 3; i--) { + bitCost += COST_BOOL(mvProb[9 + i], (tmp >> i) & 1); + } + + /* Bit 3: if ABS(mvd) < 8, it is coded with short tree, so if here + * ABS(mvd) <= 15, bit 3 must be one (because here we code values + * 8,...,15) and is not explicitly coded. */ + if (tmp > 15) { + bitCost += COST_BOOL(mvProb[9 + 3], (tmp >> 3) & 1); + } + + /* Sign */ + bitCost += COST_BOOL(mvProb[1], mvd < 0); + + return bitCost; +} + +void CoeffProb(vp8buffer* buffer, int32_t curr[4][8][3][11], + int32_t prev[4][8][3][11]) { + int32_t i, j, k, l; + int32_t prob, new, old; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 8; j++) { + for (k = 0; k < 3; k++) { + for (l = 0; l < 11; l++) { + prob = coeffUpdateProb[i][j][k][l]; + old = prev[i][j][k][l]; + new = curr[i][j][k][l]; + + if (new == old) { + VP8PutBool(buffer, prob, 0); + COMMENT("Coeff prob update"); + } else { + VP8PutBool(buffer, prob, 1); + COMMENT("Coeff prob update"); + VP8PutLit(buffer, new, 8); + COMMENT("New prob"); + } + } + } + } + } +} + +void MvProb(vp8buffer* buffer, int32_t curr[2][19], int32_t prev[2][19]) { + int32_t i, j; + int32_t prob, new, old; + + for (i = 0; i < 2; i++) { + for (j = 0; j < 19; j++) { + prob = mvUpdateProb[i][j]; + old = prev[i][j]; + new = curr[i][j]; + + if (new == old) { + VP8PutBool(buffer, prob, 0); + COMMENT("MV prob update"); + } else { + VP8PutBool(buffer, prob, 1); + COMMENT("MV prob update"); + VP8PutLit(buffer, new >> 1, 7); + COMMENT("New prob"); + } + } + } +} + +/*------------------------------------------------------------------------------ + update + determine if given probability is to be updated (savings larger than + cost of update) +------------------------------------------------------------------------------*/ +uint32_t update(uint32_t updP, uint32_t left, uint32_t right, uint32_t oldP, + uint32_t newP, uint32_t fixed) { + int32_t u, s; + + /* how much it costs to update a coeff */ + u = (int32_t)fixed + ((vp8_prob_cost[255 - updP] - vp8_prob_cost[updP]) >> 8); + /* bit savings if updated */ + s = ((int32_t)left * /* zero branch count */ + /* diff cost for '0' bin */ + (vp8_prob_cost[oldP] - vp8_prob_cost[newP]) + + (int32_t)right * /* one branch count */ + /* diff cost for '1' bin */ + (vp8_prob_cost[255 - oldP] - vp8_prob_cost[255 - newP])) >> 8; + + return (s > u); +} + +/*------------------------------------------------------------------------------ + mvprob + compute new mv probability +------------------------------------------------------------------------------*/ +uint32_t mvprob(uint32_t left, uint32_t right, uint32_t oldP) { + uint32_t p; + + if (left + right) { + p = (left * 255) / (left + right); + p &= -2; + if (!p) p = 1; + } else + p = oldP; + + return p; +} + +/*------------------------------------------------------------------------------ + UpdateEntropy +------------------------------------------------------------------------------*/ +void UpdateEntropy(vp8Instance_s* inst) { + entropy* entropy = inst->entropy; + int32_t i, j, k, l, tmp, ii; + uint16_t* pCnt = (uint16_t*)inst->asic.probCount.vir_addr; + uint16_t* pTmp; + uint32_t p, left, right, oldP, updP; + uint32_t type; + uint32_t branchCnt[2]; + const int32_t offset[] = { + -1, -1, -1, 0, 1, 2, -1, 3, 4, -1, 5, 6, -1, 7, 8, -1, + 9, 10, -1, 11, 12, 13, 14, 15, -1, 16, 17, -1, 18, 19, -1, 20, + 21, -1, 22, 23, -1, 24, 25, -1, 26, 27, 28, 29, 30, -1, 31, 32, + -1, 33, 34, -1, 35, 36, -1, 37, 38, -1, 39, 40, -1, 41, 42, 43, + 44, 45, -1, 46, 47, -1, 48, 49, -1, 50, 51, -1, 52, 53, -1, 54, + 55, -1, 56, 57, -1, -1, -1, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219 }; + + /* Update the HW prob table only when needed. */ + entropy->updateCoeffProbFlag = 0; + + /* Use default propabilities as reference when needed. */ + if (!inst->sps.refreshEntropy || inst->picBuffer.cur_pic->i_frame) { + /* Only do the copying when something has changed. */ + if (!entropy->defaultCoeffProbFlag) { + memcpy(entropy->coeffProb, defaultCoeffProb, + sizeof(defaultCoeffProb)); + entropy->updateCoeffProbFlag = 1; + } + memcpy(entropy->mvProb, defaultMvProb, sizeof(defaultMvProb)); + entropy->defaultCoeffProbFlag = 1; + } + + /* store current probs */ + memcpy(entropy->oldCoeffProb, entropy->coeffProb, sizeof(entropy->coeffProb)); + if (inst->frameCnt == 0 || !inst->picBuffer.last_pic->i_frame) + memcpy(entropy->oldMvProb, entropy->mvProb, sizeof(entropy->mvProb)); + + /* init probs */ + entropy->skipFalseProb = defaultSkipFalseProb[inst->rateControl.qpHdr]; + + /* Do not update on first frame, token/branch counters not valid yet. */ + if (inst->frameCnt == 0) return; + + /* Do not update probabilities for droppable frames. */ + if (!inst->picBuffer.cur_pic->ipf && !inst->picBuffer.cur_pic->grf && + !inst->picBuffer.cur_pic->arf) return; + + /* If previous frame was lost the prob counters are not valid. */ + if (inst->prevFrameLost) return; + +#ifdef TRACE_PROBS + /* Trace HW output prob counters into file */ + EncTraceProbs(pCnt, ASIC_VP8_PROB_COUNT_SIZE); +#endif + + /* All four block types */ + for (i = 0; i < 4; i++) { + /* All but last (==7) bands */ + for (j = 0; j < MAX_BAND; j++) + /* All three neighbour contexts */ + for (k = 0; k < MAX_CTX; k++) { + /* last token of current (type,band,ctx) */ + tmp = i * MAX_BAND * MAX_CTX + j * MAX_CTX + k; + tmp += 2 * 4 * MAX_BAND * MAX_CTX; + ii = offset[tmp]; + + right = ii >= 0 ? pCnt[ii] : 0; + + /* first two branch probabilities */ + for (l = 2; l--;) { + oldP = entropy->coeffProb[i][j][k][l]; + updP = coeffUpdateProb[i][j][k][l]; + + tmp -= 4 * MAX_BAND * MAX_CTX; + ii = offset[tmp]; + left = ii >= 0 ? pCnt[ii] : 0; + /* probability of 0 for current branch */ + if (left + right) { + p = ((left * 256) + ((left + right) >> 1)) / (left + right); + if (p > 255) p = 255; + } else + p = oldP; + + if (update(updP, left, right, oldP, p, 8)) { + entropy->coeffProb[i][j][k][l] = p; + entropy->updateCoeffProbFlag = 1; + } + right += left; + } + } + } + + /* If updating coeffProbs the defaults are no longer in use. */ + if (entropy->updateCoeffProbFlag) + entropy->defaultCoeffProbFlag = 0; + + /* skip prob */ + pTmp = pCnt + ASIC_VP8_PROB_COUNT_MODE_OFFSET; + p = pTmp[0] * 256 / inst->mbPerFrame; + entropy->skipFalseProb = CLIP3(256 - (int32_t)p, 0, 255); + + /* intra prob,, do not update if previous was I frame */ + if (!inst->picBuffer.last_pic->i_frame) { + p = pTmp[1] * 255 / inst->mbPerFrame; + entropy->intraProb = CLIP3(p, 0, 255); + } else + entropy->intraProb = 63; /* TODO default value */ + + /* MV probs shouldn't be updated if previous or current frame is intra */ + if (inst->picBuffer.last_pic->i_frame || inst->picBuffer.cur_pic->i_frame) + return; + + /* mv probs */ + pTmp = pCnt + ASIC_VP8_PROB_COUNT_MV_OFFSET; + for (i = 0; i < 2; i++) { + /* is short prob */ + left = *pTmp++; /* short */ + right = *pTmp++; /* long */ + + p = mvprob(left, right, entropy->oldMvProb[i][0]); + if (update(mvUpdateProb[i][0], left, right, + entropy->oldMvProb[i][0], p, 6)) + entropy->mvProb[i][0] = p; + + /* sign prob */ + right += left; /* total mvs */ + left = *pTmp++; /* num positive */ + /* amount of negative vectors = total - positive - zero vectors */ + right -= left - pTmp[0]; + + p = mvprob(left, right, entropy->oldMvProb[i][1]); + if (update(mvUpdateProb[i][1], left, right, + entropy->oldMvProb[i][1], p, 6)) + entropy->mvProb[i][1] = p; + + /* short mv probs, branches 2 and 3 (0/1 and 2/3) */ + for (j = 0; j < 2; j++) { + left = *pTmp++; + right = *pTmp++; + p = mvprob(left, right, entropy->oldMvProb[i][4 + j]); + if (update(mvUpdateProb[i][4 + j], left, right, + entropy->oldMvProb[i][4 + j], p, 6)) + entropy->mvProb[i][4 + j] = p; + branchCnt[j] = left + right; + } + /* short mv probs, branch 1 */ + p = mvprob(branchCnt[0], branchCnt[1], entropy->oldMvProb[i][3]); + if (update(mvUpdateProb[i][3], branchCnt[0], branchCnt[1], + entropy->oldMvProb[i][3], p, 6)) + entropy->mvProb[i][3] = p; + + /* store total count for branch 0 computation */ + type = branchCnt[0] + branchCnt[1]; + + /* short mv probs, branches 5 and 6 (4/5 and 6/7) */ + for (j = 0; j < 2; j++) { + left = *pTmp++; + right = *pTmp++; + p = mvprob(left, right, entropy->oldMvProb[i][7 + j]); + if (update(mvUpdateProb[i][7 + j], left, right, + entropy->oldMvProb[i][7 + j], p, 6)) + entropy->mvProb[i][7 + j] = p; + branchCnt[j] = left + right; + } + /* short mv probs, branch 4 */ + p = mvprob(branchCnt[0], branchCnt[1], entropy->oldMvProb[i][6]); + if (update(mvUpdateProb[i][6], branchCnt[0], branchCnt[1], + entropy->oldMvProb[i][6], p, 6)) + entropy->mvProb[i][6] = p; + + /* short mv probs, branch 0 */ + p = mvprob(type, branchCnt[0] + branchCnt[1], entropy->oldMvProb[i][2]); + if (update(mvUpdateProb[i][2], type, branchCnt[0] + branchCnt[1], + entropy->oldMvProb[i][2], p, 6)) + entropy->mvProb[i][2] = p; + } +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8entropy.h b/libv4l-rockchip/libvpu/vp8_enc/vp8entropy.h new file mode 100644 index 0000000..4168ea9 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8entropy.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef VP8ENTROPY_H +#define VP8ENTROPY_H + +#include "vp8entropytools.h" +#include "vp8putbits.h" +#include "vp8instance.h" + +void EncSwapEndianess(uint32_t* buf, uint32_t sizeBytes); +void InitEntropy(vp8Instance_s* inst); +void WriteEntropyTables(vp8Instance_s* inst); +void CoeffProb(vp8buffer* buffer, int32_t curr[4][8][3][11], + int32_t prev[4][8][3][11]); +void MvProb(vp8buffer* buffer, int32_t curr[2][19], int32_t prev[2][19]); +int32_t CostMv(int32_t mvd, int32_t* mvProb); + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8entropytable.h b/libv4l-rockchip/libvpu/vp8_enc/vp8entropytable.h new file mode 100644 index 0000000..3b20196 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8entropytable.h @@ -0,0 +1,697 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef VP8ENTROPY_TABLE_H +#define VP8ENTROPY_TABLE_H + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ +#include "vp8putbits.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/* Luma trees of keyframe and not key frame and default propability */ +static const tree const Ymode[] = { + { 0, 1, { 0 } }, /* (kf) B_PRED / DC_PRED 0 */ + { 4, 3, { 0, 1, 2 } }, /* (kf) DC_PRED / V_PRED 100 */ + { 5, 3, { 0, 1, 2 } }, /* (kf) V_PRED / H_PRED 101 */ + { 6, 3, { 0, 1, 3 } }, /* (kf) H_PRED / TM_PRED 110 */ + { 7, 3, { 0, 1, 3 } } /* (kf) TM_PRED / B_PRED 111 */ +}; + +static const tree const* YmodeTree[] = { + Ymode, /* prediction type = DC_PRED */ + Ymode + 1, /* prediction type = V_PRED */ + Ymode + 2, /* prediction type = H_PRED */ + Ymode + 3, /* prediction type = TM_PRED */ + Ymode + 4 /* prediction type = B_PRED */ +}; + +static const int32_t const kfYmodeProb[4] = { + 145, 156, 163, 128 +}; + +static const int32_t const YmodeProb[4] = { + 112, 86, 140, 37 +}; + +/* Luma tree of subblocks */ +static const tree const Bmode[] = { + { 0, 1, { 0 } }, /* B_DC_PRED, 0 */ + { 2, 2, { 0, 1 } }, /* B_TM_PRED, 10 */ + { 6, 3, { 0, 1, 2 } }, /* B_VE_PRED, 110 */ + { 28, 5, { 0, 1, 2, 3, 4 } }, /* B_HE_PRED, 11100 */ + { 58, 6, { 0, 1, 2, 3, 4, 5 } }, /* B_LD_PRED, 111010 */ + { 59, 6, { 0, 1, 2, 3, 4, 5 } }, /* B_RD_PRED, 111011 */ + { 30, 5, { 0, 1, 2, 3, 6 } }, /* B_VR_PRED, 11110 */ + { 62, 6, { 0, 1, 2, 3, 6, 7 } }, /* B_VL_PRED, 111110 */ + { 126, 7, { 0, 1, 2, 3, 6, 7, 8 } }, /* B_HD_PRED, 1111110 */ + { 127, 7, { 0, 1, 2, 3, 6, 7, 8 } } /* B_HU_PRED, 1111111 */ +}; + +static const tree const* BmodeTree[] = { + NULL, /* prediction type = DC_PRED, */ + NULL, /* prediction type = V_PRED, */ + NULL, /* prediction type = H_PRED, */ + NULL, /* prediction type = TM_PRED, */ + NULL, /* prediction type = B_PRED, */ + Bmode, /* prediction type = B_DC_PRED, */ + Bmode + 1, /* prediction type = B_TM_PRED, */ + Bmode + 2, /* prediction type = B_VE_PRED, */ + Bmode + 3, /* prediction type = B_HE_PRED, */ + Bmode + 6, /* prediction type = B_LD_PRED, */ + Bmode + 4, /* prediction type = B_RD_PRED, */ + Bmode + 5, /* prediction type = B_VR_PRED, */ + Bmode + 7, /* prediction type = B_VL_PRED, */ + Bmode + 8, /* prediction type = B_HD_PRED, */ + Bmode + 9 /* prediction type = B_HU_PRED, */ +}; + +static const int32_t const kfBmodeProb[10][10][9] = { + { + { 231, 120, 48, 89, 115, 113, 120, 152, 112 }, + { 152, 179, 64, 126, 170, 118, 46, 70, 95 }, + { 175, 69, 143, 80, 85, 82, 72, 155, 103 }, + { 56, 58, 10, 171, 218, 189, 17, 13, 152 }, + { 144, 71, 10, 38, 171, 213, 144, 34, 26 }, + { 114, 26, 17, 163, 44, 195, 21, 10, 173 }, + { 121, 24, 80, 195, 26, 62, 44, 64, 85 }, + { 170, 46, 55, 19, 136, 160, 33, 206, 71 }, + { 63, 20, 8, 114, 114, 208, 12, 9, 226 }, + { 81, 40, 11, 96, 182, 84, 29, 16, 36 } + }, + + { + { 134, 183, 89, 137, 98, 101, 106, 165, 148 }, + { 72, 187, 100, 130, 157, 111, 32, 75, 80 }, + { 66, 102, 167, 99, 74, 62, 40, 234, 128 }, + { 41, 53, 9, 178, 241, 141, 26, 8, 107 }, + { 104, 79, 12, 27, 217, 255, 87, 17, 7 }, + { 74, 43, 26, 146, 73, 166, 49, 23, 157 }, + { 65, 38, 105, 160, 51, 52, 31, 115, 128 }, + { 87, 68, 71, 44, 114, 51, 15, 186, 23 }, + { 47, 41, 14, 110, 182, 183, 21, 17, 194 }, + { 66, 45, 25, 102, 197, 189, 23, 18, 22 } + }, + + { + { 88, 88, 147, 150, 42, 46, 45, 196, 205 }, + { 43, 97, 183, 117, 85, 38, 35, 179, 61 }, + { 39, 53, 200, 87, 26, 21, 43, 232, 171 }, + { 56, 34, 51, 104, 114, 102, 29, 93, 77 }, + { 107, 54, 32, 26, 51, 1, 81, 43, 31 }, + { 39, 28, 85, 171, 58, 165, 90, 98, 64 }, + { 34, 22, 116, 206, 23, 34, 43, 166, 73 }, + { 68, 25, 106, 22, 64, 171, 36, 225, 114 }, + { 34, 19, 21, 102, 132, 188, 16, 76, 124 }, + { 62, 18, 78, 95, 85, 57, 50, 48, 51 } + }, + + { + { 193, 101, 35, 159, 215, 111, 89, 46, 111 }, + { 60, 148, 31, 172, 219, 228, 21, 18, 111 }, + { 112, 113, 77, 85, 179, 255, 38, 120, 114 }, + { 40, 42, 1, 196, 245, 209, 10, 25, 109 }, + { 100, 80, 8, 43, 154, 1, 51, 26, 71 }, + { 88, 43, 29, 140, 166, 213, 37, 43, 154 }, + { 61, 63, 30, 155, 67, 45, 68, 1, 209 }, + { 142, 78, 78, 16, 255, 128, 34, 197, 171 }, + { 41, 40, 5, 102, 211, 183, 4, 1, 221 }, + { 51, 50, 17, 168, 209, 192, 23, 25, 82 } + }, + + { + { 125, 98, 42, 88, 104, 85, 117, 175, 82 }, + { 95, 84, 53, 89, 128, 100, 113, 101, 45 }, + { 75, 79, 123, 47, 51, 128, 81, 171, 1 }, + { 57, 17, 5, 71, 102, 57, 53, 41, 49 }, + { 115, 21, 2, 10, 102, 255, 166, 23, 6 }, + { 38, 33, 13, 121, 57, 73, 26, 1, 85 }, + { 41, 10, 67, 138, 77, 110, 90, 47, 114 }, + { 101, 29, 16, 10, 85, 128, 101, 196, 26 }, + { 57, 18, 10, 102, 102, 213, 34, 20, 43 }, + { 117, 20, 15, 36, 163, 128, 68, 1, 26 } + }, + + { + { 138, 31, 36, 171, 27, 166, 38, 44, 229 }, + { 67, 87, 58, 169, 82, 115, 26, 59, 179 }, + { 63, 59, 90, 180, 59, 166, 93, 73, 154 }, + { 40, 40, 21, 116, 143, 209, 34, 39, 175 }, + { 57, 46, 22, 24, 128, 1, 54, 17, 37 }, + { 47, 15, 16, 183, 34, 223, 49, 45, 183 }, + { 46, 17, 33, 183, 6, 98, 15, 32, 183 }, + { 65, 32, 73, 115, 28, 128, 23, 128, 205 }, + { 40, 3, 9, 115, 51, 192, 18, 6, 223 }, + { 87, 37, 9, 115, 59, 77, 64, 21, 47 } + }, + + { + { 104, 55, 44, 218, 9, 54, 53, 130, 226 }, + { 64, 90, 70, 205, 40, 41, 23, 26, 57 }, + { 54, 57, 112, 184, 5, 41, 38, 166, 213 }, + { 30, 34, 26, 133, 152, 116, 10, 32, 134 }, + { 75, 32, 12, 51, 192, 255, 160, 43, 51 }, + { 39, 19, 53, 221, 26, 114, 32, 73, 255 }, + { 31, 9, 65, 234, 2, 15, 1, 118, 73 }, + { 88, 31, 35, 67, 102, 85, 55, 186, 85 }, + { 56, 21, 23, 111, 59, 205, 45, 37, 192 }, + { 55, 38, 70, 124, 73, 102, 1, 34, 98 } + }, + + { + { 102, 61, 71, 37, 34, 53, 31, 243, 192 }, + { 69, 60, 71, 38, 73, 119, 28, 222, 37 }, + { 68, 45, 128, 34, 1, 47, 11, 245, 171 }, + { 62, 17, 19, 70, 146, 85, 55, 62, 70 }, + { 75, 15, 9, 9, 64, 255, 184, 119, 16 }, + { 37, 43, 37, 154, 100, 163, 85, 160, 1 }, + { 63, 9, 92, 136, 28, 64, 32, 201, 85 }, + { 86, 6, 28, 5, 64, 255, 25, 248, 1 }, + { 56, 8, 17, 132, 137, 255, 55, 116, 128 }, + { 58, 15, 20, 82, 135, 57, 26, 121, 40 } + }, + + { + { 164, 50, 31, 137, 154, 133, 25, 35, 218 }, + { 51, 103, 44, 131, 131, 123, 31, 6, 158 }, + { 86, 40, 64, 135, 148, 224, 45, 183, 128 }, + { 22, 26, 17, 131, 240, 154, 14, 1, 209 }, + { 83, 12, 13, 54, 192, 255, 68, 47, 28 }, + { 45, 16, 21, 91, 64, 222, 7, 1, 197 }, + { 56, 21, 39, 155, 60, 138, 23, 102, 213 }, + { 85, 26, 85, 85, 128, 128, 32, 146, 171 }, + { 18, 11, 7, 63, 144, 171, 4, 4, 246 }, + { 35, 27, 10, 146, 174, 171, 12, 26, 128 } + }, + + { + { 190, 80, 35, 99, 180, 80, 126, 54, 45 }, + { 85, 126, 47, 87, 176, 51, 41, 20, 32 }, + { 101, 75, 128, 139, 118, 146, 116, 128, 85 }, + { 56, 41, 15, 176, 236, 85, 37, 9, 62 }, + { 146, 36, 19, 30, 171, 255, 97, 27, 20 }, + { 71, 30, 17, 119, 118, 255, 17, 18, 138 }, + { 101, 38, 60, 138, 55, 70, 43, 26, 142 }, + { 138, 45, 61, 62, 219, 1, 81, 188, 64 }, + { 32, 41, 20, 117, 151, 142, 20, 21, 163 }, + { 112, 19, 12, 61, 195, 128, 48, 4, 24 } + } +}; + +static const int32_t const BmodeProb[9] = { + 120, 90, 79, 133, 87, 85, 80, 111, 151 +}; + +static const int32_t const kfUVmodeProb[3] = { + 142, 114, 183 +}; + +static const int32_t const UVmodeProb[3] = { + 162, 101, 204 +}; + +static const int32_t const defaultCoeffProb[4][8][3][11] = { + { + { + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128 }, + { 189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128 }, + { 106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128 } + }, + { + { 1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128 }, + { 181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128 }, + { 78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128 } + }, + { + { 1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128 }, + { 184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128 }, + { 77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128 } + }, + { + { 1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128 }, + { 170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128 }, + { 37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128 } + }, + { + { 1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128 }, + { 207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128 }, + { 102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128 } + }, + { + { 1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128 }, + { 177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128 }, + { 80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128 } + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + + { + { + { 198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62 }, + { 131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1 }, + { 68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128 } + }, + { + { 1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128 }, + { 184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128 }, + { 81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128 } + }, + { + { 1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128 }, + { 99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128 }, + { 23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128 } + }, + { + { 1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128 }, + { 109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128 }, + { 44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128 } + }, + { + { 1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128 }, + { 94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128 }, + { 22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128 } + }, + { + { 1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128 }, + { 124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128 }, + { 35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128 } + }, + { + { 1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128 }, + { 121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128 }, + { 45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128 } + }, + { + { 1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128 } + } + }, + + { + { + { 253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128 }, + { 175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128 }, + { 73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128 } + }, + { + { 1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128 }, + { 239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128 }, + { 155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128 } + }, + { + { 1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128 }, + { 201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128 }, + { 69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128 } + }, + { + { 1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128 }, + { 141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128 } + }, + { + { 1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128 }, + { 149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128 }, + { 55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + }, + { + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 } + } + }, + + { + { + { 202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255 }, + { 126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128 }, + { 61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128 } + }, + { + { 1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128 }, + { 166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128 }, + { 39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128 } + }, + { + { 1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128 }, + { 124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128 }, + { 24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128 } + }, + { + { 1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128 }, + { 149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128 }, + { 28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128 } + }, + { + { 1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128 }, + { 123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128 }, + { 20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128 } + }, + { + { 1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128 }, + { 168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128 }, + { 47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128 } + }, + { + { 1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128 }, + { 141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128 }, + { 42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128 } + }, + { + { 1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 }, + { 238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128 } + } + } +}; + +static const int32_t const coeffUpdateProb[4][8][3][11] = { + { + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + { + { + { 217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255 }, + { 234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255 } + }, + { + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + + { + { + { 186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255 } + }, + { + { 255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + }, + + { + { + { 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + }, + { + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, + { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } + } + } +}; + +static const int32_t const mvUpdateProb[2][19] = { + { 237, 246, 253, 253, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 250, 250, 252, 254, 254 }, + + { 231, 243, 245, 253, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 251, 251, 254, 254, 254 } +}; + +static const int32_t const defaultMvProb[2][19] = { + { 162, 128, 225, 146, 172, 147, 214, 39, 156, 128, + 129, 132, 75, 145, 178, 206, 239, 254, 254 }, + + { 164, 128, 204, 170, 119, 235, 140, 230, 228, 128, + 130, 130, 74, 148, 180, 203, 236, 254, 254 } +}; + +static const int32_t const subMvPartProb[3] = { + 110, 111, 150 +}; + +static const int32_t const subMvRefProb[5][3] = { + { 147, 136, 18 }, + { 106, 145, 1 }, + { 179, 121, 1 }, + { 223, 1, 34 }, + { 208, 1, 1 } +}; + +/* Motion vector tree */ +static const tree const mvTree[] = { + { 0, 3, { 0, 1, 2 } }, /* mv_0 000 */ + { 1, 3, { 0, 1, 2 } }, /* mv_1 001 */ + { 2, 3, { 0, 1, 3 } }, /* mv_2 010 */ + { 3, 3, { 0, 1, 3 } }, /* mv_3 011 */ + { 4, 3, { 0, 4, 5 } }, /* mv_4 100 */ + { 5, 3, { 0, 4, 5 } }, /* mv_5 101 */ + { 6, 3, { 0, 4, 6 } }, /* mv_6 110 */ + { 7, 3, { 0, 4, 6 } }, /* mv_7 111 */ +}; + +/* Segment tree and default propability */ +static const tree const segmentTree[] = { + { 0, 2, { 0, 1 } }, /* segmentId = 0, 00 */ + { 1, 2, { 0, 1 } }, /* segmentId = 1, 01 */ + { 2, 2, { 0, 2 } }, /* segmentId = 2, 10 */ + { 3, 2, { 0, 2 } }, /* segmentId = 3, 11 */ +}; + +static const int32_t const segmentProb[3] = { + 255, 255, 255 +}; + +/* If probability being zero is p, then avarage bits used when bool is +zero = log2(1/p) and when bool is one = log2(1/(1-p)). + +For example bins probability being zero is p = 0.5 +bin = 0 -> average bits used is log2(1/0.5) = 1 bits/bin +bin = 1 -> average bits used is log2(1/(1 - 0.5) = 1 bits/bin + +For example bins probability being zero is p = 0.95 +bin = 0 -> average bits used is log2(1/0.95) = 0.074 bits/bin +bin = 1 -> average bits used is log2(1/(1 - 0.95) = 4.321 bits/bin + +Table cost[] below is calculated as follow: cost[p] is zero bin's average bit +cost at given p = [1..255] (note that probability is p/256) scaled up by SCALE. +for (i = 0; i < 256; i++) cost[i] = round((log2((double)256/i) * SCALE)). +Magic number SCALE = 256. */ +static const int32_t const vp8_prob_cost[] = { + 2048, 2048, 1792, 1642, 1536, 1454, 1386, 1329, 1280, 1236, + 1198, 1162, 1130, 1101, 1073, 1048, 1024, 1002, 980, 961, + 942, 924, 906, 890, 874, 859, 845, 831, 817, 804, + 792, 780, 768, 757, 746, 735, 724, 714, 705, 695, + 686, 676, 668, 659, 650, 642, 634, 626, 618, 611, + 603, 596, 589, 582, 575, 568, 561, 555, 548, 542, + 536, 530, 524, 518, 512, 506, 501, 495, 490, 484, + 479, 474, 468, 463, 458, 453, 449, 444, 439, 434, + 430, 425, 420, 416, 412, 407, 403, 399, 394, 390, + 386, 382, 378, 374, 370, 366, 362, 358, 355, 351, + 347, 343, 340, 336, 333, 329, 326, 322, 319, 315, + 312, 309, 305, 302, 299, 296, 292, 289, 286, 283, + 280, 277, 274, 271, 268, 265, 262, 259, 256, 253, + 250, 247, 245, 242, 239, 236, 234, 231, 228, 226, + 223, 220, 218, 215, 212, 210, 207, 205, 202, 200, + 197, 195, 193, 190, 188, 185, 183, 181, 178, 176, + 174, 171, 169, 167, 164, 162, 160, 158, 156, 153, + 151, 149, 147, 145, 143, 140, 138, 136, 134, 132, + 130, 128, 126, 124, 122, 120, 118, 116, 114, 112, + 110, 108, 106, 104, 102, 101, 99, 97, 95, 93, + 91, 89, 87, 86, 84, 82, 80, 78, 77, 75, + 73, 71, 70, 68, 66, 64, 63, 61, 59, 58, + 56, 54, 53, 51, 49, 48, 46, 44, 43, 41, + 40, 38, 36, 35, 33, 32, 30, 28, 27, 25, + 24, 22, 21, 19, 18, 16, 15, 13, 12, 10, + 9, 7, 6, 4, 3, 1 +}; + +static const int32_t const defaultSkipFalseProb[128] = +{ + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 251, 248, 244, 240, 236, 232, 229, 225, + 221, 217, 213, 208, 204, 199, 194, 190, + 187, 183, 179, 175, 172, 168, 164, 160, + 157, 153, 149, 145, 142, 138, 134, 130, + 127, 124, 120, 117, 114, 110, 107, 104, + 101, 98, 95, 92, 89, 86, 83, 80, + 77, 74, 71, 68, 65, 62, 59, 56, + 53, 50, 47, 44, 41, 38, 35, 32, + 30, 28, 26, 24, 22, 20, 18, 16, +}; + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8entropytools.h b/libv4l-rockchip/libvpu/vp8_enc/vp8entropytools.h new file mode 100644 index 0000000..53dc86d --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8entropytools.h @@ -0,0 +1,45 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _VP8ENTROPY_TOOLS_H_ +#define _VP8ENTROPY_TOOLS_H_ + +#include <stdint.h> + +typedef struct { + int32_t skipFalseProb; + int32_t intraProb; + int32_t lastProb; + int32_t gfProb; + int32_t kfYmodeProb[4]; + int32_t YmodeProb[4]; + int32_t kfUVmodeProb[3]; + int32_t UVmodeProb[3]; + int32_t kfBmodeProb[10][10][9]; + int32_t BmodeProb[9]; + int32_t coeffProb[4][8][3][11]; + int32_t oldCoeffProb[4][8][3][11]; + int32_t mvRefProb[4]; + int32_t mvProb[2][19]; + int32_t oldMvProb[2][19]; + int32_t subMvPartProb[3]; /* TODO use pointer directly to subMvPartProb */ + int32_t subMvRefProb[5][3]; /* TODO use pointer directly to subMvRefProb */ + int32_t defaultCoeffProbFlag; /* Flag for coeffProb == defaultCoeffProb */ + int32_t updateCoeffProbFlag; /* Flag for coeffProb != oldCoeffProb */ + int32_t segmentProb[3]; +} entropy; + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8header.c b/libv4l-rockchip/libvpu/vp8_enc/vp8header.c new file mode 100644 index 0000000..01dac05 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8header.c @@ -0,0 +1,378 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include "vp8header.h" + +#include <memory.h> +#include "vp8entropy.h" + +static void Segmentation(vp8buffer* buffer, sps* sps, ppss* ppss, + entropy* entropy, mbs* mbs); +static void FilterLevelDelta(vp8buffer* buffer, sps* sps); + +void VP8FrameHeader(vp8Instance_s* container) { + refPic* cur_pic = container->picBuffer.cur_pic; + refPic* refPicList = container->picBuffer.refPicList; + entropy* entropy = container->entropy; + sps* sps = &container->sps; /* Sequence container */ + pps* pps = container->ppss.pps; + vp8buffer* buffer = &container->buffer[1]; /* "Frame header" buffer */ + + /* Color space and pixel Type (Key frames only) */ + if (cur_pic->i_frame) { + VP8PutLit(buffer, sps->colorType, 1); + COMMENT("Frame header, buffer 1, color space type"); + + VP8PutLit(buffer, sps->clampType, 1); + COMMENT("Frame header, buffer 1, clamping type"); + } + + /* Segmentation */ + VP8PutLit(buffer, pps->segmentEnabled, 1); + COMMENT("Frame header, buffer 1, segmentation flag"); + if (pps->segmentEnabled) { + Segmentation(buffer, &container->sps, &container->ppss, + entropy, &container->mbs); + } + + VP8PutLit(buffer, sps->filterType, 1); + COMMENT("Frame header, buffer 1, filter type"); + + VP8PutLit(buffer, sps->filterLevel, 6); + COMMENT("Frame header, buffer 1, filter level"); + + VP8PutLit(buffer, sps->filterSharpness, 3); + COMMENT("Frame header, buffer 1, filter sharpness level"); + + /* Loop filter adjustments */ + VP8PutLit(buffer, sps->filterDeltaEnable, 1); + COMMENT("Frame header, buffer 1, loop filter adjustments"); + if (sps->filterDeltaEnable) { + /* Filter level delta references reset by key frame */ + if (cur_pic->i_frame) { + memset(sps->oldRefDelta, 0, sizeof(sps->refDelta)); + memset(sps->oldModeDelta, 0, sizeof(sps->modeDelta)); + } + FilterLevelDelta(buffer, sps); + } + + VP8PutLit(buffer, sps->dctPartitions, 2); + COMMENT("Frame header, buffer 1, token partition"); + + VP8PutLit(buffer, container->rateControl.qpHdr, 7); + COMMENT("Frame header, buffer 1, YacQi quantizer index"); + + /* TODO: delta quantization index */ + VP8PutLit(buffer, 0, 1); + COMMENT("Frame header, buffer 1, YdcDelta flag"); + VP8PutLit(buffer, 0, 1); + COMMENT("Frame header, buffer 1, Y2dcDelta flag"); + VP8PutLit(buffer, 0, 1); + COMMENT("Frame header, buffer 1, Y2acDelta flag"); + VP8PutLit(buffer, 0, 1); + COMMENT("Frame header, buffer 1, UVdcDelta flag"); + VP8PutLit(buffer, 0, 1); + COMMENT("Frame header, buffer 1, UVacDelta flag"); + + /* Update grf and arf buffers and sing bias, see decodframe.c 863. + * TODO swaping arg->grf and grf->arf in the same time is not working + * because of bug in the libvpx? */ + if (!cur_pic->i_frame) { + /* Input picture after reconstruction is set to new grf/arf */ + VP8PutLit(buffer, cur_pic->grf, 1); /* Grf refresh */ + COMMENT("Frame header, buffer 1, grf refresh"); + VP8PutLit(buffer, cur_pic->arf, 1); /* Arf refresh */ + COMMENT("Frame header, buffer 1, arf refresh"); + + if (!cur_pic->grf) { + if (refPicList[0].grf) { + VP8PutLit(buffer, 1, 2); /* Ipf -> grf */ + COMMENT("Frame header, buffer 1, ipf -> grf"); + } else if (refPicList[2].grf) { + VP8PutLit(buffer, 2, 2); /* Arf -> grf */ + COMMENT("Frame header, buffer 1, arf -> grf"); + } else { + VP8PutLit(buffer, 0, 2); /* Not updated */ + COMMENT("Frame header, buffer 1, no update"); + } + } + + if (!cur_pic->arf) { + if (refPicList[0].arf) { + VP8PutLit(buffer, 1, 2); /* Ipf -> arf */ + COMMENT("Frame header, buffer 1, ipf -> arf"); + } else if (refPicList[1].arf) { + VP8PutLit(buffer, 2, 2); /* Grf -> arf */ + COMMENT("Frame header, buffer 1, grf -> arf"); + } else { + VP8PutLit(buffer, 0, 2); /* Not updated */ + COMMENT("Frame header, buffer 1, no update"); + } + } + + /* Sing bias. TODO adaptive sing bias. */ + VP8PutLit(buffer, sps->singBias[1], 1); /* Grf */ + COMMENT("Frame header, buffer 1, grf sign bias"); + VP8PutLit(buffer, sps->singBias[2], 1); /* Arf */ + COMMENT("Frame header, buffer 1, arf sign bias"); + } + + + /* RefreshEntropyProbs, if 0 -> put default proabilities. If 1 + * use previous frame probabilities */ + VP8PutLit(buffer, sps->refreshEntropy, 1); + COMMENT("Frame header, buffer 1, Refresh entropy probs flag"); + + /* RefreshLastFrame flag. Note that key frame always updates ipf */ + if (!cur_pic->i_frame) { + VP8PutLit(buffer, cur_pic->ipf, 1); + COMMENT("Frame header, buffer 1, ipf refresh last frame flag"); + } + + /* Coeff probabilities, TODO: real updates */ + CoeffProb(buffer, entropy->coeffProb, entropy->oldCoeffProb); + + /* mb_no_coeff_skip . This flag indicates at the frame level if + * skipping of macroblocks with no non-zero coefficients is enabled. + * If it is set to 0 then prob_skip_false is not read and + * mb_skip_coeff is forced to 0 for all macroblocks (see Sections 11.1 + * and 12.1). TODO */ + VP8PutLit(buffer, 1, 1); + COMMENT("Frame header, buffer 1, mb no coeff skip"); + /* Probability used for decoding noCoeff flag, depens above flag TODO*/ + VP8PutLit(buffer, entropy->skipFalseProb, 8); + COMMENT("Frame header, buffer 1, skip false prob"); + + if (cur_pic->i_frame) return; + + /* The rest are inter frame only */ + + /* Macroblock is intra predicted probability */ + VP8PutLit(buffer, entropy->intraProb, 8); + COMMENT("Frame header, buffer 1, intra prob"); + + /* Inter is predicted from immediately previous frame probability */ + VP8PutLit(buffer, entropy->lastProb, 8); + COMMENT("Frame header, buffer 1, last prob"); + + /* Inter is predicted from golden frame probability */ + VP8PutLit(buffer, entropy->gfProb, 8); + COMMENT("Frame header, buffer 1, gf prob"); + + /* Intra mode probability updates not supported yet TODO */ + VP8PutLit(buffer, 0, 1); + COMMENT("Frame header, buffer 1, intra mode prob update"); + + /* Intra chroma probability updates not supported yet TODO */ + VP8PutLit(buffer, 0, 1); + COMMENT("Frame header, buffer 1, intra chroma prob update"); + + /* Motion vector probability update not supported yet TOTO real updates */ + MvProb(buffer, entropy->mvProb, entropy->oldMvProb); +} + +/*------------------------------------------------------------------------------ + FrameTag +------------------------------------------------------------------------------*/ +void VP8FrameTag(vp8Instance_s* container) { + picBuffer* picBuffer = &container->picBuffer; + refPic* cur_pic = picBuffer->cur_pic; + sps* sps = &container->sps; /* Sequence container */ + vp8buffer* buffer = &container->buffer[0]; /* Frame tag buffer */ + int32_t tmp; + + /* Frame tag contains (lsb first): + * 1. A 1-bit frame type (0 for key frames, 1 for inter frames) + * 2. A 3-bit version number (0 - 3 are defined as 4 different profiles + * 3. A 1-bit showFrame flag (1 when current frame is display) + * 4. A 19-bit size of the first data partition in bytes + * Note that frame tag is written to the stream in little endian mode */ + + tmp = ((container->buffer[1].byteCnt) << 5) | + ((cur_pic->show ? 1 : 0) << 4) | + (container->sps.profile << 1) | + (cur_pic->i_frame ? 0 : 1); + + /* Note that frame tag is written _really_ literal to buffer, don't use + * VP8PutLit() use VP8PutBit() instead */ + + VP8PutByte(buffer, tmp & 0xff); + COMMENT("Frame tag, buffer 0, The first byte"); + + VP8PutByte(buffer, (tmp >> 8) & 0xff); + COMMENT("Frame tag, buffer 0, The second byte"); + + VP8PutByte(buffer, (tmp >> 16) & 0xff); + COMMENT("Frame tag, buffer 0, The third byte"); + + if (!cur_pic->i_frame) return; + + /* For key frames this is followed by a further 7 bytes of uncompressed + * data as follows */ + VP8PutByte(buffer, 0x9d); + COMMENT("Frame tag, buffer 0, next byte"); + VP8PutByte(buffer, 0x01); + COMMENT("Frame tag, buffer 0, next byte"); + VP8PutByte(buffer, 0x2a); + COMMENT("Frame tag, buffer 0, next byte"); + + tmp = sps->picWidthInPixel | (sps->horizontalScaling << 14); + VP8PutByte(buffer, tmp & 0xff); + COMMENT("Frame tag, buffer 0, next byte"); + VP8PutByte(buffer, tmp >> 8); + COMMENT("Frame tag, buffer 0, next byte"); + + tmp = sps->picHeightInPixel | (sps->verticalScaling << 14); + VP8PutByte(buffer, tmp & 0xff); + COMMENT("Frame tag, buffer 0, next byte"); + VP8PutByte(buffer, tmp >> 8); + COMMENT("Frame tag, buffer 0, next byte"); +} + +/*------------------------------------------------------------------------------ + Segmentation +------------------------------------------------------------------------------*/ +void Segmentation(vp8buffer* buffer, sps* sps, ppss* ppss, entropy* entropy, + mbs* mbs) { + pps* pps = ppss->pps; + sgm* sgm = &ppss->pps->sgm; /* New segmentation data */ + int32_t i, tmp; + bool dataModified = false; + + /* Do we need to updata segmentation data */ + if (memcmp(ppss->qpSgm, pps->qpSgm, sizeof(ppss->qpSgm))) + dataModified = true; + + if (memcmp(ppss->levelSgm, pps->levelSgm, sizeof(ppss->levelSgm))) + dataModified = true; + + /* Update segmentation map only if there are no previous map or + * previous map differs or previous frame did not use segmentation at + * all. Note also that API set mapModified=true if user changes + * segmentation map */ + if (!ppss->prevPps) { + sgm->mapModified = true; + } + + COMMENT("Frame header, buffer 1, segmentation map modified"); + VP8PutLit(buffer, sgm->mapModified, 1); + COMMENT("Frame header, buffer 1, segmentation data modified"); + VP8PutLit(buffer, dataModified, 1); + + if (dataModified) { + COMMENT("Frame header, buffer 1, segmentation data abs"); + /* ABS=1 vs. Deltas=0 */ + VP8PutLit(buffer, 1, 1); + + for (i = 0; i < SGM_CNT; i++) { + tmp = pps->qpSgm[i]; + VP8PutLit(buffer, 1, 1); + VP8PutLit(buffer, ABS(tmp), 7); + VP8PutLit(buffer, tmp < 0, 1); + } + + for (i = 0; i < SGM_CNT; i++) { + tmp = pps->levelSgm[i]; + VP8PutLit(buffer, 1, 1); + VP8PutLit(buffer, ABS(tmp), 6); + VP8PutLit(buffer, tmp < 0, 1); + } + } + + /* Segmentation map probabilities */ + if (sgm->mapModified) { + int32_t sum1 = sgm->idCnt[0] + sgm->idCnt[1]; + int32_t sum2 = sgm->idCnt[2] + sgm->idCnt[3]; + + ASSERT(sum1); + ASSERT(sum2); + + tmp = 255 * sum1 / (sum1 + sum2); + entropy->segmentProb[0] = CLIP3(tmp, 1, 255); + + tmp = sum1 ? 255 * sgm->idCnt[0] / sum1 : 255; + entropy->segmentProb[1] = CLIP3(tmp, 1, 255); + + tmp = sum2 ? 255 * sgm->idCnt[2] / sum2 : 255; + entropy->segmentProb[2] = CLIP3(tmp, 1, 255); + + for (i = 0; i < 3; i++) { + if (sgm->idCnt[i] != 0) { + COMMENT("Frame header, buffer 1, segment prob"); + VP8PutLit(buffer, 1, 1); + VP8PutLit(buffer, entropy->segmentProb[i], 8); + } else { + COMMENT("Frame header, buffer 1, no segment prob"); + VP8PutLit(buffer, 0, 1); + } + } + } + + /* This point new segmentation data is written to the stream, save new + * values because they are reference values of next frame */ + memcpy(ppss->qpSgm, pps->qpSgm, sizeof(ppss->qpSgm)); + memcpy(ppss->levelSgm, pps->levelSgm, sizeof(ppss->levelSgm)); +} + +/*------------------------------------------------------------------------------ + FilterLevelDelta +------------------------------------------------------------------------------*/ +void FilterLevelDelta(vp8buffer* buffer, sps* sps) { + int32_t i, tmp; + int32_t modeUpdate[4]; + int32_t refUpdate[4]; + bool update = false; + + /* Find out what delta values are changed */ + for (i = 0; i < 4; i++) { + modeUpdate[i] = sps->modeDelta[i] != sps->oldModeDelta[i]; + refUpdate[i] = sps->refDelta[i] != sps->oldRefDelta[i]; + if (modeUpdate[i] || refUpdate[i]) + update = true; + } + + /* With error resilient mode update the level values for every frame. */ + if (!sps->refreshEntropy) + update = true; + + /* Do the deltas need to be updated */ + VP8PutLit(buffer, update, 1); + if (!update) return; + + /* Reference frame mode based deltas */ + for (i = 0; i < 4; i++) { + VP8PutLit(buffer, refUpdate[i], 1); + if (refUpdate[i]) { + tmp = sps->refDelta[i]; + VP8PutLit(buffer, ABS(tmp), 6); /* Delta */ + VP8PutLit(buffer, tmp < 0, 1); /* Sign */ + } + } + + /* Macroblock mode based deltas */ + for (i = 0; i < 4; i++) { + VP8PutLit(buffer, modeUpdate[i], 1); + if (modeUpdate[i]) { + tmp = sps->modeDelta[i]; + VP8PutLit(buffer, ABS(tmp), 6); /* Delta */ + VP8PutLit(buffer, tmp < 0, 1); /* Sign */ + } + } + + /* Store the new values as reference for next frame */ + memcpy(sps->oldRefDelta, sps->refDelta, sizeof(sps->refDelta)); + memcpy(sps->oldModeDelta, sps->modeDelta, sizeof(sps->modeDelta)); +} diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8header.h b/libv4l-rockchip/libvpu/vp8_enc/vp8header.h new file mode 100644 index 0000000..6ffb96c --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8header.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef VP8HEADERS_H +#define VP8HEADERS_H + +#include "vp8instance.h" + +void VP8FrameHeader(vp8Instance_s*); +void VP8FrameTag(vp8Instance_s*); +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8init.c b/libv4l-rockchip/libvpu/vp8_enc/vp8init.c new file mode 100644 index 0000000..f96a34e --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8init.c @@ -0,0 +1,304 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include <memory.h> +#include <malloc.h> +#include "vp8init.h" +#include "vp8macroblocktools.h" +#include "enccommon.h" + +#define VP8ENC_MIN_ENC_WIDTH 132 /* 144 - 12 pixels overfill */ +#define VP8ENC_MAX_ENC_WIDTH 4080 +#define VP8ENC_MIN_ENC_HEIGHT 96 +#define VP8ENC_MAX_ENC_HEIGHT 4080 + +#define VP8ENC_MAX_MBS_PER_PIC 65025 /* 4080x4080 */ + +static void SetParameter(vp8Instance_s* inst, const VP8EncConfig* pEncCfg); + +static int32_t SetPictureBuffer(vp8Instance_s* inst); + +/*------------------------------------------------------------------------------ + + VP8CheckCfg + + Function checks that the configuration is valid. + + Input pEncCfg Pointer to configuration structure. + + Return ENCHW_OK The configuration is valid. + ENCHW_NOK Some of the parameters in configuration are not valid. + +------------------------------------------------------------------------------*/ +bool_e VP8CheckCfg(const VP8EncConfig* pEncCfg) { + ASSERT(pEncCfg); + + /* Encoded image width limits, multiple of 4 */ + if (pEncCfg->width < VP8ENC_MIN_ENC_WIDTH || + pEncCfg->width > VP8ENC_MAX_ENC_WIDTH || (pEncCfg->width & 0x3) != 0) + return ENCHW_NOK; + + /* Encoded image height limits, multiple of 2 */ + if (pEncCfg->height < VP8ENC_MIN_ENC_HEIGHT || + pEncCfg->height > VP8ENC_MAX_ENC_HEIGHT || (pEncCfg->height & 0x1) != 0) + return ENCHW_NOK; + + /* total macroblocks per picture limit */ + if (((pEncCfg->height + 15) / 16) * ((pEncCfg->width + 15) / 16) > + VP8ENC_MAX_MBS_PER_PIC) { + return ENCHW_NOK; + } + + /* Check frame rate */ + if (pEncCfg->frameRateNum < 1 || pEncCfg->frameRateNum > ((1 << 20) - 1)) + return ENCHW_NOK; + + if (pEncCfg->frameRateDenom < 1) { + return ENCHW_NOK; + } + + /* special allowal of 1000/1001, 0.99 fps by customer request */ + if (pEncCfg->frameRateDenom > pEncCfg->frameRateNum && + !(pEncCfg->frameRateDenom == 1001 && pEncCfg->frameRateNum == 1000)) { + return ENCHW_NOK; + } + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + VP8Init + + Function initializes the Encoder and creates new encoder instance. + + Input pEncCfg Encoder configuration. + instAddr Pointer to instance will be stored in this address + + Return VP8ENC_OK + VP8ENC_MEMORY_ERROR + VP8ENC_EWL_ERROR + VP8ENC_EWL_MEMORY_ERROR + VP8ENC_INVALID_ARGUMENT + +------------------------------------------------------------------------------*/ +VP8EncRet VP8Init(const VP8EncConfig* pEncCfg, vp8Instance_s** instAddr) { + vp8Instance_s* inst = NULL; + VP8EncRet ret = VP8ENC_OK; + int32_t i; + + ASSERT(pEncCfg); + ASSERT(instAddr); + + *instAddr = NULL; + + /* Encoder instance */ + inst = (vp8Instance_s*)malloc(sizeof(vp8Instance_s)); + + if (inst == NULL) { + ret = VP8ENC_MEMORY_ERROR; + goto err; + } + + memset(inst, 0, sizeof(vp8Instance_s)); + + /* Set parameters depending on user config */ + SetParameter(inst, pEncCfg); + InitQuantTables(inst); + + if (SetPictureBuffer(inst) != ENCHW_OK) { + ret = VP8ENC_INVALID_ARGUMENT; + goto err; + } + + VP8InitRc(&inst->rateControl, 1); + + /* Initialize ASIC */ + (void) VP8_EncAsicControllerInit(&inst->asic); + + /* Allocate internal SW/HW shared memories */ + if (VP8_EncAsicMemAlloc_V2(&inst->asic, + pEncCfg->width, + pEncCfg->height, + ASIC_VP8, inst->numRefBuffsLum, + inst->numRefBuffsChr) != ENCHW_OK) { + ret = VP8ENC_EWL_MEMORY_ERROR; + goto err; + } + + /* Assign allocated HW frame buffers into picture buffer */ + inst->picBuffer.size = inst->numRefBuffsLum; + for (i = 0; i < inst->numRefBuffsLum; i++) + inst->picBuffer.refPic[i].picture.lum = i; + for (i = 0; i < inst->numRefBuffsChr; i++) + inst->picBuffer.refPic[i].picture.cb = i; + + *instAddr = inst; + + inst->asic.regs.intra16Favor = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.prevModeFavor = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.interFavor = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.skipPenalty = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.diffMvPenalty[0] = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.diffMvPenalty[1] = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.diffMvPenalty[2] = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.splitPenalty[0] = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.splitPenalty[1] = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.splitPenalty[2] = 0x3FF; /* No 8x4 MVs in VP8 */ + inst->asic.regs.splitPenalty[3] = ASIC_PENALTY_UNDEFINED; + inst->asic.regs.zeroMvFavorDiv2 = 0; /* No favor for VP8 */ + + /* Disable intra and ROI areas by default */ + inst->asic.regs.intraAreaTop = inst->asic.regs.intraAreaBottom = + inst->asic.regs.intraAreaLeft = inst->asic.regs.intraAreaRight = + inst->asic.regs.roi1Top = inst->asic.regs.roi1Bottom = + inst->asic.regs.roi1Left = inst->asic.regs.roi1Right = + inst->asic.regs.roi2Top = inst->asic.regs.roi2Bottom = + inst->asic.regs.roi2Left = inst->asic.regs.roi2Right = 255; + + return ret; + + err: + free(inst); + return ret; +} + +/*------------------------------------------------------------------------------ + + VP8Shutdown + + Function frees the encoder instance. + + Input vp8Instance_s * Pointer to the encoder instance to be freed. + After this the pointer is no longer valid. + +------------------------------------------------------------------------------*/ +void VP8Shutdown(vp8Instance_s* data) { + ASSERT(data); + + VP8_EncAsicMemFree_V2(&data->asic); + + PictureBufferFree(&data->picBuffer); + + PicParameterSetFree(&data->ppss); + + free(data); +} + +/*------------------------------------------------------------------------------ + + SetParameter + + Set all parameters in instance to valid values depending on user config. + +------------------------------------------------------------------------------*/ +void SetParameter(vp8Instance_s* inst, const VP8EncConfig* pEncCfg) { + int32_t width, height; + sps* sps = &inst->sps; + + ASSERT(inst); + + /* Internal images, next macroblock boundary */ + width = 16 * ((pEncCfg->width + 15) / 16); + height = 16 * ((pEncCfg->height + 15) / 16); + + /* Luma ref buffers can be read and written at the same time, + * but chroma buffers must be one for reading and one for writing */ + inst->numRefBuffsLum = pEncCfg->refFrameAmount; + inst->numRefBuffsChr = inst->numRefBuffsLum + 1; + + /* Macroblock */ + inst->mbPerFrame = width / 16 * height / 16; + inst->mbPerRow = width / 16; + inst->mbPerCol = height / 16; + + /* Sequence parameter set */ + sps->picWidthInPixel = pEncCfg->width; + sps->picHeightInPixel = pEncCfg->height; + sps->picWidthInMbs = width / 16; + sps->picHeightInMbs = height / 16; + + sps->horizontalScaling = 0; /* TODO, not supported yet */ + sps->verticalScaling = 0; /* TODO, not supported yet */ + sps->colorType = 0; /* TODO, not supported yet */ + sps->clampType = 0; /* TODO, not supported yet */ + sps->dctPartitions = 0; /* Dct data partitions 0=1, 1=2, 2=4, 3=8 */ + sps->partitionCnt = 2 + (1 << sps->dctPartitions); + sps->profile = 1; /* Currently ASIC only supports bilinear ipol */ + sps->filterType = 0; + sps->filterLevel = 0; + sps->filterSharpness = 0; + sps->autoFilterLevel = 1; /* Automatic filter values by default. */ + sps->autoFilterSharpness = 1; + sps->quarterPixelMv = 1; /* 1=adaptive by default */ + sps->splitMv = 1; /* 1=adaptive by default */ + sps->refreshEntropy = 1; /* 0=default probs, 1=prev frame probs */ + memset(sps->singBias, 0, sizeof(sps->singBias)); + + sps->filterDeltaEnable = true; + memset(sps->refDelta, 0, sizeof(sps->refDelta)); + memset(sps->modeDelta, 0, sizeof(sps->modeDelta)); + + /* Rate control */ + inst->rateControl.virtualBuffer.bitRate = 1000000; + inst->rateControl.qpHdr = -1; + inst->rateControl.picRc = ENCHW_YES; + inst->rateControl.picSkip = ENCHW_NO; + inst->rateControl.qpMin = 0; + inst->rateControl.qpMax = 127; + inst->rateControl.gopLen = 150; + inst->rateControl.mbPerPic = inst->mbPerFrame; + inst->rateControl.outRateDenom = pEncCfg->frameRateDenom; + inst->rateControl.outRateNum = pEncCfg->frameRateNum; +} + +int32_t SetPictureBuffer(vp8Instance_s* inst) { + picBuffer* picBuffer = &inst->picBuffer; + sps* sps = &inst->sps; + int32_t width, height; + + width = sps->picWidthInMbs * 16; + height = sps->picHeightInMbs * 16; + PictureBufferAlloc(picBuffer, width, height); + + width = sps->picWidthInMbs; + height = sps->picHeightInMbs; + if (PicParameterSetAlloc(&inst->ppss) != ENCHW_OK) + return ENCHW_NOK; + + inst->ppss.pps = inst->ppss.store; + inst->ppss.pps->segmentEnabled = 0; /* Segmentation disabled by default. */ + inst->ppss.pps->sgm.mapModified = 0; + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + + Round the width to the next multiple of 8 or 16 depending on YUV type. + +------------------------------------------------------------------------------*/ +int32_t VP8GetAllowedWidth(int32_t width, VP8EncPictureType inputType) { + if (inputType == VP8ENC_YUV420_PLANAR) { + /* Width must be multiple of 16 to make + * chrominance row 64-bit aligned */ + return ((width + 15) / 16) * 16; + } else { /* VP8ENC_YUV420_SEMIPLANAR */ + /* VP8ENC_YUV422_INTERLEAVED_YUYV */ + /* VP8ENC_YUV422_INTERLEAVED_UYVY */ + return ((width + 7) / 8) * 8; + } +} diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8init.h b/libv4l-rockchip/libvpu/vp8_enc/vp8init.h new file mode 100644 index 0000000..e871bb0 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8init.h @@ -0,0 +1,27 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef __VP8_INIT_H__ +#define __VP8_INIT_H__ + +#include "vp8encapi.h" +#include "vp8instance.h" + +bool_e VP8CheckCfg(const VP8EncConfig* pEncCfg); +int32_t VP8GetAllowedWidth(int32_t width, VP8EncPictureType inputType); +VP8EncRet VP8Init(const VP8EncConfig* pEncCfg, vp8Instance_s** instAddr); +void VP8Shutdown(vp8Instance_s* data); +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8instance.h b/libv4l-rockchip/libvpu/vp8_enc/vp8instance.h new file mode 100644 index 0000000..ec9d05e --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8instance.h @@ -0,0 +1,77 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef __VP8_INSTANCE_H__ +#define __VP8_INSTANCE_H__ + +#include "encasiccontroller.h" +#include "enccommon.h" +#include "vp8seqparameterset.h" +#include "vp8picparameterset.h" +#include "vp8picturebuffer.h" +#include "vp8putbits.h" +#include "vp8ratecontrol.h" +#include "vp8quanttable.h" + +enum VP8EncStatus { + VP8ENCSTAT_INIT = 0xA1, + VP8ENCSTAT_KEYFRAME, + VP8ENCSTAT_START_FRAME, + VP8ENCSTAT_ERROR +}; + +typedef struct { + int32_t quant[2]; + int32_t zbin[2]; + int32_t round[2]; + int32_t dequant[2]; +} qp; + +typedef struct { + /* Approximate bit cost of mode. IOW bits used when selected mode is + * boolean encoded using appropriate tree and probabilities. Note that + * this value is scale up with SCALE (=256) */ + int32_t intra16ModeBitCost[4 + 1]; + int32_t intra4ModeBitCost[14 + 1]; +} mbs; + +typedef struct +{ + uint32_t encStatus; + uint32_t mbPerFrame; + uint32_t mbPerRow; + uint32_t mbPerCol; + uint32_t frameCnt; + uint32_t testId; + uint32_t numRefBuffsLum; + uint32_t numRefBuffsChr; + uint32_t prevFrameLost; + vp8RateControl_s rateControl; + picBuffer picBuffer; /* Reference picture container */ + sps sps; /* Sequence parameter set */ + ppss ppss; /* Picture parameter set */ + vp8buffer buffer[4]; /* Stream buffer per partition */ + qp qpY1[QINDEX_RANGE]; /* Quant table for 1'st order luminance */ + qp qpY2[QINDEX_RANGE]; /* Quant table for 2'nd order luminance */ + qp qpCh[QINDEX_RANGE]; /* Quant table for chrominance */ + mbs mbs; + asicData_s asic; + uint32_t* pOutBuf; /* User given stream output buffer */ + const void* inst; /* Pointer to this instance for checking */ + entropy entropy[1]; +} vp8Instance_s; + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.c b/libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.c new file mode 100644 index 0000000..8b8b54b --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.c @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include "vp8macroblocktools.h" +#include "vp8quanttable.h" + +void InitQuantTables(vp8Instance_s* mbs) { + int32_t i, j, tmp; + qp* qp; + + for (i = 0; i < QINDEX_RANGE; i++) { + /* Quant table for 1'st order luminance */ + qp = &mbs->qpY1[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = DcQLookup[i]; + } else { + tmp = AcQLookup[i]; + } + qp->quant[j] = MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((QZbinFactors[i] * tmp) + 64) >> 7; + qp->round[j] = (QRoundingFactors[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + + /* Quant table for 2'st order luminance */ + qp = &mbs->qpY2[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = DcQLookup[i] * 2; + } else { + tmp = AcQLookup[i]; + tmp = (tmp * 155) / 100; + if (tmp < 8) tmp = 8; + } + qp->quant[j] = MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((QZbinFactors[i] * tmp) + 64) >> 7; + qp->round[j] = (QRoundingFactors[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + + /* Quant table for chrominance */ + qp = &mbs->qpCh[i]; + for (j = 0; j < 2; j++) { + if (j == 0) { + tmp = DcQLookup[i]; + if (tmp > 132) tmp = 132; + } else { + tmp = AcQLookup[i]; + } + qp->quant[j] = MIN((1 << 16) / tmp, 0x3FFF); + qp->zbin[j] = ((QZbinFactors[i] * tmp) + 64) >> 7; + qp->round[j] = (QRoundingFactors[i] * tmp) >> 7; + qp->dequant[j] = tmp; + } + } +} + + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.h b/libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.h new file mode 100644 index 0000000..8c126dd --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8macroblocktools.h @@ -0,0 +1,54 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _VP8MACROBLOCK_TOOLS_H_ +#define _VP8MACROBLOCK_TOOLS_H_ + +#include "vp8instance.h" + +typedef enum { + /* Intra luma 16x16 or intra chroma 8x8 prediction modes */ + DC_PRED, + V_PRED, + H_PRED, + TM_PRED, + + /* Common name of intra predicted mb where partition size is 4x4 */ + B_PRED, + + /* Intra 4x4 prediction modes */ + B_DC_PRED, + B_TM_PRED, + B_VE_PRED, + B_HE_PRED, + B_LD_PRED, + B_RD_PRED, + B_VR_PRED, + B_VL_PRED, + B_HD_PRED, + B_HU_PRED, + + /* Inter prediction (partitioning) types */ + P_16x16, /* [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] */ + P_16x8, /* [0,1,2,3,4,5,6,7,8][9,10,11,12,13,14,15] */ + P_8x16, /* [0,1,4,5,8,9,12,13][2,3,6,7,10,11,14,15] */ + P_8x8, /* [0,1,4,5][2,3,6,7][8,9,12,13][10,11,14,15] */ + P_4x4 /* Every subblock gets its own vector */ +} type; + +void InitQuantTables(vp8Instance_s*); + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.c b/libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.c new file mode 100644 index 0000000..653bb98 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.c @@ -0,0 +1,38 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include "vp8picparameterset.h" + +#include <malloc.h> +#include <memory.h> + +#include "enccommon.h" +#include "libvpu/rk_vepu_debug.h" + +int32_t PicParameterSetAlloc(ppss* ppss) { + ppss->size = 1; + ppss->store = (pps*) malloc(ppss->size * sizeof(pps)); + if (ppss->store == NULL) { + VPU_PLG_ERR("Fail to malloc ppss store.\n"); + return ENCHW_NOK; + } + return ENCHW_OK; +} + +void PicParameterSetFree(ppss* ppss) { + free(ppss->store); + ppss->store = NULL; +} diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.h b/libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.h new file mode 100644 index 0000000..8b2047f --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8picparameterset.h @@ -0,0 +1,54 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef VP8PIC_PARAMETER_SET_H +#define VP8PIC_PARAMETER_SET_H + +#include <stdbool.h> +#include <stdint.h> + +#define SGM_CNT 4 + +typedef struct sgm { + bool mapModified; /* Segmentation map has been modified */ + int32_t idCnt[SGM_CNT]; /* Id counts because of probability */ + /* Segment ID map is stored in ASIC SW/HW mem regs->segmentMap */ +} sgm; + +typedef struct { + struct sgm sgm; /* Segmentation data */ + int32_t qp; /* Final qp value of current macroblock */ + bool segmentEnabled; /* Segmentation enabled */ + int32_t qpSgm[SGM_CNT]; /* Qp if segments enabled (encoder set) */ + int32_t levelSgm[SGM_CNT]; /* Level if segments enabled (encoder set) */ +} pps; + +typedef struct { + pps* store; /* Picture parameter set tables */ + int32_t size; /* Size of above storage table */ + pps* pps; /* Active picture parameter set */ + pps* prevPps; /* Previous picture parameter set */ + int32_t qpSgm[SGM_CNT]; /* Current qp and level of segmentation... */ + int32_t levelSgm[SGM_CNT]; /* ...which are written to the stream */ +} ppss; + +/*------------------------------------------------------------------------------ + 4. Function prototypes +------------------------------------------------------------------------------*/ +int32_t PicParameterSetAlloc(ppss* ppss); +void PicParameterSetFree(ppss* ppss); + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.c b/libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.c new file mode 100644 index 0000000..82cb146 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.c @@ -0,0 +1,277 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include <memory.h> +#include <malloc.h> +#include "enccommon.h" +#include "vp8picturebuffer.h" + +static void Alloc(refPic* refPic, int32_t width, int32_t height); +static void RefPicListInitialization(picBuffer* ref); +static void ResetRefPic(refPic* refPic); + +void PictureBufferAlloc(picBuffer* picBuffer, int32_t width, int32_t height) { + int32_t i; + + /* Be sure that everything is initialized if something goes wrong */ + memset(picBuffer->refPic, 0, sizeof(picBuffer->refPic)); + memset(picBuffer->refPicList, 0, sizeof(picBuffer->refPicList)); + + /* Reference frame base (lum,cb) and macroblock stuff */ + for (i = 0; i < BUFFER_SIZE + 1; i++) { + Alloc(&picBuffer->refPic[i], width, height); + /* Back reference pointer (pointer to itself) */ + picBuffer->refPic[i].refPic = &picBuffer->refPic[i]; + } + picBuffer->cur_pic = &picBuffer->refPic[0]; +} + +void PictureBufferFree(picBuffer* picBuffer) { + memset(picBuffer->refPic, 0, sizeof(picBuffer->refPic)); +} + +void Alloc(refPic* refPic, int32_t width, int32_t height) { + refPic->picture.lumWidth = width; + refPic->picture.lumHeight = height; + refPic->picture.chWidth = width / 2; + refPic->picture.chHeight = height / 2; + refPic->picture.lum = 0; + refPic->picture.cb = 0; +} + +void InitializePictureBuffer(picBuffer* picBuffer) { + int32_t i; + + /* I frame (key frame) resets reference pictures */ + if (picBuffer->cur_pic->i_frame) { + picBuffer->cur_pic->p_frame = false; + picBuffer->cur_pic->ipf = true; + picBuffer->cur_pic->grf = true; + picBuffer->cur_pic->arf = true; + for (i = 0; i < BUFFER_SIZE + 1; i++) { + if (&picBuffer->refPic[i] != picBuffer->cur_pic) { + ResetRefPic(&picBuffer->refPic[i]); + } + } + } + + /* Initialize reference picture list, note that API (user) can change + * reference picture list */ + for (i = 0; i < BUFFER_SIZE; i++) { + ResetRefPic(&picBuffer->refPicList[i]); + } + RefPicListInitialization(picBuffer); +} + +void UpdatePictureBuffer(picBuffer* picBuffer) { + refPic * cur_pic,*tmp,*refPic,*refPicList; + int32_t i, j; + + refPicList = picBuffer->refPicList; /* Reference frame list */ + refPic = picBuffer->refPic; /* Reference frame store */ + cur_pic = picBuffer->cur_pic; /* Reconstructed picture */ + picBuffer->last_pic = picBuffer->cur_pic; + + /* Reset old marks from reference frame store if user wants to change + * current ips/grf/arf frames. */ + + /* Input picture marking */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (&refPic[i] == cur_pic) continue; + if (cur_pic->ipf) refPic[i].ipf = false; + if (cur_pic->grf) refPic[i].grf = false; + if (cur_pic->arf) refPic[i].arf = false; + } + + /* Reference picture marking */ + for (i = 0; i < picBuffer->size; i++) { + for (j = 0; j < picBuffer->size + 1; j++) { + if (refPicList[i].grf) refPic[j].grf = false; + if (refPicList[i].arf) refPic[j].arf = false; + } + } + + /* Reference picture status is changed */ + for (i = 0; i < picBuffer->size; i++) { + if (refPicList[i].grf) refPicList[i].refPic->grf = true; + if (refPicList[i].arf) refPicList[i].refPic->arf = true; + } + + /* Find new picture not used as reference and set it to new cur_pic */ + for (i = 0; i < picBuffer->size + 1; i++) { + tmp = &refPic[i]; + if (!tmp->ipf && !tmp->arf && !tmp->grf) { + picBuffer->cur_pic = &refPic[i]; + break; + } + } +} + +void RefPicListInitialization(picBuffer* picBuffer) { + refPic * cur_pic,*refPic,*refPicList; + int32_t i, j = 0; + + refPicList = picBuffer->refPicList; /* Reference frame list */ + refPic = picBuffer->refPic; /* Reference frame store */ + cur_pic = picBuffer->cur_pic; /* Reconstructed picture */ + + /* The first in the list is immediately previous picture. Note that + * cur_pic (the picture under reconstruction) is skipped */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (refPic[i].ipf && (&refPic[i] != cur_pic)) { + refPicList[j++] = refPic[i]; + break; + } + } + + /* The second in the list is golden frame */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (refPic[i].grf && (&refPic[i] != cur_pic)) { + refPicList[j++] = refPic[i]; + break; + } + } + + /* The third in the list is alternative reference frame */ + for (i = 0; i < picBuffer->size + 1; i++) { + if (refPic[i].arf && (&refPic[i] != cur_pic)) { + refPicList[j] = refPic[i]; + break; + } + } + + /* Reset the ipf/grf/arf flags */ + for (i = 0; i < picBuffer->size; i++) { + refPicList[i].ipf = false; + refPicList[i].grf = false; + refPicList[i].arf = false; + } +} + +void ResetRefPic(refPic* refPic) { + refPic->poc = -1; + refPic->i_frame = false; + refPic->p_frame = false; + refPic->show = false; + refPic->ipf = false; + refPic->arf = false; + refPic->grf = false; + refPic->search = false; +} + +/*------------------------------------------------------------------------------ + PictureBufferSetRef + + Set the ASIC reference and reconstructed frame buffers based + on the user preference and picture buffer. +------------------------------------------------------------------------------*/ +void PictureBufferSetRef(picBuffer* picBuffer, asicData_s* asic) { + int32_t i, refIdx = -1, refIdx2 = -1; + refPic* refPicList = picBuffer->refPicList; + int32_t noGrf = 0, noArf = 0; + + /* Amount of buffered frames limits grf/arf availability. */ + if (picBuffer->size < 2) {noGrf = 1; + picBuffer->cur_pic->grf = false; } + if (picBuffer->size < 3) {noArf = 1; + picBuffer->cur_pic->arf = false; } + + /* If current picture shall refresh grf/arf remove marks from ref list */ + for (i = 0; i < picBuffer->size; i++) { + if (picBuffer->cur_pic->grf || noGrf) + picBuffer->refPicList[i].grf = false; + if (picBuffer->cur_pic->arf || noArf) + picBuffer->refPicList[i].arf = false; + } + + /* ASIC can use one or two reference frame, use the first ones marked. */ + for (i = 0; i < BUFFER_SIZE; i++) { + if ((i < picBuffer->size) && refPicList[i].search) { + if (refIdx == -1) + refIdx = i; + else if (refIdx2 == -1) + refIdx2 = i; + else + refPicList[i].search = 0; + } else { + refPicList[i].search = 0; + } + } + + /* If no reference specified, use ipf */ + if (refIdx == -1) + refIdx = 0; + + asic->regs.mvRefIdx[0] = asic->regs.mvRefIdx[1] = refIdx; + + /* Set the reference buffer for ASIC, no reference for intra frames */ + if (picBuffer->cur_pic->p_frame) { + /* Mark the ref pic that is used */ + picBuffer->refPicList[refIdx].search = 1; + + /* Check that enough frame buffers is available. */ + ASSERT(refPicList[refIdx].picture.lum); + + asic->regs.internalImageLumBaseR[0] = refPicList[refIdx].picture.lum; + asic->regs.internalImageChrBaseR[0] = refPicList[refIdx].picture.cb; + asic->regs.internalImageLumBaseR[1] = refPicList[refIdx].picture.lum; + asic->regs.internalImageChrBaseR[1] = refPicList[refIdx].picture.cb; + + asic->regs.mvRefIdx[0] = asic->regs.mvRefIdx[1] = refIdx; + asic->regs.ref2Enable = 0; + + /* Enable second reference frame usage */ + if (refIdx2 != -1) { + asic->regs.internalImageLumBaseR[1] = refPicList[refIdx2].picture.lum; + asic->regs.internalImageChrBaseR[1] = refPicList[refIdx2].picture.cb; + asic->regs.mvRefIdx[1] = refIdx2; + asic->regs.ref2Enable = 1; + } + } + + /* Set the reconstructed frame buffer for ASIC. Luma can be written + * to same buffer but chroma read and write buffers must be different. */ + asic->regs.recWriteDisable = 0; + if (!picBuffer->cur_pic->picture.lum) { + refPic* cur_pic = picBuffer->cur_pic; + refPic* cand; + int32_t recIdx = -1; + + /* No free luma buffer so we must "steal" a luma buffer from + * some other ref pic that is no longer needed. */ + for (i = 0; i < picBuffer->size + 1; i++) { + cand = &picBuffer->refPic[i]; + if (cand == cur_pic) continue; + if (((cur_pic->ipf | cand->ipf) == cur_pic->ipf) && + ((cur_pic->grf | cand->grf) == cur_pic->grf) && + ((cur_pic->arf | cand->arf) == cur_pic->arf)) + recIdx = i; + } + + if (recIdx >= 0) { + /* recIdx is overwritten or unused so steal it */ + cur_pic->picture.lum = picBuffer->refPic[recIdx].picture.lum; + picBuffer->refPic[recIdx].picture.lum = 0; + } else { + /* No available buffer found, must be no refresh */ + ASSERT((cur_pic->ipf | cur_pic->grf | cur_pic->arf) == 0); + asic->regs.recWriteDisable = 1; + } + } + asic->regs.internalImageLumBaseW = picBuffer->cur_pic->picture.lum; + asic->regs.internalImageChrBaseW = picBuffer->cur_pic->picture.cb; +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.h b/libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.h new file mode 100644 index 0000000..043006b --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8picturebuffer.h @@ -0,0 +1,70 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _VP8PICTURE_BUFFER_H_ +#define _VP8PICTURE_BUFFER_H_ + +#include <stdbool.h> +#include <stdint.h> + +#include "vp8entropytools.h" +#include "encasiccontroller.h" + +#define BUFFER_SIZE 3 + +typedef struct { + int32_t lumWidth; /* Width of *lum */ + int32_t lumHeight; /* Height of *lum */ + int32_t chWidth; /* Width of *cb and *cr */ + int32_t chHeight; /* Height of *cb and *cr */ + uint32_t lum; + uint32_t cb; +} picture; + +typedef struct refPic { + picture picture; /* Image data */ + entropy* entropy; /* Entropy store of picture */ + int32_t poc; /* Picture order count */ + + bool i_frame; /* I frame (key frame), only intra mb */ + bool p_frame; /* P frame, intra and inter mb */ + bool show; /* Frame is for display (showFrame flag) */ + bool ipf; /* Frame is immediately previous frame */ + bool arf; /* Frame is altref frame */ + bool grf; /* Frame is golden frame */ + bool search; /* Frame is used for motion estimation */ + struct refPic* refPic; /* Back reference pointer to itself */ +} refPic; + +typedef struct { + int32_t size; /* Amount of allocated reference pictures */ + picture input; /* Input picture */ + refPic refPic[BUFFER_SIZE + 1]; /* Reference picture store */ + refPic refPicList[BUFFER_SIZE]; /* Reference picture list */ + refPic* cur_pic; /* Pointer to picture under reconstruction */ + refPic* last_pic; /* Last picture */ +} picBuffer; + +/*------------------------------------------------------------------------------ + Function prototypes +------------------------------------------------------------------------------*/ +void PictureBufferAlloc(picBuffer* picBuffer, int32_t width, int32_t height); +void PictureBufferFree(picBuffer* picBuffer); +void InitializePictureBuffer(picBuffer* picBuffer); +void UpdatePictureBuffer(picBuffer* picBuffer); +void PictureBufferSetRef(picBuffer* picBuffer, asicData_s* asic); + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8putbits.c b/libv4l-rockchip/libvpu/vp8_enc/vp8putbits.c new file mode 100644 index 0000000..0773e5f --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8putbits.c @@ -0,0 +1,164 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#include "vp8putbits.h" + +#include <stdio.h> +#include "enccommon.h" + +/*------------------------------------------------------------------------------ + SetBuffer + Input buffer Pointer to the buffer structure. + data Pointer to data buffer. + size Size of data buffer. + Return ENCHW_OK Buffer status is OK. + ENCHW_NOK Buffer overflow. +------------------------------------------------------------------------------*/ +int32_t VP8SetBuffer(vp8buffer* buffer, uint8_t* data, int32_t size) { + if ((buffer == NULL) || (data == NULL) || (size < 1)) return ENCHW_NOK; + + buffer->data = data; + buffer->pData = data; /* First position of buffer */ + buffer->size = size; /* Buffer size in bytes */ + buffer->range = 255; + buffer->bottom = 0; /* PutBool bottom */ + buffer->bitsLeft = 24; + buffer->byteCnt = 0; + + return ENCHW_OK; +} + +/*------------------------------------------------------------------------------ + PutByte write byte literallyt to next place of buffer and advance data + pointer to next place + + Input buffer Pointer to the buffer stucture + value Byte +------------------------------------------------------------------------------*/ +void VP8PutByte(vp8buffer* buffer, int32_t byte) { + ASSERT((uint32_t)byte < 256); + ASSERT(buffer->data < buffer->pData + buffer->size); + *buffer->data++ = byte; + buffer->byteCnt++; +} + +/*------------------------------------------------------------------------------ + PutLit write "literal" bits to stream using PutBool() where probability + is 128. Note that real bits written to stream are not necessarily same + than literal value. Bit write order: MSB...LSB. +------------------------------------------------------------------------------*/ +void VP8PutLit(vp8buffer* buffer, int32_t value, int32_t number) { + ASSERT(number < 32 && number > 0); + ASSERT(((value & (-1 << number)) == 0)); + + while (number--) { + VP8PutBool(buffer, 128, (value >> number) & 0x1); + } +} + +/*------------------------------------------------------------------------------ + PutBool +------------------------------------------------------------------------------*/ +void VP8PutBool(vp8buffer* buffer, int32_t prob, int32_t boolValue) { + int32_t split = 1 + ((buffer->range - 1) * prob >> 8); + int32_t lengthBits = 0; + int32_t bits = 0; + + if (boolValue) { + buffer->bottom += split; + buffer->range -= split; + } else { + buffer->range = split; + } + + while (buffer->range < 128) { + /* Detect carry and add carry bit to already written + * buffer->data if needed */ + if (buffer->bottom < 0) { + uint8_t* data = buffer->data; + while (*--data == 255) { + *data = 0; + } + (*data)++; + } + buffer->range <<= 1; + buffer->bottom <<= 1; + + if (!--buffer->bitsLeft) { + lengthBits += 8; + bits <<= 8; + bits |= (buffer->bottom >> 24) & 0xff; + TRACE_BIT_STREAM(bits & 0xff, 8); + *buffer->data++ = (buffer->bottom >> 24) & 0xff; + buffer->byteCnt++; + buffer->bottom &= 0xffffff; /* Keep 3 bytes */ + buffer->bitsLeft = 8; + /* TODO use big enough buffer and check buffer status + * for example in the beginning of mb row */ + ASSERT(buffer->data < buffer->pData + buffer->size - 1); + } + } +} + +/*------------------------------------------------------------------------------ + PutTree +------------------------------------------------------------------------------*/ +void VP8PutTree(vp8buffer* buffer, tree const* tree, int32_t* prob) { + int32_t value = tree->value; + int32_t number = tree->number; + int32_t const* index = tree->index; + + while (number--) { + VP8PutBool(buffer, prob[*index++], (value >> number) & 1); + } +} + +/*------------------------------------------------------------------------------ + FlushBuffer put remaining buffer->bottom bits to the stream +------------------------------------------------------------------------------*/ +void VP8FlushBuffer(vp8buffer* buffer) { + int32_t bitsLeft = buffer->bitsLeft; + int32_t bottom = buffer->bottom; + + /* Detect (unlikely) carry and add carry bit to already written + * buffer->data if needed */ + if (bottom & (1 << (32 - bitsLeft))) { + uint8_t* data = buffer->data; + while (*--data == 255) { + *data = 0; + } + (*data)++; + } + + /* Move remaining bits to left until byte boundary */ + bottom <<= (bitsLeft & 0x7); + + /* Move remaining bytes to left until word boundary */ + bottom <<= (bitsLeft >> 3) * 8; + + /* Write valid (and possibly padded) bits to stream */ + *buffer->data++ = 0xff & (bottom >> 24); + *buffer->data++ = 0xff & (bottom >> 16); + *buffer->data++ = 0xff & (bottom >> 8); + *buffer->data++ = 0xff & bottom; + buffer->byteCnt += 4; + + TRACE_BIT_STREAM(bottom, 32); + + COMMENT("flush"); + +} + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8putbits.h b/libv4l-rockchip/libvpu/vp8_enc/vp8putbits.h new file mode 100644 index 0000000..4b4198d --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8putbits.h @@ -0,0 +1,46 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef VP8PUT_BITS_H +#define VP8PUT_BITS_H + +#include <stdint.h> + +typedef struct { + uint8_t* data; /* Pointer to next byte of data buffer */ + uint8_t* pData; /* Pointer to beginning of data buffer */ + int32_t size; /* Size of *data in bytes */ + int32_t byteCnt; /* Data buffer stream byte count */ + + int32_t range; /* Bool encoder range [128, 255] */ + int32_t bottom; /* Bool encoder left endpoint */ + int32_t bitsLeft; /* Bool encoder bits left before flush bottom */ +} vp8buffer; + +typedef struct { + int32_t value; /* Bits describe the bool tree */ + int32_t number; /* Number, valid bit count in above tree */ + int32_t index[9]; /* Probability table index */ +} tree; + +int32_t VP8SetBuffer(vp8buffer*, uint8_t*, int32_t); +void VP8PutByte(vp8buffer* buffer, int32_t byte); +void VP8PutLit(vp8buffer*, int32_t, int32_t); +void VP8PutBool(vp8buffer* buffer, int32_t prob, int32_t boolValue); +void VP8PutTree(vp8buffer* buffer, tree const* tree, int32_t* prob); +void VP8FlushBuffer(vp8buffer* buffer); + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8quanttable.h b/libv4l-rockchip/libvpu/vp8_enc/vp8quanttable.h new file mode 100644 index 0000000..e52c393 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8quanttable.h @@ -0,0 +1,92 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ +#ifndef _VP8QUANT_TABLE_H +#define _VP8QUANT_TABLE_H + +#include <stdint.h> + +#define QINDEX_RANGE 128 + +static const int DcQLookup[QINDEX_RANGE] = { + 4, 5, 6, 7, 8, 9, 10, 10, 11, 12, + 13, 14, 15, 16, 17, 17, 18, 19, 20, 20, + 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 91, 93, 95, 96, + 98, 100, 101, 102, 104, 106, 108, 110, 112, 114, + 116, 118, 122, 124, 126, 128, 130, 132, 134, 136, + 138, 140, 143, 145, 148, 151, 154, 157 +}; + +static const int AcQLookup[QINDEX_RANGE] = { + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 60, 62, 64, 66, 68, + 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, + 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 119, 122, 125, 128, 131, 134, + 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, + 167, 170, 173, 177, 181, 185, 189, 193, 197, 201, + 205, 209, 213, 217, 221, 225, 229, 234, 239, 245, + 249, 254, 259, 264, 269, 274, 279, 284 +}; + +static const int32_t const QRoundingFactors[QINDEX_RANGE] = { + 56, 56, 56, 56, 56, 56, 56, 56, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48 +}; + +static const int32_t const QZbinFactors[QINDEX_RANGE] = { + 64, 64, 64, 64, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80 +}; + +static const int32_t ZbinBoost[16] = { + 0, 0, 8, 10, 12, 14, 16, 20, 24, 28, + 32, 36, 40, 44, 44, 44 +}; + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.c b/libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.c new file mode 100644 index 0000000..1eeb845 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.c @@ -0,0 +1,673 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ +#include "vp8ratecontrol.h" + +#include <memory.h> + +#include "vp8quanttable.h" +#include "libvpu/rk_vepu_debug.h" + +#define DIV(a, b) (((a) + (SIGN(a) * (b)) / 2) / (b)) +#define DSCY 64 /* n * 64 */ +#define I32_MAX 2147483647 /* 2 ^ 31 - 1 */ +#define QP_DELTA 4 +#define RC_ERROR_RESET 0x7fffffff + +static int32_t InitialQp(int32_t bits, int32_t pels); +static void PicSkip(vp8RateControl_s* rc); +static void PicQuantLimit(vp8RateControl_s* rc); +static int32_t VirtualBuffer(vp8VirtualBuffer_s* vb, int32_t timeInc); +static void PicQuant(vp8RateControl_s* rc); +static int32_t avg_rc_error(linReg_s* p); +static void update_rc_error(linReg_s* p, int32_t bits); +static int32_t gop_avg_qp(vp8RateControl_s* rc); +static int32_t new_pic_quant(linReg_s* p, int32_t bits, true_e useQpDeltaLimit); +static void update_tables(linReg_s* p, int32_t qp, int32_t bits); +static void update_model(linReg_s* p); +static int32_t lin_sy(int32_t* qp, int32_t* r, int32_t n); +static int32_t lin_sx(int32_t* qp, int32_t n); +static int32_t lin_sxy(int32_t* qp, int32_t* r, int32_t n); +static int32_t lin_nsxx(int32_t* qp, int32_t n); + +void VP8InitRc(vp8RateControl_s* rc, uint32_t newStream) { + vp8VirtualBuffer_s* vb = &rc->virtualBuffer; + int32_t maxBps; + + if (rc->qpMax >= QINDEX_RANGE) + rc->qpMax = QINDEX_RANGE - 1; + + if (rc->qpMin < 0) + rc->qpMin = 0; + + /* Limit bitrate settings that are way over head. + * Maximum limit is half of the uncompressed YUV bitrate (12bpp). */ + maxBps = rc->mbPerPic * 16 * 16 * 6; /* Max bits per frame */ + maxBps = VP8Calculate(maxBps, rc->outRateNum, rc->outRateDenom); + if (maxBps < 0) + maxBps = I32_MAX; + vb->bitRate = MIN(vb->bitRate, maxBps); + + vb->bitPerPic = VP8Calculate(vb->bitRate, rc->outRateDenom, rc->outRateNum); + + /* QP -1: Initial QP estimation done by RC */ + if (rc->qpHdr == -1) + rc->qpHdr = InitialQp(vb->bitPerPic, rc->mbPerPic * 16 * 16); + + PicQuantLimit(rc); + + VPU_PLG_DBG("InitRc:\n picRc %i\n picSkip %i\n", + rc->picRc, rc->picSkip); + VPU_PLG_DBG(" qpHdr %i\n qpMin,Max %i,%i\n", + rc->qpHdr, rc->qpMin, rc->qpMax); + + VPU_PLG_DBG(" BitRate %i\n BitPerPic %i\n", + vb->bitRate, vb->bitPerPic); + + /* If changing QP/bitrate between frames don't reset GOP RC */ + if (!newStream) + return; + + rc->qpHdrPrev = rc->qpHdr; + rc->fixedQp = rc->qpHdr; + rc->frameCoded = ENCHW_YES; + rc->currFrameIntra = 1; + rc->prevFrameIntra = 0; + rc->frameCnt = 0; + rc->gopQpSum = 0; + rc->gopQpDiv = 0; + rc->targetPicSize = 0; + rc->frameBitCnt = 0; + + memset(&rc->linReg, 0, sizeof(linReg_s)); + rc->linReg.qs[0] = AcQLookup[QINDEX_RANGE - 1]; + rc->linReg.qp_prev = rc->qpHdr; + + vb->gopRem = rc->gopLen; + vb->timeScale = rc->outRateNum; + + update_rc_error(&rc->rError, RC_ERROR_RESET); +} + +/*------------------------------------------------------------------------------ + InitialQp() Returns sequence initial quantization parameter based on the + configured resolution and bitrate. +------------------------------------------------------------------------------*/ +static int32_t InitialQp(int32_t bits, int32_t pels) { + /* Table with resulting average bits/pixel as a function of QP. + * The table is calculated by encoding a set of 4CIF resolution video + * clips with fixed QP. */ + const int32_t qp_tbl[2][12] = { + { 47, 57, 73, 93, 122, 155, 214, 294, 373, 506, 781, 0x7FFFFFFF }, + { 120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10 } }; + const int32_t upscale = 8000; + int32_t i = -1; + + /* prevents overflow, QP would anyway be 10 with this high bitrate + for all resolutions under and including 1920x1088 */ + if (bits > 1000000) + return 10; + + /* Make room for multiplication */ + pels >>= 8; + bits >>= 5; + + /* Adjust the bits value for the current resolution */ + bits *= pels + 250; + ASSERT(pels > 0); + ASSERT(bits > 0); + bits /= 350 + (3 * pels) / 4; + bits = VP8Calculate(bits, upscale, pels << 6); + + while (qp_tbl[0][++i] < bits); + + VPU_PLG_DBG("BPP %d\n", bits); + + return qp_tbl[1][i]; +} + +/*------------------------------------------------------------------------------ + VirtualBuffer() Return difference of target and real buffer fullness. + Virtual buffer and real bit count grow until one second. After one second + output bit rate per second is removed from virtualBitCnt and realBitCnt. Bit + drifting has been taken care. + + If the leaky bucket in VBR mode becomes empty (e.g. underflow), those R * T_e + bits are lost and must be decremented from virtualBitCnt. (NOTE: Drift + calculation will mess virtualBitCnt up, so the loss is added to realBitCnt) +------------------------------------------------------------------------------*/ +static int32_t VirtualBuffer(vp8VirtualBuffer_s* vb, int32_t timeInc) { + int32_t drift, target; + + /* Saturate realBitCnt, this is to prevent overflows caused by much greater + bitrate setting than is really possible to reach */ + if (vb->realBitCnt > 0x1FFFFFFF) + vb->realBitCnt = 0x1FFFFFFF; + if (vb->realBitCnt < -0x1FFFFFFF) + vb->realBitCnt = -0x1FFFFFFF; + + vb->picTimeInc += timeInc; + vb->virtualBitCnt += VP8Calculate(vb->bitRate, timeInc, vb->timeScale); + target = vb->virtualBitCnt - vb->realBitCnt; + + /* Saturate target, prevents rc going totally out of control. + This situation should never happen. */ + if (target > 0x1FFFFFFF) + target = 0x1FFFFFFF; + if (target < -0x1FFFFFFF) + target = -0x1FFFFFFF; + + /* picTimeInc must be in range of [0, timeScale) */ + while (vb->picTimeInc >= vb->timeScale) { + vb->picTimeInc -= vb->timeScale; + vb->virtualBitCnt -= vb->bitRate; + vb->realBitCnt -= vb->bitRate; + } + drift = VP8Calculate(vb->bitRate, vb->picTimeInc, vb->timeScale); + drift -= vb->virtualBitCnt; + vb->virtualBitCnt += drift; + + VPU_PLG_DBG("virtualBitCnt: %7i\nrealBitCnt: %7i", + vb->virtualBitCnt, vb->realBitCnt); + VPU_PLG_DBG(" diff bits: %7i\n", target); + + return target; +} + +/*------------------------------------------------------------------------------ + VP8BeforePicRc() Update virtual buffer and calculate picInitQp for current + picture. +------------------------------------------------------------------------------*/ +void VP8BeforePicRc(vp8RateControl_s* rc, uint32_t timeInc, + uint32_t frameTypeIntra) { + vp8VirtualBuffer_s* vb = &rc->virtualBuffer; + int32_t brDiff = 0; + + rc->frameCoded = ENCHW_YES; + rc->currFrameIntra = frameTypeIntra; + + VPU_PLG_DBG("BEFORE PIC RC: pic=%d\n", rc->frameCnt); + VPU_PLG_DBG("Frame type: %7i timeInc: %7i\n", frameTypeIntra, timeInc); + + if (rc->currFrameIntra || vb->gopRem == 1) { + vb->gopRem = rc->gopLen; + } else { + vb->gopRem--; + } + + /* Use virtual buffer to calculate the difference of target bitrate + * and actual bitrate */ + brDiff = VirtualBuffer(&rc->virtualBuffer, (int32_t)timeInc); + + /* Calculate target size for this picture */ + rc->targetPicSize = + vb->bitPerPic + DIV(brDiff, MAX(rc->virtualBuffer.gopRem, 3)); + rc->targetPicSize = MAX(0, rc->targetPicSize); + + if (rc->picSkip) + PicSkip(rc); + + /* determine initial quantization parameter for current picture */ + PicQuant(rc); + /* quantization parameter user defined limitations */ + PicQuantLimit(rc); + /* Store the start QP, before any adjustment */ + rc->qpHdrPrev = rc->qpHdr; + + if (rc->currFrameIntra) { + if (rc->fixedIntraQp) + rc->qpHdr = rc->fixedIntraQp; + else if (!rc->prevFrameIntra) + rc->qpHdr += rc->intraQpDelta; + + /* quantization parameter user defined limitations still apply */ + PicQuantLimit(rc); + } else { + /* trace the QP over GOP, excluding Intra QP */ + rc->gopQpSum += rc->qpHdr; + rc->gopQpDiv++; + } + + VPU_PLG_DBG("Frame coded %7d ", rc->frameCoded); + VPU_PLG_DBG("Frame qpHdr %7d ", rc->qpHdr); + VPU_PLG_DBG("GopRem: %7d ", vb->gopRem); + VPU_PLG_DBG("Target bits: %7d \n", rc->targetPicSize); + VPU_PLG_DBG("Rd: %7d\n", avg_rc_error(&rc->rError)); +} + +/*---------------------------------------------------------------------------- + VP8AfterPicRc() Update RC statistics after encoding frame. +-----------------------------------------------------------------------------*/ +void VP8AfterPicRc(vp8RateControl_s* rc, uint32_t byteCnt) { + vp8VirtualBuffer_s* vb = &rc->virtualBuffer; + int32_t bitCnt = (int32_t)byteCnt * 8; + + rc->frameCnt++; + rc->frameBitCnt = bitCnt; + rc->prevFrameIntra = rc->currFrameIntra; + vb->realBitCnt += bitCnt; + + VPU_PLG_DBG("AfterPicRc:\n"); + VPU_PLG_DBG("BitCnt %7d\n", bitCnt); + VPU_PLG_DBG("BitErr/avg %6d%% ", + ((bitCnt - vb->bitPerPic) * 100) / (vb->bitPerPic + 1)); + VPU_PLG_DBG("BitErr/target %6d%%\n", + rc->targetPicSize ? + (((bitCnt - rc->targetPicSize) * 100) / rc->targetPicSize) : -1); + + /* Needs number of bits used for residual */ + if ((!rc->currFrameIntra) || (rc->gopLen == 1)) { + update_tables(&rc->linReg, rc->qpHdrPrev, + VP8Calculate(bitCnt, 256, rc->mbPerPic)); + + if (vb->gopRem == rc->gopLen - 1) { + /* First INTER frame of GOP */ + update_rc_error(&rc->rError, RC_ERROR_RESET); + VPU_PLG_DBG("P --- I --- D ---\n"); + } else { + /* Store the error between target and actual frame size + * Saturate the error to avoid inter frames with + * mostly intra MBs to affect too much */ + update_rc_error(&rc->rError, + MIN(bitCnt - rc->targetPicSize, 2 * rc->targetPicSize)); + } + + update_model(&rc->linReg); + } else { + VPU_PLG_DBG("P xxx I xxx D xxx\n"); + } + +} + +/*---------------------------------------------------------------------------- + PicSkip() Decrease framerate if not enough bits available. +-----------------------------------------------------------------------------*/ +void PicSkip(vp8RateControl_s* rc) { + vp8VirtualBuffer_s* vb = &rc->virtualBuffer; + int32_t bitAvailable = vb->virtualBitCnt - vb->realBitCnt; + int32_t skipIncLimit = -vb->bitPerPic / 3; + int32_t skipDecLimit = vb->bitPerPic / 3; + + /* When frameRc is enabled, skipFrameTarget is not allowed to be > 1 + * This makes sure that not too many frames is skipped and lets + * the frameRc adjust QP instead of skipping many frames */ + if (((rc->picRc == ENCHW_NO) || (vb->skipFrameTarget == 0)) && + (bitAvailable < skipIncLimit)) + vb->skipFrameTarget++; + + if ((bitAvailable > skipDecLimit) && vb->skipFrameTarget > 0) + vb->skipFrameTarget--; + + if (vb->skippedFrames < vb->skipFrameTarget) { + vb->skippedFrames++; + rc->frameCoded = ENCHW_NO; + } else { + vb->skippedFrames = 0; + } +} + +/*---------------------------------------------------------------------------- + PicQuant() Calculate quantization parameter for next frame. In the beginning + of GOP use previous GOP average QP and otherwise find new QP + using the target size and previous frames QPs and bit counts. +-----------------------------------------------------------------------------*/ +void PicQuant(vp8RateControl_s* rc) { + int32_t qp = 0; + int32_t avgRcError, bits; + true_e useQpDeltaLimit = ENCHW_YES; + + if (rc->picRc != ENCHW_YES) { + rc->qpHdr = rc->fixedQp; + VPU_PLG_DBG("R/cx: xxxx QP: xx xx D: xxxx newQP: xx\n"); + return; + } + + /* Determine initial quantization parameter for current picture */ + if (rc->currFrameIntra) { + /* If all frames or every other frame is intra we calculate new QP + * for intra the same way as for inter */ + if (rc->gopLen == 1 || rc->gopLen == 2) { + qp = new_pic_quant(&rc->linReg, + VP8Calculate(rc->targetPicSize, 256, rc->mbPerPic), + useQpDeltaLimit); + } else { + VPU_PLG_DBG("R/cx: xxxx QP: xx xx D: xxxx newQP: xx\n"); + qp = gop_avg_qp(rc); + } + if (qp) { + rc->qpHdr = qp; + } + } else if (rc->prevFrameIntra) { + /* Previous frame was intra, use the same QP */ + VPU_PLG_DBG("R/cx: xxxx QP: == == D: ==== newQP: ==\n"); + rc->qpHdr = rc->qpHdrPrev; + } else { + /* Calculate new QP by matching to previous frames R-Q curve */ + avgRcError = avg_rc_error(&rc->rError); + bits = VP8Calculate(rc->targetPicSize - avgRcError, 256, rc->mbPerPic); + rc->qpHdr = new_pic_quant(&rc->linReg, bits, useQpDeltaLimit); + } +} + +/*---------------------------------------------------------------------------- + PicQuantLimit() +-----------------------------------------------------------------------------*/ +void PicQuantLimit(vp8RateControl_s* rc) { + rc->qpHdr = MIN(rc->qpMax, MAX(rc->qpMin, rc->qpHdr)); +} + +/*------------------------------------------------------------------------------ + Calculate() I try to avoid overflow and calculate good enough result of a*b/c +------------------------------------------------------------------------------*/ +int32_t VP8Calculate(int32_t a, int32_t b, int32_t c) { + uint32_t left = 32; + uint32_t right = 0; + uint32_t shift; + int32_t sign = 1; + int32_t tmp; + uint32_t utmp; + + if (a == 0 || b == 0) { + return 0; + } else if ((a * b / b) == a && c != 0) { + return (a * b / c); + } + if (a < 0) { + sign = -1; + a = -a; + } + if (b < 0) { + sign *= -1; + b = -b; + } + if (c < 0) { + sign *= -1; + c = -c; + } + + if (c == 0) { + return 0x7FFFFFFF * sign; + } + + if (b > a) { + tmp = b; + b = a; + a = tmp; + } + + for (--left; (((uint32_t)a << left) >> left) != (uint32_t)a; --left) ; + left--; /* unsigned values have one more bit on left, + we want signed accuracy. shifting signed values gives + lint warnings */ + + while (((uint32_t)b >> right) > (uint32_t)c) { + right++; + } + + if (right > left) { + return 0x7FFFFFFF * sign; + } else { + shift = left - right; + utmp = (((uint32_t)a << shift) / (uint32_t)c * (uint32_t)b); + utmp = (utmp >> shift) * sign; + return (int32_t)utmp; + } +} + +/*------------------------------------------------------------------------------ + avg_rc_error() PI(D)-control for rate prediction error. +------------------------------------------------------------------------------*/ +static int32_t avg_rc_error(linReg_s* p) { + return DIV(p->bits[2] * 4 + p->bits[1] * 6 + p->bits[0] * 0, 100); +} + +/*------------------------------------------------------------------------------ + update_rc_error() Update PI(D)-control values +------------------------------------------------------------------------------*/ +static void update_rc_error(linReg_s* p, int32_t bits) { + p->len = 3; + + if (bits == (int32_t)RC_ERROR_RESET) { + /* RESET */ + p->bits[0] = 0; + p->bits[1] = 0; + p->bits[2] = 0; + return; + } + p->bits[0] = bits - p->bits[2]; /* Derivative */ + p->bits[1] = bits + p->bits[1]; /* Integral */ + p->bits[2] = bits; /* Proportional */ + + VPU_PLG_DBG("P %7d I %7d D %7d\n", p->bits[2], p->bits[1], p->bits[0]); +} + +/*------------------------------------------------------------------------------ + gop_avg_qp() Average quantization parameter of P frames of the previous GOP. +------------------------------------------------------------------------------*/ +int32_t gop_avg_qp(vp8RateControl_s* rc) { + int32_t avgQp = 0; + + if (rc->gopQpSum) { + avgQp = DIV(rc->gopQpSum, rc->gopQpDiv); + } + rc->gopQpSum = 0; + rc->gopQpDiv = 0; + + return avgQp; +} + +/*------------------------------------------------------------------------------ + new_pic_quant() Calculate new quantization parameter from the 2nd degree R-Q + equation. Further adjust Qp for "smoother" visual quality. +------------------------------------------------------------------------------*/ +static int32_t new_pic_quant(linReg_s* p, int32_t bits, true_e useQpDeltaLimit) { + int32_t tmp, qp_best = p->qp_prev, qp = p->qp_prev, diff; + int32_t diff_prev = 0, qp_prev = 0, diff_best = 0x7FFFFFFF; + + VPU_PLG_DBG("R/cx: %7d ",bits); + + if (p->a1 == 0 && p->a2 == 0) { + VPU_PLG_DBG(" QP: xx xx D: ==== newQP: %2d\n", qp); + return qp; + } + + /* Target bits is negative => increase QP by maximum allowed */ + if (bits <= 0) { + if (useQpDeltaLimit) + qp = MIN(QINDEX_RANGE - 1, MAX(0, qp + QP_DELTA)); + else + qp = MIN(QINDEX_RANGE - 1, MAX(0, qp + 10)); + + VPU_PLG_DBG(" QP: xx xx D: ---- newQP: %2d\n", qp); + return qp; + } + + /* Find the qp that has the best match on fitted curve */ + do { + tmp = DIV(p->a1, AcQLookup[qp]); + tmp += DIV(p->a2, AcQLookup[qp] * AcQLookup[qp]); + diff = ABS(tmp - bits); + + if (diff < diff_best) { + if (diff_best == 0x7FFFFFFF) { + diff_prev = diff; + qp_prev = qp; + } else { + diff_prev = diff_best; + qp_prev = qp_best; + } + diff_best = diff; + qp_best = qp; + if ((tmp - bits) <= 0) { + if (qp < 1) { + break; + } + qp--; + } else { + if (qp >= QINDEX_RANGE - 1) { + break; + } + qp++; + } + } else { + break; + } + } while ((qp >= 0) && (qp < QINDEX_RANGE)); + qp = qp_best; + + VPU_PLG_DBG(" QP: %2d %2d D: %7d", qp, qp_prev, diff_prev - diff_best); + + /* Limit Qp change for smoother visual quality */ + if (useQpDeltaLimit) { + tmp = qp - p->qp_prev; + if (tmp > QP_DELTA) { + qp = p->qp_prev + QP_DELTA; + } else if (tmp < -QP_DELTA) { + qp = p->qp_prev - QP_DELTA; + } + } + + return qp; +} + +/*------------------------------------------------------------------------------ + update_tables() only statistics of PSLICE, please. +------------------------------------------------------------------------------*/ +static void update_tables(linReg_s* p, int32_t qp, int32_t bits) { + const int32_t clen = 10; + int32_t tmp = p->pos; + + p->qp_prev = qp; + p->qs[tmp] = AcQLookup[qp]; + p->bits[tmp] = bits; + + if (++p->pos >= clen) { + p->pos = 0; + } + if (p->len < clen) { + p->len++; + } +} + +/*------------------------------------------------------------------------------ + update_model() Update model parameter by Linear Regression. +------------------------------------------------------------------------------*/ +static void update_model(linReg_s* p) { + int32_t* qs = p->qs, *r = p->bits, n = p->len; + int32_t i, a1, a2, sx = lin_sx(qs, n), sy = lin_sy(qs, r, n); + + for (i = 0; i < n; i++) { + VPU_PLG_DBG("model: qs: %i r: %i\n",qs[i], r[i]); + } + + a1 = lin_sxy(qs, r, n); + a1 = a1 < I32_MAX / n ? a1 * n : I32_MAX; + + VPU_PLG_DBG("model: sy: %i sx: %i\n", sy, sx); + if (sy == 0) { + a1 = 0; + } else { + a1 -= (sx < I32_MAX / sy) ? sx * sy : I32_MAX; + } + + a2 = (lin_nsxx(qs, n) - (sx * sx)); + if (a2 == 0) { + if (p->a1 == 0) { + /* If encountered in the beginning */ + a1 = 0; + } else { + a1 = (p->a1 * 2) / 3; + } + } else { + a1 = VP8Calculate(a1, DSCY, a2); + } + + /* Value of a1 shouldn't be excessive (small) */ + a1 = MAX(a1, -4096 * DSCY); + a1 = MIN(a1, 4096 * DSCY - 1); + + ASSERT(ABS(a1) * sx >= 0); + ASSERT(sx * DSCY >= 0); + a2 = DIV(sy * DSCY, n) - DIV(a1 * sx, n); + + VPU_PLG_DBG("model: a2:%9d a1:%8d\n", a2, a1); + + if (p->len > 0) { + p->a1 = a1; + p->a2 = a2; + } +} + +/*------------------------------------------------------------------------------ + lin_sy() calculate value of Sy for n points. +------------------------------------------------------------------------------*/ +static int32_t lin_sy(int32_t* qp, int32_t* r, int32_t n) { + int32_t sum = 0; + + while (n--) { + sum += qp[n] * qp[n] * r[n]; + if (sum < 0) { + return I32_MAX / DSCY; + } + } + return DIV(sum, DSCY); +} + +/*------------------------------------------------------------------------------ + lin_sx() calculate value of Sx for n points. +------------------------------------------------------------------------------*/ +static int32_t lin_sx(int32_t* qp, int32_t n) { + int32_t tmp = 0; + + while (n--) { + ASSERT(qp[n]); + tmp += qp[n]; + } + return tmp; +} + +/*------------------------------------------------------------------------------ + lin_sxy() calculate value of Sxy for n points. +------------------------------------------------------------------------------*/ +static int32_t lin_sxy(int32_t* qp, int32_t* r, int32_t n) { + int32_t tmp, sum = 0; + + while (n--) { + tmp = qp[n] * qp[n] * qp[n]; + if (tmp > r[n]) { + sum += DIV(tmp, DSCY) * r[n]; + } else { + sum += tmp * DIV(r[n], DSCY); + } + if (sum < 0) { + return I32_MAX; + } + } + return sum; +} + +/*------------------------------------------------------------------------------ + lin_nsxx() calculate value of n * Sxy for n points. +------------------------------------------------------------------------------*/ +static int32_t lin_nsxx(int32_t* qp, int32_t n) { + int32_t tmp = 0, sum = 0, d = n; + + while (n--) { + tmp = qp[n]; + tmp *= tmp; + sum += d * tmp; + } + return sum; +} diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.h b/libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.h new file mode 100644 index 0000000..27ca812 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8ratecontrol.h @@ -0,0 +1,95 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ +#ifndef VP8_RATE_CONTROL_H +#define VP8_RATE_CONTROL_H + +#include <stdint.h> + +#include "enccommon.h" + +typedef struct { + int32_t a1; /* model parameter */ + int32_t a2; /* model parameter */ + int32_t qp_prev; /* previous QP */ + int32_t qs[15]; /* quantization step size */ + int32_t bits[15]; /* Number of bits needed to code residual */ + int32_t pos; /* current position */ + int32_t len; /* current lenght */ + int32_t zero_div; /* a1 divisor is 0 */ +} linReg_s; + +/* Virtual buffer */ +typedef struct +{ + int32_t bufferSize; /* size of the virtual buffer */ + int32_t bitRate; /* input bit rate per second */ + int32_t bitPerPic; /* average number of bits per picture */ + int32_t picTimeInc; /* timeInc since last coded picture */ + int32_t timeScale; /* input frame rate numerator */ + int32_t unitsInTic; /* input frame rate denominator */ + int32_t virtualBitCnt; /* virtual (channel) bit count */ + int32_t realBitCnt; /* real bit count */ + int32_t bufferOccupancy; /* number of bits in the buffer */ + int32_t skipFrameTarget; /* how many frames should be skipped in a row */ + int32_t skippedFrames; /* how many frames have been skipped in a row */ + int32_t bucketFullness; /* Leaky Bucket fullness */ + int32_t gopRem; /* Number of frames remaining in this GOP */ +} vp8VirtualBuffer_s; + +typedef struct +{ + true_e picRc; + true_e picSkip; /* Frame Skip enable */ + true_e frameCoded; /* Frame coded or not */ + int32_t mbPerPic; /* Number of macroblock per picture */ + int32_t mbRows; /* MB rows in picture */ + int32_t currFrameIntra; /* Is current frame intra frame? */ + int32_t prevFrameIntra; /* Was previous frame intra frame? */ + int32_t fixedQp; /* Pic header qp when fixed */ + int32_t qpHdr; /* Pic header qp of current voded picture */ + int32_t qpMin; /* Pic header minimum qp, user set */ + int32_t qpMax; /* Pic header maximum qp, user set */ + int32_t qpHdrPrev; /* Pic header qp of previous coded picture */ + int32_t outRateNum; + int32_t outRateDenom; + vp8VirtualBuffer_s virtualBuffer; + /* for frame QP rate control */ + linReg_s linReg; /* Data for R-Q model */ + linReg_s rError; /* Rate prediction error (bits) */ + int32_t targetPicSize; + int32_t frameBitCnt; + /* for GOP rate control */ + int32_t gopQpSum; + int32_t gopQpDiv; + int32_t frameCnt; + int32_t gopLen; + int32_t intraQpDelta; + int32_t fixedIntraQp; + int32_t mbQpAdjustment; /* QP delta for MAD macroblock QP adjustment */ + int32_t intraPictureRate; + int32_t goldenPictureRate; + int32_t altrefPictureRate; +} vp8RateControl_s; + +/*------------------------------------------------------------------------------ + Function prototypes +------------------------------------------------------------------------------*/ +void VP8InitRc(vp8RateControl_s* rc, uint32_t newStream); +void VP8BeforePicRc(vp8RateControl_s* rc, uint32_t timeInc, uint32_t frameTypeIntra); +void VP8AfterPicRc(vp8RateControl_s* rc, uint32_t byteCnt); +int32_t VP8Calculate(int32_t a, int32_t b, int32_t c); +#endif /* VP8_RATE_CONTROL_H */ + diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8seqparameterset.h b/libv4l-rockchip/libvpu/vp8_enc/vp8seqparameterset.h new file mode 100644 index 0000000..a53002c --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vp8seqparameterset.h @@ -0,0 +1,53 @@ +/*------------------------------------------------------------------------------ +-- -- +-- This software is confidential and proprietary and may be used -- +-- only as expressly authorized by a licensing agreement from -- +-- -- +-- Hantro Products Oy. -- +-- -- +-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY -- +-- ALL RIGHTS RESERVED -- +-- -- +-- The entire notice above must be reproduced -- +-- on all copies and should not be removed. -- +-- -- +-------------------------------------------------------------------------------- +*/ + +#ifndef _VP8SEQ_PARAMETER_SET_H_ +#define _VP8SEQ_PARAMETER_SET_H_ + +#include <stdbool.h> +#include <stdint.h> + +typedef struct { + int32_t picWidthInMbs; + int32_t picHeightInMbs; + int32_t picWidthInPixel; + int32_t picHeightInPixel; + int32_t horizontalScaling; + int32_t verticalScaling; + int32_t colorType; + int32_t clampType; + int32_t dctPartitions; /* Dct data partitions 0=1, 1=2, 2=4, 3=8 */ + int32_t partitionCnt; /* Abbreviation: 2+(1<<prm->dctPartitions) */ + int32_t profile; + int32_t filterType; + int32_t filterLevel; + int32_t filterSharpness; + int32_t quarterPixelMv; + int32_t splitMv; + int32_t singBias[3]; /* SingBias: 0 = ipf, 1 = grf, 2 = arf */ + + int32_t autoFilterLevel; + int32_t autoFilterSharpness; + bool filterDeltaEnable; + int32_t modeDelta[4]; + int32_t oldModeDelta[4]; + int32_t refDelta[4]; + int32_t oldRefDelta[4]; + + int32_t refreshEntropy; +} sps; + +#endif diff --git a/libv4l-rockchip/libvpu/vp8_enc/vpu_mem.c b/libv4l-rockchip/libvpu/vp8_enc/vpu_mem.c new file mode 100644 index 0000000..eff57dd --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vpu_mem.c @@ -0,0 +1,27 @@ +/* Copyright 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "vpu_mem.h" + +#include <malloc.h> +#include <memory.h> + +#include "libvpu/rk_vepu_debug.h" + +int32_t VPUMallocLinear(VPUMemLinear_t* p, uint32_t size) { + p->vir_addr = (uint32_t*) calloc(1, size); + if (p->vir_addr == NULL) { + VPU_PLG_ERR("Fail to malloc."); + return -1; + } + p->size = size; + p->phy_addr = 0x0; + return 0; +} + +void VPUFreeLinear(VPUMemLinear_t* p) { + free(p->vir_addr); + memset(p, 0, sizeof(VPUMemLinear_t)); +} diff --git a/libv4l-rockchip/libvpu/vp8_enc/vpu_mem.h b/libv4l-rockchip/libvpu/vp8_enc/vpu_mem.h new file mode 100644 index 0000000..40a1e09 --- /dev/null +++ b/libv4l-rockchip/libvpu/vp8_enc/vpu_mem.h @@ -0,0 +1,21 @@ +/* Copyright 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __VPU_MEM_H__ +#define __VPU_MEM_H__ + +#include <stdint.h> + +typedef struct VPUMem { + uint32_t phy_addr; + uint32_t* vir_addr; + uint32_t size; +} VPUMemLinear_t; + +int32_t VPUMallocLinear(VPUMemLinear_t* p, uint32_t size); +void VPUFreeLinear(VPUMemLinear_t* p); + +#endif /* __VPU_MEM_H__ */ + -- GitLab